customCreateSubAgentAiRequest computed hasOpenProject with a bare `parent`
identifier that does not exist in scope (it resolved to the `window.parent`
global), so CRA's no-restricted-globals rule failed `npm run build` on all
three OS jobs of release run 38344881723. Fall back to the parent request in
localAiRequestsCache[parentAiRequestId], mirroring the continue-turn path's
`existing.gameProjectJson`.
Add tests/unit/tier2-restricted-globals.test.mjs: a targeted guard for this
regression class, which `npm test` could not see because it never runs
eslint. Verified red on the pre-fix source (reports 5182:27 / 5182:37, exactly
matching the CI eslint output) and green after the fix.
Refresh the MANIFEST.json pin for CustomAIClient.js (219717 bytes).
Suite: 241/241. Seam gate green. Patched-tree apply verified on a scratch copy.
- Wire client-side asset and resource store search in BYOK mode using listAllPublicAssets and listAllResources
- Add parameter aliasing for add_or_edit_variable (name -> variable_name_or_path, type -> variable_type, default value)
- Normalize put_2d_instances (default layer_name and brush_kind, support direct batch instance placement)
- Implement engine reflection for search_docs via gd.getAllPlatformExtensions()
- Filter initialize_project when project is open and document full gameplay test harness API
- Update MANIFEST.json, patches/14-ai-utils.patch, and expand test suite to 240 tests
- Sanitize machine-local paths for CI hygiene checks
- IPC debug logger bridge:
- Add IPC bridge from launcher/preload-unlock.cjs to launcher/heretek-hook.cjs via 'heretek:debug-log'
- Support customSource in launcher/debug-logger.cjs to record renderer events (source: 'renderer') directly to JSONL disk logs
- Prevent losing renderer errors, warnings, and turn events previously buffered only in-memory
- AI Agent request & telemetry capture:
- Instrument sendChatCompletion in packages/ai-studio/AI/CustomAIClient.js to emit ai-request-sent, ai-response-received, and ai-request-error
- Record endpointUrl, model, prompt messages, tools, durationMs, and provider token usage
- Instrument LoopGuard.js with [TOOL_CALL] and [TOOL_RESULT] carrying callId, arguments, repeat counts, and error counts
- Add safeFormatMessagesForDebug helper for bounded, safe message serialization
- Tool audit & diagnostics:
- Add standalone parser scripts/audit_agent_log.py and comprehensive report AUDIT_AGENT_LOG_REPORT.md auditing 67 agent interaction rows
- Verification & tests:
- Update packages/ai-studio/MANIFEST.json sha256 checksums and byte counts
- Add unit tests in tests/launcher/debug-logger.test.cjs covering IPC event forwarding and disk serialization
- Full test suite passes: 237/237 passing (+2 new tests)
- CustomAIClient: search_docs/read_full_docs offline suffix + OFFLINE_DOCS helpers
- Patch 14: local pre-pass for docs (offline:true, no network) + create_or_update_plan via PlanStore validate/merge
- Tests: 3 new assertions in ai-byok-flow.test.mjs proving no dead tool calls
- MANIFEST: recompute CustomAIClient hash/bytes
- LICENSE (MIT, Heretek-AI 2026) with scope note: covers this repo's
original files; upstream GDevelop (Core/GDJS/newIDE/Extensions) stays
under its own MIT licenses, never vendored (closes#26).
- package.json: add "license": "MIT".
- docs/sonar-triage.md: SonarCloud advisory-only, no properties file
added (default-branch effect only); 6 MAJOR residuals documented as
accepted/owner-UI-action (closes SonarCloud box of #14).
- npm test 131/131 green.
- Hygiene calls the org workflow that rejects machine-local paths.
- CodeRabbit skips patches/, which tests/patches/ already pins.
- CLAUDE_CODE_RESEARCH_PROMPT.md named five absolute paths under one
developer's home directory; they are now repo-relative.
No patch, launcher, pinned runtime or test file is touched.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Raised in review:
- A run-wide SHA256SUMS.txt went stale as soon as one OS was published
into an existing release. Each build job now writes SHA256SUMS-<os>.txt
for exactly the files it uploads; the publish job re-verifies them.
- Workflows that run repository code no longer leave the checkout token
on disk, and seam-tests/e2e get an explicit read-only token.
- docs/release-signing.md claimed signing needed no workflow change. For
macOS that is wrong: the ad-hoc step would replace a Developer ID
signature. Corrected.
- AUDIT_REPORT.md: say up front that it is append-only and §9 is current.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Two holes raised in review, each now with a negative control:
- an endpoint route could lose its local-* user branch and still pass;
sites that take a userId must now carry both conditions.
- discovery was by declaration shape, so a hosted request in a function
declaration or method would have gone unclassified. Every hosted
request must now sit inside a classified call site.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
open() re-initializes an XHR, but the per-instance shadows from a spoofed
response stayed and a later real request would read back the old 200.
Remove them on open(). Raised in review; red test first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
CodeQL flagged a check-then-write race (js/file-system-race) on the build
config: existsSync, then read and write by path. Open the file once and
read, truncate and write through that descriptor. Same edit, same exit
codes (2 missing, 1 refused).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Upstream added chat attachments after the fork diverged, so the forward-
ported Generation.js had no BYOK branch for them: with a custom endpoint
enabled, a logged-in user's attachment was still uploaded to GDevelop's
storage (logged out, the UI already refuses before uploading).
- createAiAttachmentUploads throws before any hosted call when the custom
endpoint is enabled or the user is local-* — the same rule the presigned
project-JSON upload already uses. The caller turns it into the existing
'upload failed' chip.
- createAiAttachmentDownloads returns not-found entries for a local-* user.
Attachments of a hosted chat are hosted data and are still read there.
Patch 07 was re-derived, not hand-edited: a plain diff -U3 of pristine vs
patched reproduces the previous patch byte-for-byte, and the new one
differs from it only by these two insertions (minus-line count unchanged
at 66). The contract test asserted the gap; it now asserts the guards
(red before, green after). REBASE.md records these as post-fork additions
and switches the rebase recipe to use our own patched file as the third
side, since the donor is retired.
Not verified live: reaching the guard needs a logged-in session.
Co-Authored-By: Claude Opus 5.5 <[email protected]>