Babel keeps value-form named imports of Flow types (GLTF from
three/examples/jsm/loaders/GLTFLoader; User/Auth from firebase/auth),
and react-scripts sets strictExportPresence, so the dev server failed
to compile with 7 'export not found' errors (also present on upstream
master, which no CI job catches since nothing builds the editor
bundle).
Use inline 'type' qualifiers (existing repo convention) and record the
4 newly divergent upstream-owned paths in fork-divergence.json.
Two problems made this fork expensive to maintain: scanner noise nobody
could act on, and divergence from upstream that nothing tracked.
Code scanning reported 3,518 open alerts. 3,449 were fallow findings and
2,399 of those sat in vendored bundles `.fallow.toml` never listed
(jolt-physics.wasm.js 436, box2djs/box2d.js 328, the Firebase SDK 655,
Recast, PeerJS, draco). Listing them plus raising the CRAP thresholds from
the defaults to evidence-based values takes fallow from 3,449 findings to
155, all in maintained code. The remaining 69 were CodeQL: 8 third-party
actions are now pinned to full commit SHAs with `# vN` comments (so
Dependabot keeps updating them) and all 10 workflows declare an explicit
least-privilege `permissions:` block.
SonarCloud's 2,845 open issues are mostly not this fork's code — 2,526 sit
in files byte-identical to upstream. The real defect was configuration:
~200 lines of `sonar.issue.ignore.multicriteria.e1..e88` in
.sonarcloud.properties, plus scripts/sonarcloud-apply-suppressions.sh, were
inert. That key is a Project Settings UI setting and cannot be read from
that file under automatic analysis, so two phases of remediation work
chased config the server never saw. Both are deleted; the exclusions that
do work are kept and extended. `sonar.test.inclusions` no longer declares
production source directories as test inclusions.
Divergence is now bounded and checked. `fork-divergence.json` is a
checked-in allowlist of the 111 modified, 51 fork-only and 7
upstream-missing paths, and `scripts/check-fork-divergence.js` fails CI on
divergence that is not listed or on stale entries. It reads upstream
through the GitHub trees API because 4ian/GDevelop is ~1.7GB and this runs
on every PR. Restoring Extensions/Physics3DBehavior/tests/
Physics3DRuntimeBehavior.spec.js — deleted by an earlier SonarCloud pass to
silence one rule — removes one entry each.
Repairs found along the way: every `// nosonar` marker sat on the line
before the statement SonarCloud flags, where the directive does nothing;
each is now on the exact reported line. Four garbled comment fragments left
in multiplayertools.ts by the same pass are gone. A two-line re-export shim
with no importers (AiGeneration/CustomAIClient.js) is deleted.
`scripts/sonarcloud-drift.js` now writes its outputs to $GITHUB_OUTPUT and
seeds its own baseline, so the weekly drift job's ceiling can actually fire;
it previously ran behind `continue-on-error` against a threshold that
predated the exclusions and was unreachable.
Root documentation collapses to MAINTENANCE.md. The three SonarCloud phase
plans and the Dependabot plan described steps that were proven impossible
and are deleted; AI_GAME_STUDIO_ASSESSMENT.md is a design record and stays.
Verified: newIDE/app 176/176 suites and 1,922 tests pass; GDevelop.js 33/33
suites and 1,177 tests pass; GDJS Karma 1,287 pass with the same 9
pre-existing failures (Firebase network tests) reproduced on a pristine
tree. check-format lists 37 files against the documented 41-file baseline,
so no new violations. Lockfile, drift and divergence guards all exit 0.
create_or_update_plan omits `dependsOn` when the caller did not send it
(08a49e2f5, W11), but the spec still expected it normalized to []. Lock
in both cases instead: omitted stays absent, provided is kept and
trimmed. This is the failure blocking PR #148 CI; the spec was stale on
master itself.
Closes the verification gap tracked in #146 for 08a49e2f5.
- Upgrade GDJS/tests karma stack (karma 6.4.4, karma-mocha 2,
karma-chrome-launcher 3): the socket.io-parser ^4.2.7 override from
186ae04ac forces socket.io 4.x, which is incompatible with karma 1.7
("SocketIO is not a constructor"). Supersedes #110.
- Guard process.env in FirebaseExtension.spec.js: uncaught
ReferenceError in the browser aborts karma 6 runs.
- Fix stale tilemap culling test: 08a49e2f5 deliberately made nested
tile maps draw in full (no wrong-window culling); the test still
asserted the pre-remediation behavior.
- Add Model3DObjectConfiguration.spec.js: useInstancing set to true
round-trips through C++ serialization; false default preserved.
Verified on Node 20.20.2 / Chrome Headless 153:
GDJS/tests 1287/1296 passed (3DCulling, Model3DInstancing and
tilemapCulling green; remaining failures are Firebase e2e without a
valid GD_TEST_FIREBASE_API_KEY and 1-ulp float-equality flakes in
untouched files). GDevelop.js Jest: 33/33 suites, 1177 passed.
16-reviewer audit of ae815f489 (103 findings) remediated in six groups.
1. Lazy THREE init (runtimeobject.ts): scratch Box3/Matrix4/Euler allocated on
first use, so a 2D-only export (never loads three.js) boots.
2. Culling correctness: computeAABB uses |size|/2 half-extents and places the box
at the true rotation pivot C' = P + R*(C-P); custom-object children union
conservative boxes; the frustum is rebuilt in the boxes' space (right-multiply
_threeGroup.matrixWorld) with a numeric cache incl. camera-Z; hide/cull route
through setCullingVisible/applyRenderVisibility (no detached-carrier writes);
custom-object children and nested tile maps no longer cull with a wrong window.
3. Studio pipeline wedge (Utils.js + Studio/*): lock release over all calls,
working marks only editor calls, spawn failures reach the model, plan merge on
objects (JSON.parse bug), one persistent LoopGuard with real call_id +
re-arming + recordSuccess, RequestWriteGate self-retry + supersede-rejects,
UseStudioRuntime fire-and-forget gate write + recomputed plan + sent check,
FinalizeSubAgents terminal-'error' + executed-but-unsent + turn-cap + enriched
report, send-returns-boolean, BYOK cache write-through, suspension cascade,
turn-cap dispatch, stand-alone cannot spawn.
4. Instancing: useInstancing now serializes (C++); the pool grows without null.add
and collapses deleted slots; the instance matrix is normalized
(carrier * correction) and rewritten on rotation/hide; animated/skinned/morph/
multi-mesh models rejected; per-slot shadows; layer moves re-acquire.
5. BYOK role enforcement: studioRoleId persisted and re-applied every turn (tools +
prompt); dispatch filters tools outside the role; readOnly roles skip edit
approval.
6. Warnings + Info: mutating-tool classification, hasOwnProperty role guards,
cache-message merge, spawn arg caps, per-batch GDD note, fan-out cap, plan
dependsOn-omission + caps + duplicate-id + fail-closed + trimmed ids, tilemap
rotated/mirror bail + window margin + null-map guard, pool dispose wired to
unloadScene, schema description required, plus doc/comment corrections.
Verified: engine builds clean; boot + computeAABB (13/13) + Model3DInstancePool
(9/9) harnesses pass; Jest green for src/AiGeneration + src/AI (175), CustomAIClient
(27, incl. the critical second-turn role regression), PlanStore (25),
FinalizeSubAgents (21), LoopGuard (18), RequestWriteGate (11), Roles (9).
Answers the two questions the fork asked, then acts on both.
Assessment (AI_GAME_STUDIO_ASSESSMENT.md): a literal Anno-1800-scale 3D
city builder is not achievable on this engine - no instancing, no 3D
culling, Android is a Cordova WebView around the same HTML5 runtime, and a
15 MB per-resource cloud-build ceiling. A 2D isometric city builder of
Anno-1602/1701 scope is reachable today. The hosted backend already is a
multi-agent company; the BYOK path can reach none of it (no plan tool, no
sub-agent tool, no role prompts, no local spawner, no loop guard).
Studio (phases 2-5, 9-11), all under newIDE/app/src/AiGeneration/Studio/:
* Roles.js - manager/designer/developer/tester: prompts, exact tool
subsets, read-only invariant, turn caps.
* PlanStore.js - create_or_update_plan is real under BYOK and returns the
shape getLatestActivePlan/OrchestratorPlan already read; the dispatcher
merges a new plan over the existing one so a re-plan cannot strip a field
another writer set.
* SpawnSubAgents.js + customCreateSubAgentAiRequest - spawn_agent (the BYOK
tool schema goes 29 -> 39 tools) and a real child AiRequest carrying the
role's prompt and tool subset.
* FinalizeSubAgents.js + UseStudioRuntime.js - a finished child's report is
written onto its parent's function_call_output and the plan task flips.
* RequestWriteGate.js - one gate owns writes to an AiRequest, with named
block reasons and latest-wins per-request serialization.
* LoopGuard.js - a local circuit breaker (repeated identical calls, error
storms, turn count) with a steer -> constrain ladder. Ported from
chaitanyagiri/munder-difflin (MIT) src/main/breaker.ts, incl. its #377
whole-arguments sha256 key; no MD source is vendored.
* One in-flight model turn per request id, and the two in-place mutators
made whole-replace so a concurrent turn cannot discard them.
Engine (phases 6-8):
* 3D culling: gdjs.Object3DCulling shared AABB maths, a per-layer frustum
cache, and a 3D branch in both _updateObjectsPreRender implementations.
Capability-checked, because CustomRuntimeObject3D does not extend
RuntimeObject3D.
* Instancing: opt-in Model3D "Use instancing" property + Model3DInstancePool,
one InstancedMesh per (resource, material, layer) for single non-skinned
meshes; every other model silently keeps the clone path.
* TileMap culling generalised to TileMap (not just SimpleTileMap) and to
tilemaps nested in custom objects, with bounds clamped to the map.
Two bugs found by running the loop end-to-end rather than by tests: the
instance pool was page-global (handing out slots on a discarded scene's
mesh), and buildSubAgentReport read only `output_text` while the local path
emits `text`, so every local sub-agent reported "(no report)".
Synthesize an agent-facing guide for this fork from four independent
read-only surveys of the source tree, test surface, build/config, and
scripts/docs, then verified against the checkout before commit.
Covers the eight required sections plus two additions specific to this
repository:
- Generated-file boundary table (libGD.js, glue.cpp, types.d.ts,
locales/**, theme variables, codemod-frozen JsExtension.js) and the
vendored list, since hand-editing those is the highest-frequency
mistake here.
- Fork Divergence: the three concentrated upstream-conflict zones (BYOK
AI client, client-side unlock switch, auto-updater feed) and the five
BYOK paths the upstream-sync workflow protects by name - renaming or
moving them silently disables the integrity guard.
Also records the measured red baseline on clean master, so a change is
not blamed for it: `cd GDJS && npm run check-format` lists 41 files and
`npm run check-types` reports 322 errors (305 THREE, 17 Spine/pixi).
Neither is gated by the fork's ci.yml, which runs both inside
newIDE/app only.
Verification: all cited paths confirmed present; every documented npm
script confirmed against its package.json; extension counts checked
against Extensions/CMakeLists.txt (48 dirs, 31 JsExtension.js, 17 C++).
The step comment and the user-facing warning both asserted "org policy forces
a read-only GITHUB_TOKEN". That is wrong, and it was steering readers toward
buying a SYNC_PAT they do not need. Replaced with what was actually measured.
Verified by probe against this repo, all as app/github-actions with
secrets.GITHUB_TOKEN:
REST POST /pulls -> OK (created a PR)
gh pr create -> OK (created a PR)
gh pr create on upstream-sync-* -> OK (created a PR)
while the repo reports:
default_workflow_permissions = write
can_approve_pull_request_reviews = true
runtime grant = Contents:write + PullRequests:write
git push with that token = succeeds
SYNC_PAT = not set
So the token can create PRs here; the failure is real but unexplained. The
comment now says so instead of blaming a policy that does not apply.
Failure behaviour is unchanged: the run still degrades to a compare URL
rather than failing. Only the explanation changed.
Probe results (all from this repo, token = secrets.GITHUB_TOKEN, actor
app/github-actions):
REST POST /repos/{o}/{r}/pulls => OK (PR #142)
GraphQL gh pr create => OK (PR #143)
gh pr create on an existing
upstream-sync-* branch => OK (PRs #144, #145)
So GITHUB_TOKEN CAN create pull requests here, by either API. The recorded
conclusion "org policy forces read-only GITHUB_TOKEN" is wrong:
repo default_workflow_permissions = write
repo can_approve_pull_request_reviews = true
runtime grant = Contents:write, PullRequests:write
git push with the same token = succeeds
SYNC_PAT = not set (verified at runtime)
No SYNC_PAT is needed.
Kept issues:write, which the conflict path genuinely needs for
`gh issue create` and which the workflow never declared.
Also removes the stale in-workflow comment asserting the org-policy claim.
Still open: why `gh pr create` fails inside upstream-sync.yml but succeeds
from an equivalent probe. All probes are deleted; the difference is not the
token, the API, the branch, or the permissions block.
REST, GraphQL, and gh pr create all succeed from a probe with
secrets.GITHUB_TOKEN, but the real sync step still fails with
'GraphQL: Resource not accessible by integration'.
This replicates the exact step: same GH_TOKEN expression, same branch, same
call - then repeats it with the token unset/plain, to isolate whether the
SYNC_PAT expression or the branch name is responsible.
The only permission difference between my successful probe run and the failing
sync run: the probe had Issues:write, the sync workflow did not.
The conflict path calls `gh issue create`, which is why issues:write is needed.
Adding it also restores parity with the probe, which created PRs fine via both
REST and GraphQL using the same GITHUB_TOKEN.
Evidence so far:
- GITHUB_TOKEN CAN create PRs here: REST PR #142 and gh pr create PR #143,
both authored by app/github-actions
- so 'org policy forces read-only GITHUB_TOKEN' is wrong
- the only difference in the failing step is its GH_TOKEN expression:
secrets.SYNC_PAT != '' && secrets.SYNC_PAT || secrets.GITHUB_TOKEN
- repo secret list is empty, but ORG secrets are unreadable to me (403)
If an unreadable org-level SYNC_PAT exists and is empty/invalid, that
expression selects it and PR creation fails while the token itself is fine.
This prints only a boolean, never the value. Remove after the run.
Result: BOTH paths succeed when the step actually runs.
REST POST /pulls => OK (PR #142)
GraphQL gh pr create => OK (PR #143)
So GITHUB_TOKEN CAN create pull requests in this repo, via either API. The
'org policy forces read-only GITHUB_TOKEN' conclusion is definitively wrong.
Narrowing the real difference. My earlier probe used REST
(gh api -X POST /pulls) and succeeded - PR #141 was created. upstream-sync
uses gh pr create, which goes through GraphQL createPullRequest, and fails
with 'Resource not accessible by integration'.
This runs BOTH against this repo in one job and prints results to stdout,
since the step summary is not retrievable through the API.
The probe ran 'gh issue delete' on cleanup, so absence of the issue proves
nothing about whether creation succeeded. Superseded by an end-to-end run of
the real workflow, which is the decisive test.
The PR probe proved GITHUB_TOKEN creates pull requests fine (PR #141,
author app/github-actions), so 'org policy forces read-only' is wrong for PRs.
upstream-sync's CONFLICT path calls gh issue create, not gh pr create, and the
repo's earlier probe tested issue creation. This isolates whether issue
permissions differ from pull-request permissions.
Probe result: GITHUB_TOKEN CAN create pull requests in this repo.
step 2 contents:write push => ok
step 3 REST POST /pulls => ok (created PR #141)
step 4 gh pr create => ok
PR #141 author => app/github-actions
So the recorded conclusion 'org policy forces read-only GITHUB_TOKEN' is
WRONG, and no SYNC_PAT is needed. The upstream-sync failure has a different,
still-unidentified cause.
Settles a misdiagnosis. The recorded conclusion was "org policy forces
read-only GITHUB_TOKEN", but the evidence does not support it:
repo default_workflow_permissions = write
repo can_approve_pull_request_reviews = true
workflow permissions block = contents:write, pull-requests:write
token granted at runtime = Contents:write, PullRequests:write
git push with that same token = SUCCEEDS
Yet `gh pr create` fails with "Resource not accessible by integration
(createPullRequest)". So "read-only" is wrong and the real cause is unknown.
The probe isolates each capability so the failing one is unambiguous:
1. token identity (GET /user) and effective repo permissions
2. contents:write push (control - known to work)
3. REST POST /pulls (the API gh uses underneath)
4. `gh pr create` (the exact command upstream-sync runs)
workflow_dispatch only, so it cannot fire on push. Touches nothing on master:
it pushes a probe/* branch and force-deletes it, plus closes any PR it opened.
Delete this file once the run summary has been read.
The plan document on master is stale: four follow-up doc commits were pushed to
`chore/ci-remediation` after PR #124 had already been squash-merged, so they
never reached master. The branch is about to be deleted, so rescue them here.
What master was missing:
- the corrected `Upload SARIF` analysis. Master still says "three distinct
bugs"; there were **four**. #137's per-run category stamping fixed the
collision, then code scanning rejected the file on content
(`locationFromSarifResult: expected at least one location`) because the
`fallow/dupes` run's 239 results carry no `locations`. #138 dropped them.
- the verified acceptance table (all six criteria, with evidence) in place of
the old unverified numbered list.
- the before/after `Outcome` table.
Only the document is taken. The rest of that branch is stale and would revert
13 merged PRs — e.g. it restores `newIDE/app/patches/wavesurfer.js+7.12.6.patch`
which was deliberately deleted, and reverts `dotenv` to ^18.0.0. Verified the
diff touches no code: `git diff master -- . ':!DEPENDABOT*'` is empty.
Fourth and final failure in this job. #137 fixed the category collision (that
step now succeeds — the log shows "Give each SARIF run a unique category" ✔ and
only `Upload SARIF` failing), but code scanning then rejected the file on
content:
##[error]Code Scanning could not process the submitted SARIF file:
locationFromSarifResult: expected at least one location, ...
Cause: fallow's `fallow/dupes` run reports code duplication as 239 results, and
**none of them carry a `locations` array** — there is no file/line for code
scanning to annotate:
run[0]: results=17 without locations=0
run[1]: results=239 without locations=239 <- fallow/dupes
run[2]: results=400 without locations=0
Code scanning requires at least one location per result, so one bad run fails
the whole upload. Drop those results and the run itself when nothing usable
remains; keep the location-bearing findings.
Also drops the now-redundant `category: fallow` input from #134 — it applies to
the whole upload, not to runs inside the file, so it never addressed the actual
collision.
Verified against real output from the pinned CLI ([email protected].0, 3 runs,
426 KB):
runs: 3 -> 2; dropped 239 location-less result(s);
categories: fallow/run-0, fallow/run-1
unique categories: true; results without locations: 0; results kept: 417
Duplication findings are not lost from the project — they remain in the
`audit` job's summary and the archived fallow.log. They simply cannot be
represented as code-scanning alerts.
Corrects the diagnosis in #134. That PR added `category: fallow` to the upload
step, but `Upload SARIF` still fails on master with the same message:
##[error]The CodeQL Action does not support uploading multiple SARIF runs
with the same category.
The `category:` input applies to the whole upload, not to runs inside the file.
The real cause is in the SARIF fallow produces: it emits THREE runs and two of
them carry no `automationDetails`, so they both fall back to the default
category and collide with each other.
run[0] automationDetails=None
run[1] automationDetails={'id': 'fallow/dupes'}
run[2] automationDetails=None
Code scanning keys analyses on each run's `automationDetails.id`, so the fix is
to stamp a distinct id on every run before uploading.
Verified against real output from the pinned CLI (`[email protected].0`, 426 KB, 3
runs): the step rewrites them to `fallow/run-0`, `fallow/run-1`,
`fallow/run-2` — three unique ids. The absent-file path (the failure mode #124
fixed) exits 0 with a notice rather than crashing, since a scan that produced no
SARIF should not mask the original error.
* Bump dotenv in /newIDE/electron-app/app in the weekly-deps group
Bumps the weekly-deps group in /newIDE/electron-app/app with 1 update: [dotenv](https://github.com/motdotla/dotenv).
Updates `dotenv` from 18.0.0 to 18.0.1
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v18.0.0...v18.0.1)
---
updated-dependencies:
- dependency-name: dotenv
dependency-version: 18.0.1
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: weekly-deps
...
Signed-off-by: dependabot[bot] <[email protected]>
* fix(lockfile): regenerate newIDE/electron-app/app lockfile against master
Dependabot's regeneration for dotenv 18.0.0 -> 18.0.1 dropped hoisted peer dependencies,
leaving the lockfile out of sync with package.json (npm ci hard-fails).
Restored master's lockfile and reapplied the bump; see #136 for the
root cause and evidence.
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: BillyOutlast <[email protected]>
* Bump dotenv in /newIDE/electron-app in the weekly-deps group
Bumps the weekly-deps group in /newIDE/electron-app with 1 update: [dotenv](https://github.com/motdotla/dotenv).
Updates `dotenv` from 18.0.0 to 18.0.1
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v18.0.0...v18.0.1)
---
updated-dependencies:
- dependency-name: dotenv
dependency-version: 18.0.1
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: weekly-deps
...
Signed-off-by: dependabot[bot] <[email protected]>
* fix(lockfile): regenerate newIDE/electron-app lockfile against master
Dependabot's regeneration for dotenv 18.0.0 -> 18.0.1 dropped hoisted peer dependencies,
leaving the lockfile out of sync with package.json (npm ci hard-fails).
Restored master's lockfile and reapplied the bump; see #136 for the
root cause and evidence.
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: BillyOutlast <[email protected]>
* Bump patch-package from 6.5.1 to 8.0.1 in /GDJS
Bumps [patch-package](https://github.com/ds300/patch-package) from 6.5.1 to 8.0.1.
- [Release notes](https://github.com/ds300/patch-package/releases)
- [Changelog](https://github.com/ds300/patch-package/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ds300/patch-package/commits)
---
updated-dependencies:
- dependency-name: patch-package
dependency-version: 8.0.1
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <[email protected]>
* fix(lockfile): regenerate GDJS lockfile against master
Dependabot's regeneration for patch-package 6.5.1 -> 8.0.1 dropped hoisted peer dependencies,
leaving the lockfile out of sync with package.json (npm ci hard-fails).
Restored master's lockfile and reapplied the bump; see #136 for the
root cause and evidence.
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: BillyOutlast <[email protected]>
* Bump @types/node from 26.6.1 to 26.6.2 in /GDJS in the weekly-deps group
Bumps the weekly-deps group in /GDJS with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).
Updates `@types/node` from 26.6.1 to 26.6.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
---
updated-dependencies:
- dependency-name: "@types/node"
dependency-version: 26.6.2
dependency-type: direct:development
update-type: version-update:semver-patch
dependency-group: weekly-deps
...
Signed-off-by: dependabot[bot] <[email protected]>
* fix(lockfile): regenerate GDJS lockfile against master
Dependabot's regeneration for @types/node 26.6.1 -> 26.6.2 dropped hoisted peer dependencies,
leaving the lockfile out of sync with package.json (npm ci hard-fails).
Restored master's lockfile and reapplied the bump; see #136 for the
root cause and evidence.
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: BillyOutlast <[email protected]>
Follow-up to #124. That PR fixed the flag error (`--output` is an alias of
`--format`, so `--format sarif --output fallow.sarif` aborted and no file was
written) — `Run fallow full scan` now succeeds on master and does produce
fallow.sarif. The next step then failed instead:
##[error]The CodeQL Action does not support uploading multiple SARIF runs
with the same category. Please update your workflow to upload a single run
per category.
Code scanning keys analyses by `category`, and with no explicit category this
upload lands in the same default bucket as CodeQL's own run for the same
commit. Setting `category: fallow` keeps the two separable and lets the upload
complete.
Verified against the action's own input schema: `category` is an optional
string used "by Code Scanning for matching the analyses".
* ci: fix fallow SARIF, upstream-sync token dead end, guard coverage; refresh vuln docs
Four independent defects found while reviewing the open Dependabot queue.
fallow.yml
- `--format` and `--output` are the SAME option (`--output` is a documented
alias of `--format`), so `--format sarif --output fallow.sarif` aborted with
"the argument '--format <FORMAT>' cannot be used multiple times" and never
wrote the file. The following `upload-sarif` step then failed with
"Path does not exist: fallow.sarif", reddening `Fallow full scan` on master
and on every PR. Use `--output-file` for the path.
- Pin the CLI to 3.27.0. A bare `npx fallow` resolves the `latest` dist-tag at
run time and was observed returning 3.3.0 on one run and 3.27.0 on another,
so the full scan could silently disagree with the `audit` job (which pins
3.27.0 through the action's `version:` input).
upstream-sync.yml
- Org policy forces a read-only GITHUB_TOKEN and no SYNC_PAT secret exists, so
`gh pr create` can never succeed ("Resource not accessible by integration")
and the run failed with exit 1 every day. The branch is already pushed by
that point, so degrade to a warning plus a ready-to-click compare URL in the
step summary instead of failing.
check-lockfiles.js
- `newIDE/visual-tests/package-lock.json` existed on disk but was absent from
the guard's list (10 lockfiles, 9 guarded). Added.
dependabot.yml
- Drop the `ignore:` block pinning electron to 32.x. Both manifests are now on
the current release line (newIDE/electron-app 44.4.3, GDJS/Runtime/Electron
44.3.0), so the block only suppressed legitimate updates.
- `exclude-patterns` on the newIDE/app weekly group: for 0.x packages a
"minor" bump is breaking by semver convention, so the group silently carried
migrations like three 0.160->0.186 and spine-pixi-v7 4.2->4.3 alongside real
patch bumps. One such group PR grew into a 19-package migration.
- Raise newIDE/app's `open-pull-requests-limit` 5 -> 10; 6 PRs are already
open there, so new ones were being suppressed at the source.
KNOWN_VULNS.md
- Rewritten against the live API and the manifests. The previous revision
claimed the fork stays on electron 32.x with 47 advisories (it is on 44.4.3),
and that all non-electron vulnerabilities were remediated (the API reports
49 open alerts: 22 high, 25 medium, 2 low, across 18 packages).
- Documented two guard gaps: the `tar` floor (`< 6.2.1`) is bypassed by the
guard's same-major rule while advisories cover `<= 7.5.17`, and
newIDE/visual-tests was unguarded.
- Recorded the four no-patch advisories as accepted risk.
DEPENDABOT_PR_REMEDIATION_PLAN.md
- Full review of the 32 open PRs: 6 root causes, all reproduced locally, with
fixes verified before being proposed.
* fix(deps): repair three lockfiles already desynced on master; gate lockfile sync in CI
`npm ci` hard-fails when package.json and package-lock.json disagree, but CI
only installed the directories some later job happened to need. Three lockfiles
had rotted on master without anything noticing:
GDJS 16 missing packages (@pixi/* 7.4.3)
newIDE/electron-app/app 6 missing + 3 invalid (electron 44.4.3, @electron/get)
SharedLibs/TileMapHelper 36 missing + 2 invalid (@webassemblyjs/*, terser)
Each only failed the moment someone tried to install in that directory — which
is how the GDJS one stayed invisible while PR #121 was being reviewed for an
unrelated reason.
Regenerated all three with `npm install --package-lock-only`. All ten manifests
now install clean under `npm ci --dry-run`:
GDevelop.js GDJS GDJS/tests newIDE/app newIDE/electron-app
newIDE/electron-app/app newIDE/web-app newIDE/visual-tests
SharedLibs/TileMapHelper SharedLibs/ThreeAddons -> rc=0, 0 sync errors
Added a `lockfile-sync` matrix job over all ten directories so drift fails on
the PR that causes it. `--ignore-scripts` keeps postinstall hooks
(patch-package, import-resources) out of it — the job only asserts that the
lockfile resolves.
`node scripts/security/check-lockfiles.js` still exits 0.
* fix(deps): bump adm-zip 0.6.0 -> 0.6.1, closing 2 high advisories
`[email protected]` is vulnerable to GHSA-7q85-xj36-vmfc (high, patched in 0.6.1).
It is a *direct* dependency declared as `^0.6.0` in both manifests, so 0.6.1 was
already permitted — the lockfiles were simply pinned at the vulnerable 0.6.0 and
never re-resolved.
Verified the overrides already present in both manifests (`^0.6.0`) are harmless
here: a fresh resolution with or without them yields 0.6.1. Raising the override
to `^0.6.1` is NOT the fix — npm rejects it with EOVERRIDE because the override
would conflict with the direct dependency. Regenerating is the correct fix.
newIDE/app/package-lock.json adm-zip 0.6.0 -> 0.6.1
newIDE/electron-app/package-lock.json adm-zip 0.6.0 -> 0.6.1
Closes 2 of the 22 open high-severity alerts. The remaining `adm-zip` medium
advisory (GHSA-vwc7-r8mq-g2x9) has no patch and stays documented as accepted
risk in KNOWN_VULNS.md.
All ten manifests verified: `npm ci --dry-run` rc=0, 0 sync errors, and
`node scripts/security/check-lockfiles.js` exits 0.
* docs: record execution status for the PR remediation plan
Queue 32 -> 25 open; 8 merged. Adds the evidence used to justify each merge,
the repo fixes landed in PR #124, the three master lockfiles found already
desynced (GDJS, newIDE/electron-app/app, SharedLibs/TileMapHelper) and the
adm-zip 0.6.0 -> 0.6.1 bump that closed 2 high advisories.
Also records the rebase mechanics blocker: PRs 18/26/37/39/40/104 do not move
on '@dependabot rebase' because they were edited by hand; only #40 reports it.
* Merge master into chore/ci-remediation
Master advanced 10 merges (our own dependency PRs), so the lockfiles this
branch regenerated were stale against it. The merge reverted
newIDE/electron-app/package-lock.json to master's pre-regeneration copy;
regenerated it again (adm-zip stays 0.6.1).
All ten manifests verified in the merged state: npm ci --dry-run rc=0,
0 sync errors, guard exits 0.
* ci: run lockfile-sync as one job, not a 10-way matrix
Each matrix entry was a dry-run resolve taking a few seconds, so the 10-way
matrix bought ~30s of wall clock at the cost of 10 runners. The queue
contention that produced was starving the slower build-libgd and Jest jobs,
which dominate the workflow anyway.
Now a single job loops the same ten directories, continues past a failure so
one run reports every drifted manifest, and exits 1 at the end. Verified both
paths locally: on a good tree it prints "All lockfiles in sync." and exits 0;
with one drifted manifest it prints the per-directory ❌ with the npm
Missing:/Invalid: lines, keeps checking the rest, and exits 1.
* Bump grunt-contrib-compress from 1.6.0 to 2.0.0 in /GDevelop.js
Bumps [grunt-contrib-compress](https://github.com/gruntjs/grunt-contrib-compress) from 1.6.0 to 2.0.0.
- [Release notes](https://github.com/gruntjs/grunt-contrib-compress/releases)
- [Changelog](https://github.com/gruntjs/grunt-contrib-compress/blob/main/CHANGELOG)
- [Commits](https://github.com/gruntjs/grunt-contrib-compress/commits/v2.0.0)
---
updated-dependencies:
- dependency-name: grunt-contrib-compress
dependency-version: 2.0.0
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <[email protected]>
* fix(deps): pin adm-zip >=0.6.0 in GDevelop.js so the lockfile guard passes
grunt-contrib-compress 1.6.0 -> 2.0.0 pulls [email protected] transitively, which
trips the lockfile security guard:
GDevelop.js/package-lock.json: [email protected] matches < 0.6.0
master's GDevelop.js does not carry adm-zip at all, so the override is inert
there (verified: regenerating master with the override present yields no adm-zip
entry). With the bump applied it resolves 0.6.1 and the guard is clean.
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: BillyOutlast <[email protected]>