@forgeax/game 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ runtime.
10
10
 
11
11
  > [!IMPORTANT]
12
12
  > The published package carries `forgeax-game` and scoped `game` binary aliases and resolves the exact
13
- > `@forgeax/engine-sdk@0.1.7` and `pnpm@11.7.0` dependencies. It has no
13
+ > `@forgeax/engine-sdk@0.1.26` and `pnpm@11.7.0` dependencies. It has no
14
14
  > `@forgeax/game-runtime` dependency and no static Preview fallback.
15
15
 
16
16
  ## Supported flow
@@ -44,9 +44,11 @@ cd ./empty-game-directory
44
44
  npx -y @forgeax/game init
45
45
  ```
46
46
 
47
- The first command writes only the `forgeax` MCP member in the canonical Codex,
47
+ The first command writes the `forgeax` MCP member in the canonical Codex,
48
48
  Cursor, and Claude Code user configs. It preserves unrelated bytes and values,
49
49
  reports `CURRENT` on an idempotent rerun, and says which host must restart or reload.
50
+ Existing older package-owned Asset3D MCP entries are also refreshed; absent or
51
+ custom Asset3D entries are not added or overwritten.
50
52
  The second command must run from the intended blank directory. It creates the Engine
51
53
  game there, binds the exact release identity, and reports the canonical root and
52
54
  host-skill result. Existing exact games are read back and bound without recreation;
@@ -60,9 +62,13 @@ npx -y @forgeax/game@latest update --ide codex
60
62
  ```
61
63
 
62
64
  `update` reports the configured transition, for example
63
- `plugin 0.3.2 -> 0.3.3`. It refreshes configuration, skills, and routing from the
65
+ `plugin 0.3.4 -> 0.3.5`. It refreshes configuration, skills, and routing from the
64
66
  package being executed; it does not independently fetch another package.
65
67
 
68
+ See [0.3.5 compatibility notes](docs/release-0.3.5.md) before upgrading games pinned
69
+ to older Engine versions. This release recognizes strict v2 manifests without
70
+ requiring the removed `entry` field, but does not migrate game dependencies.
71
+
66
72
  > [!NOTE]
67
73
  > Asset3D is optional and **disabled by default**. The two commands above never contact
68
74
  > the internal asset catalog, provision the bundled platform Provider, or add
@@ -203,8 +209,9 @@ environment contract. The Provider access check returns only the exact download
203
209
  origins required by the sandbox. Failed validation or installation rolls back a
204
210
  newly written credential.
205
211
 
206
- The npm package carries the digest-pinned Darwin arm64 Provider archive as an inert
207
- asset. `enable` reuses the exact verified Provider from
212
+ The npm package carries digest-pinned Darwin arm64 and Linux x64 Provider archives
213
+ as inert assets. `enable` selects only the archive matching the current host and
214
+ reuses the exact verified Provider from
208
215
  `~/.forgeax/providers/asset3d-search/<sha256>/`, or provisions that packaged archive
209
216
  when the cache is absent. It never downloads Provider code from GitHub or another
210
217
  repository. Only after Provider verification and its MCP handshake succeed does it merge the `forgeax` and
@@ -278,7 +285,9 @@ and evidence boundaries.
278
285
 
279
286
  See [docs/runtime.md](docs/runtime.md) for the exact artifact and lifecycle contract.
280
287
  For the current AW-default plus explicit EA environment contract and maintainer
281
- publish checklist, see [docs/release-0.3.3.md](docs/release-0.3.3.md). The original AW
288
+ publish checklist, see [docs/release-0.3.4.md](docs/release-0.3.4.md). The AW-default
289
+ plus explicit EA environment contract was introduced in
290
+ [docs/release-0.3.3.md](docs/release-0.3.3.md). The original AW
282
291
  production default is recorded in [docs/release-0.3.2.md](docs/release-0.3.2.md), authenticated Provider
283
292
  delivery is documented in [docs/release-0.3.1.md](docs/release-0.3.1.md),
284
293
  and the original two-command onboarding contract remains documented in
package/dist/main.js CHANGED
@@ -342,7 +342,7 @@ function engineGameId(root) {
342
342
  try {
343
343
  const manifest = JSON.parse(readFileSync(join2(root, "forge.json"), "utf8"));
344
344
  const pkg = JSON.parse(readFileSync(join2(root, "package.json"), "utf8"));
345
- return typeof manifest.id === "string" && SLUG_RE.test(manifest.id) && typeof manifest.entry === "string" && typeof pkg.dependencies?.["@forgeax/engine"] === "string" ? manifest.id : undefined;
345
+ return typeof manifest.id === "string" && SLUG_RE.test(manifest.id) && (manifest.schemaVersion === "2.0.0" ? typeof manifest.defaultScene === "string" && /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(manifest.defaultScene) : (manifest.schemaVersion === undefined || manifest.schemaVersion === "1.0.0") && typeof manifest.entry === "string") && typeof pkg.dependencies?.["@forgeax/engine"] === "string" ? manifest.id : undefined;
346
346
  } catch {
347
347
  return;
348
348
  }
@@ -710,8 +710,8 @@ import { existsSync as existsSync3, lstatSync as lstatSync3, readFileSync as rea
710
710
  import { isAbsolute as isAbsolute2, relative as relative3, resolve as resolve4, sep as sep2 } from "node:path";
711
711
 
712
712
  // src/engine/constants.ts
713
- var ENGINE_VERSION = "0.1.7";
714
- var ENGINE_COMMIT = "984e80ac55b5f4f2afed3211c854b482a4018199";
713
+ var ENGINE_VERSION = "0.1.26";
714
+ var ENGINE_COMMIT = "f3d0db12405e168e4204e32a9cde32e0df8d87ae";
715
715
  var ENGINE_SDK_PACKAGE = "@forgeax/engine-sdk";
716
716
  var PNPM_VERSION = "11.7.0";
717
717
 
@@ -732,7 +732,7 @@ import { createRequire } from "node:module";
732
732
  import { basename, delimiter, dirname as dirname4, isAbsolute, relative as relative2, resolve as resolve3, sep } from "node:path";
733
733
  import { tmpdir } from "node:os";
734
734
  import { fileURLToPath as fileURLToPath2 } from "node:url";
735
- var SDK_MANIFEST_SCHEMA = "1.6.0";
735
+ var SDK_MANIFEST_SCHEMA = "1.7.0";
736
736
  var SDK_CLI_RELATIVE = ["bin", "forgeax.mjs"];
737
737
  var CARRIER_ENVIRONMENT_ALLOWLIST = [
738
738
  "HOME",
@@ -1690,7 +1690,7 @@ async function startEnginePreview(projectRoot, gameRoot, options = {}) {
1690
1690
  }
1691
1691
  const token = randomBytes(32).toString("hex");
1692
1692
  const previewInstanceId = randomUUID();
1693
- const child = spawn(process.execPath, [release.cliPath, "preview", "--json"], {
1693
+ const child = spawn(process.execPath, [release.cliPath, "preview", "--port", "0", "--json"], {
1694
1694
  cwd: release.gameRoot,
1695
1695
  detached: true,
1696
1696
  env: { ...process.env, FORGEAX_PREVIEW_INSTANCE_TOKEN: token },
@@ -2946,12 +2946,12 @@ var RELEASE_IDENTITY_MIME = "application/vnd.forgeax.game-release-identity+json"
2946
2946
  var RELEASE_IDENTITY = Object.freeze({
2947
2947
  schema: RELEASE_IDENTITY_SCHEMA,
2948
2948
  gamePackage: "@forgeax/game",
2949
- gameVersion: "0.3.3",
2949
+ gameVersion: "0.3.5",
2950
2950
  gameBin: "forgeax-game",
2951
2951
  engineSdkPackage: ENGINE_SDK_PACKAGE,
2952
2952
  engineSdkVersion: ENGINE_VERSION,
2953
2953
  engineSourceCommit: ENGINE_COMMIT,
2954
- carrierIntegrity: "sha512-f3Nz+ZoIOLVjNeKPock46+gwmC1wOWh9TJupQPl25+wZbIN1dJmki5LK6mNhchPxF7fffarbcFWGMqpKHkjQSw==",
2954
+ carrierIntegrity: "sha512-G5ovsbdzkWWeMfFy3MxVk0qcAvWnZxJnlypMGgxFUDaKr3Wv9uVuhPV88LZ1A9mhFJJSfrE1d5R3WvHgulygRQ==",
2955
2955
  sdkManifestDigest: `sha256:${"0".repeat(64)}`,
2956
2956
  sdkTreeDigest: `sha256:${"0".repeat(64)}`,
2957
2957
  fullZipDigest: `sha256:${"0".repeat(64)}`,
@@ -3356,7 +3356,7 @@ function launchSpec(mode) {
3356
3356
  }
3357
3357
  return {
3358
3358
  command: "npx",
3359
- args: ["-y", "-p", "@forgeax/game@0.3.3", "forgeax-game", "mcp"]
3359
+ args: ["-y", "-p", "@forgeax/game@0.3.5", "forgeax-game", "mcp"]
3360
3360
  };
3361
3361
  }
3362
3362
  function asset3dLaunchSpec(mode) {
@@ -4275,8 +4275,12 @@ var RECEIPT_SCHEMA_SHA256 = "e0dc9e9fe9872f09af9fca6d0c17d22aca63c2b546c55c0b669
4275
4275
  var ASSET3D_PROVIDER_COMMIT = "c181c48fbffc933a7ce9a0836f7878ca5e6d77e1";
4276
4276
  var BUNDLED_ASSET3D_PROVIDERS = Object.freeze({
4277
4277
  "darwin-arm64": {
4278
- sha256: "c8d2afd7ba68ae4b3540c927a2ff7133a82ea90975d09cab1d10b003fbbdeed3",
4278
+ sha256: "9492c507a3afe5cafcd50b5f782b313c8716c2e52f5def06592c6a100c0459db",
4279
4279
  relativePath: "asset3d/provider/asset3d-search-provider-c181c48fbffc933a7ce9a0836f7878ca5e6d77e1-darwin-arm64.tar.gz"
4280
+ },
4281
+ "linux-x64": {
4282
+ sha256: "e6ac3df76c8b82f9fe2c063dd3f221324a9dad5176fd52535a5144b0ff6002d8",
4283
+ relativePath: "asset3d/provider/asset3d-search-provider-c181c48fbffc933a7ce9a0836f7878ca5e6d77e1-linux-x64.tar.gz"
4280
4284
  }
4281
4285
  });
4282
4286
  var INSTALL_SCHEMA = "forgeax.asset3d-install/1.0.0";
@@ -5868,7 +5872,7 @@ async function runDormantAsset3dMcp() {
5868
5872
  result: {
5869
5873
  protocolVersion,
5870
5874
  capabilities: { tools: {} },
5871
- serverInfo: { name: "asset3d-search", version: "0.3.3" }
5875
+ serverInfo: { name: "asset3d-search", version: "0.3.5" }
5872
5876
  }
5873
5877
  };
5874
5878
  } else if (request2.method === "tools/list") {
@@ -6082,6 +6086,38 @@ async function runAsset3dMcpProxy(projectRoot, launch) {
6082
6086
  });
6083
6087
  }
6084
6088
 
6089
+ // src/asset3d/host-config.ts
6090
+ function inspectAsset3dHost(client, root) {
6091
+ const launch = asset3dLaunchSpec("npx");
6092
+ const status = inspectConfig(client, root, launch, ASSET3D_SERVER_KEY);
6093
+ if (status.state !== "different")
6094
+ return status;
6095
+ const previous = configuredGameVersion(client, root, ASSET3D_SERVER_KEY);
6096
+ const current = launch.args.find((arg) => arg.startsWith("@forgeax/game@"))?.slice("@forgeax/game@".length);
6097
+ if (!previous || !current || !/^\d+\.\d+\.\d+$/.test(previous) || !/^\d+\.\d+\.\d+$/.test(current))
6098
+ return status;
6099
+ const oldParts = previous.split(".").map(Number);
6100
+ const newParts = current.split(".").map(Number);
6101
+ const differing = oldParts.findIndex((part, index) => part !== newParts[index]);
6102
+ if (differing < 0 || oldParts[differing] >= newParts[differing])
6103
+ return status;
6104
+ const oldLaunch = { ...launch, args: launch.args.map((arg) => arg === `@forgeax/game@${current}` ? `@forgeax/game@${previous}` : arg) };
6105
+ if (inspectConfig(client, root, oldLaunch, ASSET3D_SERVER_KEY).state !== "current")
6106
+ return status;
6107
+ return { ...status, state: "outdated" };
6108
+ }
6109
+ function refreshAsset3dHost(client, root) {
6110
+ const status = inspectAsset3dHost(client, root);
6111
+ if (status.state === "outdated") {
6112
+ const result = applyConfig(client, root, asset3dLaunchSpec("npx"), ASSET3D_SERVER_KEY);
6113
+ process.stdout.write(`UPDATED ${client.label} Asset3D bridge: ${result.path}
6114
+ `);
6115
+ } else if (status.state === "different" || status.state === "invalid") {
6116
+ process.stderr.write(`WARN ${client.label}: existing ${ASSET3D_SERVER_KEY} configuration was preserved; it is not a recognized older package launcher.
6117
+ `);
6118
+ }
6119
+ }
6120
+
6085
6121
  // src/cli/dispatch.ts
6086
6122
  var HELP = `ForgeaX game development plugin
6087
6123
 
@@ -6186,6 +6222,7 @@ async function installCommand(args) {
6186
6222
  }
6187
6223
  try {
6188
6224
  const result = applyConfig(client, project.root ?? process.cwd(), launch);
6225
+ refreshAsset3dHost(client, project.root ?? process.cwd());
6189
6226
  process.stdout.write(`${result.changed ? "UPDATED" : "CURRENT"} ${client.label}: ${result.path}${result.backup ? ` (backup: ${result.backup})` : ""}
6190
6227
  `);
6191
6228
  if (client.postInstallNote)
@@ -6565,6 +6602,7 @@ async function updateCommand(args) {
6565
6602
  for (const client of configured) {
6566
6603
  const previousVersion = configuredGameVersion(client, root);
6567
6604
  const result = applyConfig(client, root, launch);
6605
+ refreshAsset3dHost(client, root);
6568
6606
  process.stdout.write(`${result.changed ? "UPDATED" : "CURRENT"} ${client.label}: ${result.path} (plugin ${formatVersionTransition(previousVersion)})
6569
6607
  `);
6570
6608
  }
@@ -6687,7 +6725,7 @@ async function asset3dCommand(args) {
6687
6725
  const client = findClient(id);
6688
6726
  if (!client)
6689
6727
  throw new Error(`asset3d_client_invalid: ${id}`);
6690
- const state = inspectConfig(client, projectRoot, bridge, ASSET3D_SERVER_KEY);
6728
+ const state = inspectAsset3dHost(client, projectRoot);
6691
6729
  if (state.state === "different") {
6692
6730
  throw new Error(`asset3d_client_server_conflict: ${client.label} already has a different ${ASSET3D_SERVER_KEY} entry`);
6693
6731
  }
package/docs/asset3d.md CHANGED
@@ -14,11 +14,13 @@ second importer or Preview server.
14
14
 
15
15
  > [!IMPORTANT]
16
16
  > Provider archives are platform-specific artifacts. The npm package embeds the
17
- > currently released Darwin arm64 archive so a cache-empty user does not depend on a
18
- > private source repository or release download. Installation deliberately returns
17
+ > currently released Darwin arm64 and Linux x64 archives so a cache-empty user does
18
+ > not depend on a private source repository or release download. Linux requires an
19
+ > x86-64 host and Python 3.11 or 3.12. Installation deliberately returns
19
20
  > `provider_platform_mismatch` when an archive target differs from the current host.
20
- > Each bundled target therefore needs its own digest, offline verification, MCP
21
- > handshake, and real service-path evidence.
21
+ > Unsupported targets such as Linux arm64 and Windows fail closed. Each bundled
22
+ > target therefore needs its own digest, offline verification, MCP handshake, and
23
+ > real service-path evidence.
22
24
 
23
25
  ## Trust and data flow
24
26
 
@@ -178,11 +180,12 @@ successful; `asset3d abort` removes only its transaction quarantine.
178
180
  ## Distribution and evidence boundary
179
181
 
180
182
  The packed Game Plugin includes the self-contained CLI bundle, existing connector
181
- Skill, exact K0 TGZ, checked P0 result/receipt schemas, and the immutable URL/digest
182
- table for supported Provider targets. It does not embed the Provider runtime archive,
183
- Engine payload, source checkout, credentials, or workspace links. Provider archives
184
- are separate release assets so a disabled installation downloads nothing. The package
185
- artifact gate recomputes every embedded predecessor digest.
183
+ Skill, exact K0 TGZ, checked P0 result/receipt schemas, and an inert, digest-pinned
184
+ Provider archive for every supported target. It does not embed a provisioned Python
185
+ environment, managed Provider cache, Engine payload, source checkout, credentials, or
186
+ workspace links. A disabled installation neither extracts an archive nor contacts a
187
+ network service. The package artifact gate recomputes every embedded predecessor
188
+ digest.
186
189
 
187
190
  Controlled external-consumer evidence may establish package installation, raw MCP
188
191
  framing, local redirect/ZIP handling, multi-GLB and texture import, reuse, refresh,
@@ -0,0 +1,66 @@
1
+ # @forgeax/game 0.3.4 release contract
2
+
3
+ Version `0.3.4` adds a self-contained Linux x64 Asset3D Provider while preserving
4
+ the existing opt-in workflow. Ordinary `install` and `init` remain platform-neutral
5
+ and keep Asset3D disabled. A user enables Asset3D only from an initialized game:
6
+
7
+ ```bash
8
+ npx -y @forgeax/game@0.3.4 asset3d enable
9
+ npx -y @forgeax/game@0.3.4 asset3d doctor --json
10
+ ```
11
+
12
+ ## Supported Provider targets
13
+
14
+ | Host | Provider archive SHA-256 | Status |
15
+ |---|---|---|
16
+ | Darwin arm64 | `9492c507a3afe5cafcd50b5f782b313c8716c2e52f5def06592c6a100c0459db` | Supported |
17
+ | Linux x64 | `e6ac3df76c8b82f9fe2c063dd3f221324a9dad5176fd52535a5144b0ff6002d8` | Supported; Python 3.11 or 3.12 required |
18
+
19
+ Both archives bind Provider commit
20
+ `c181c48fbffc933a7ce9a0836f7878ca5e6d77e1`. The package build fails if either
21
+ source archive is absent, is a symlink, or differs from its approved digest. The npm
22
+ artifact gate repeats those checks against the packed bytes.
23
+
24
+ The offline wheelhouses omit upstream dependency test suites and redact
25
+ credential-shaped user-info from dependency documentation examples. Runtime modules
26
+ and package metadata remain present, each rewritten wheel is re-RECORDed and
27
+ hash-locked, and the resulting platform archives are byte-reproducible. This keeps
28
+ test-only public tokens and false credential patterns out of the npm payload.
29
+
30
+ Linux arm64 and Windows are not part of this release. `asset3d enable` fails closed
31
+ with `asset3d_provider_target_unreleased` on those hosts; it does not install a
32
+ different target or fall back to downloaded Provider code.
33
+
34
+ ## Linux release gate
35
+
36
+ The Ubuntu x64 CI job performs the Linux-specific verification from the same package
37
+ assets that are published:
38
+
39
+ 1. Provision the Provider into an empty managed cache without downloading Provider
40
+ code or Python dependencies.
41
+ 2. Verify the archive manifest, target, file digests, wheel lock, and converter.
42
+ 3. Execute the bundled Linux x64 `FBX2glTF` binary.
43
+ 4. Launch the installed Provider over stdio MCP and require `search_asset` in
44
+ `tools/list`.
45
+
46
+ This proves Linux provisioning and MCP capability discovery. It does not substitute
47
+ for an authenticated request to the internal AW service, which requires network
48
+ reachability and user credentials and remains a separate environment acceptance
49
+ gate.
50
+
51
+ ## Maintainer checklist
52
+
53
+ - [ ] `bun run typecheck`
54
+ - [ ] `bun test`
55
+ - [ ] `bun run build`
56
+ - [ ] `npm pack --ignore-scripts --pack-destination <empty-directory>`
57
+ - [ ] `bun run release:check -- <exact-tarball>`
58
+ - [ ] Ubuntu x64 `asset3d-linux-x64` CI job is green on the exact release commit.
59
+ - [ ] The packed artifact contains both Provider archives and no credential, source
60
+ checkout, managed cache, or provisioned Python environment.
61
+ - [ ] The exact tarball passes the repository secret and private-path scans before
62
+ publication.
63
+
64
+ The AW production default and explicit EA override remain as documented in
65
+ [`release-0.3.3.md`](release-0.3.3.md). Credential storage and real search/import
66
+ acceptance boundaries remain unchanged and are defined in [`asset3d.md`](asset3d.md).
@@ -0,0 +1,32 @@
1
+ # @forgeax/game 0.3.5
2
+
3
+ ## Compatibility repair
4
+
5
+ | Boundary | Release behavior |
6
+ |:--|:--|
7
+ | Engine SDK | Exact dependency 0.1.26, commit `f3d0db12405e168e4204e32a9cde32e0df8d87ae` |
8
+ | Project discovery | Recognizes strict `forge.json` v2 with `defaultScene`; does not inject the forbidden legacy `entry` field |
9
+ | SDK manifest | Validates the released 1.7.0 manifest and exact Engine/DevKit identities |
10
+ | Preview | Uses Engine-owned `--port 0` allocation instead of conflicting with another game on port 5173 |
11
+ | Asset3D upgrade | Refreshes existing older package-owned bridges during install/update; preserves custom configurations |
12
+
13
+ ## Install or update
14
+
15
+ ```bash
16
+ npx -y @forgeax/game@0.3.5 install --ide codex,cursor,claude
17
+ # In a genuinely empty game directory:
18
+ npx -y @forgeax/game@0.3.5 init
19
+ ```
20
+
21
+ For an existing Engine 0.1.26 project, run `update --ide codex` with this package,
22
+ then restart the host session. Asset3D remains opt-in with `asset3d enable`.
23
+
24
+ > [!IMPORTANT]
25
+ > This release pins Engine 0.1.26. It does not silently migrate games using Engine
26
+ > 0.1.7. Keep those games on plugin 0.3.4 until deliberately migrating through the
27
+ > Engine-supported workflow. Do not add `entry` to a v2 manifest to work around the
28
+ > old plugin's project detection.
29
+
30
+ The plugin must return Engine-owned Preview readiness and matching root/build
31
+ identity. A direct Engine CLI preview or a listening port alone is not MCP
32
+ acceptance. Asset search/import and visible gameplay require separate verification.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageManager": "bun@1.3.14",
3
3
  "name": "@forgeax/game",
4
- "version": "0.3.3",
4
+ "version": "0.3.5",
5
5
  "private": false,
6
6
  "type": "module",
7
7
  "description": "@forgeax/game — an MCP/CLI connector for exact released ForgeaX Engine games and Engine-owned Preview.",
@@ -25,6 +25,8 @@
25
25
  "docs/release-0.3.1.md",
26
26
  "docs/release-0.3.2.md",
27
27
  "docs/release-0.3.3.md",
28
+ "docs/release-0.3.4.md",
29
+ "docs/release-0.3.5.md",
28
30
  "README.md"
29
31
  ],
30
32
  "scripts": {
@@ -32,6 +34,7 @@
32
34
  "release:check": "bun scripts/check-package-artifact.ts",
33
35
  "acceptance": "bun scripts/accept-packed-consumer.ts",
34
36
  "acceptance:asset3d": "bun scripts/accept-asset3d-packed-consumer.ts",
37
+ "verify:asset3d-linux": "bun scripts/verify-linux-asset3d-provider.ts",
35
38
  "release:publish": "bun scripts/publish-package.ts",
36
39
  "prepack": "bun build.mjs",
37
40
  "typecheck": "tsc --noEmit",
@@ -49,7 +52,7 @@
49
52
  ],
50
53
  "license": "MIT",
51
54
  "dependencies": {
52
- "@forgeax/engine-sdk": "0.1.7",
55
+ "@forgeax/engine-sdk": "0.1.26",
53
56
  "pnpm": "11.7.0"
54
57
  },
55
58
  "devDependencies": {