diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index 7bf3280..c7c62ce 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -19,4 +19,4 @@ jobs: with: node-version: '20' - - run: node scripts/check-docs.mjs + - run: npm run check diff --git a/agent-setup.mdx b/agent-setup.mdx index 51db32e..3f3b3fb 100644 --- a/agent-setup.mdx +++ b/agent-setup.mdx @@ -1,10 +1,13 @@ --- title: "Agent Setup" -description: "Point any AI coding agent at Summercraft: one paste-prompt that takes it from empty directory to a multiplayer Godot game submitted for review." +description: "Point an AI coding agent at the canonical Summer Engine prompt: build a multiplayer Summer game in GDScript and submit it for review." icon: "bot" --- -Summercraft is built to be published to by AI coding agents. You do not need Summer Engine installed to ship a game: any agent with a shell (Claude Code, Cursor, Codex, Copilot Workspace, anything) can build a multiplayer Godot game as a GDScript-only `.pck` and submit it through the live publish API. A human reviews every submission before it goes live. +An AI coding agent can use Summer Engine to build a multiplayer **Summer game** in +**GDScript**, integrate the **Summer SDK**, validate it locally, and submit it through the +live submission API. A human reviews every submission before its catalog status can become +`published`; published catalog status does not make an uploaded game playable yet. ## Point your agent at Summercraft @@ -13,13 +16,15 @@ Paste this into any coding agent: ```text Fetch https://docs.summerengine.com/agent-setup/prompt.md and follow it exactly, top to bottom. It is the canonical instruction set for building a multiplayer -Godot 4.5 game against the Summer SDK and publishing it to Summercraft. +Summer game in GDScript with Summer Engine and the Summer SDK, then publishing +it to Summercraft. Context you need before you start: -- Summercraft (https://summercraft.ai) is the platform where Summer SDK games - are published and played. The publish API lives at https://summercraft.ai/api/*. -- You will build a GDScript-only game that extends SummerGame, export a .pck - with Godot 4.5 headless (no export templates needed), and publish it in four +- Summercraft (https://summercraft.ai) accepts Summer SDK games for review. + The submission API lives at https://summercraft.ai/api/*; uploaded games are + not playable on the platform yet. +- You will install and use Summer Engine, build a GDScript-only game that + extends SummerGame, export a .pck with the Summer Engine binary, and publish it in four API calls: create game -> get presigned upload URL -> PUT the .pck -> finalize (the server re-verifies your sha256). - Publishing needs a Summercraft access token in SUMMERCRAFT_ACCESS_TOKEN. @@ -28,7 +33,7 @@ Context you need before you start: - Each publish step is limited to 1 request per hour per account, so validate everything locally before touching the API. - After finalize the release is "pending_review" in a manual human review - queue. There is no auto-publish, and browser/desktop play of uploaded Godot + queue. There is no auto-publish, and browser/desktop play of uploaded Summer games is not live yet - say so honestly when you report back. - Any docs page is fetchable as raw markdown by adding .md to its URL; the index is at https://docs.summerengine.com/llms.txt. @@ -40,12 +45,12 @@ The prompt at [/agent-setup/prompt](/agent-setup/prompt) is the canonical, alway ## What the agent will do -1. **Check prerequisites** — Godot 4.5 for headless export, `curl`, a sha256 tool, and (only at publish time) your access token. +1. **Check prerequisites** — Summer Engine for local validation/export, `curl`, a sha256 tool, and (only at publish time) your access token. 2. **Build a multiplayer-native game** — `extends SummerGame`, all gameplay authority on server paths, player state via `set_synced`, local SDK stubs so everything parses and smoke-runs without the platform runtime. 3. **Validate locally** — headless smoke run, banned-API self-check, pack-content check. The upload budget is 1/hour, so the prompt front-loads every check. 4. **Export a game-only `.pck`** — the preset excludes stubs and project config; ships GDScript as readable source. 5. **Publish through the live API** — create game → presigned upload → server-verified finalize. See [Exporting and Uploading](/api-reference/summer-sdk/exporting-and-uploading-your-game) for the full reference. -6. **Report honestly** — release `pending_review` in the manual queue; approval publishes it, rejection comes with a reason on [summercraft.ai/creator](https://summercraft.ai/creator). +6. **Report honestly** — release `pending_review` in the manual queue; approval changes its catalog status to `published`, but does not make it playable yet. Rejection comes with a reason on [summercraft.ai/creator](https://summercraft.ai/creator). ## The one thing the agent cannot do: sign in @@ -58,23 +63,16 @@ Agents must never handle your password. Create your account and session yourself There is no dedicated token page yet; this manual step is the current path. The publish API accepts `Authorization: Bearer ` on every endpoint. -## What is live vs. coming - -| Capability | Status | -|---|---| -| Create Godot game records via API | **Live** | -| Direct-to-storage `.pck` upload (presigned, write-once) | **Live** | -| Server-side sha256 verification at finalize | **Live** | -| Manual human review queue | **Live** — every release, no auto-publish | -| Authenticated release downloads (`download-url`) | **Live** — owner/admins always; others once published | -| Browser `.pck` submit page ([summercraft.ai/submit](https://summercraft.ai/submit)) | **Live** — multipart flow with automated static scanner | -| Playing uploaded Godot games in the browser | Coming — not yet available | -| Playing uploaded Godot games in the desktop shell | Coming — not yet available | -| Hosted dedicated game servers for uploaded games | Coming — not yet available | -| Automated runtime sandbox for submissions | Coming — review is manual today | -| `SummerMultiplayerPeer` transport (stock `@rpc` compatibility) | Coming — contract published, being built in the engine fork; current runtime multiplayer is host-authoritative over ENet | - -Docs on this site never promise capabilities that are not deployed. If a page and reality disagree, trust the API's own error text and mail [founders@summerengine.com](mailto:founders@summerengine.com). +## Platform status + +The release API, browser submission with static scanning, manual review queue, and +authenticated release downloads are deployed. That does not make an approved game playable. + +Use the single canonical [Product source & platform status](/knowledge-base/source-status) +table for every Live / Scaffold / Planned decision. It covers playback, hosted servers, +matchmaking, the runtime sandbox, and the transport contract without duplicating a second +status table here. If documentation and reality disagree, trust the API's own error text and +mail [founders@summerengine.com](mailto:founders@summerengine.com). ## For agents reading this page directly diff --git a/agent-setup/prompt.mdx b/agent-setup/prompt.mdx index a53e79d..bd16475 100644 --- a/agent-setup/prompt.mdx +++ b/agent-setup/prompt.mdx @@ -1,33 +1,59 @@ --- title: "Agent Prompt" -description: "The canonical instruction set for AI coding agents building and publishing a multiplayer Godot game to Summercraft. Fetch this page raw at /agent-setup/prompt.md." +description: "Canonical instructions for an AI coding agent to build a multiplayer Summer game in GDScript with Summer Engine and publish it for review." icon: "bot" noindex: false --- -You are an AI coding agent. Your job is to build a multiplayer Godot game as a GDScript-only `.pck` and publish it to Summercraft for review. Follow this document top to bottom. Everything in it was verified against the live platform; where a capability is not live yet, this document says so explicitly. +You are an AI coding agent. Your job is to use **Summer Engine** and the **Summer SDK** to +build a multiplayer **Summer game** in **GDScript**, export a game-only `.pck`, and publish +it to Summercraft for review. Follow this document top to bottom. Where a platform +capability is not live yet, this document says so explicitly. Any page of these docs is fetchable as raw markdown by appending `.md` to its URL. The full page index is at `https://docs.summerengine.com/llms.txt`. ## 1. What Summercraft is -Summercraft (`https://summercraft.ai`) is the platform where games built against the Summer SDK are published and played. You write a plain Godot 4.5 game in GDScript, extend the SDK base class `SummerGame`, export a `.pck` that contains only your game files, and submit it through the publish API. A human reviews every submission before it goes live. There is no auto-publish. +Summercraft (`https://summercraft.ai`) is the platform where Summer games built with the +Summer SDK are submitted. Use Summer Engine, extend the SDK base class `SummerGame`, export +a `.pck` containing only game files, and submit it through the publish API. A human reviews +every submission before its catalog status can become `published`. There is no auto-publish, +and a published catalog release is not playable yet. - The publish API lives at `https://summercraft.ai/api/*`. - Docs live at `https://docs.summerengine.com`. -- The Summer SDK classes (`Summer`, `SummerGame`, `SummerPlayer`, `SummerCharacter3D`) are provided by the Summercraft runtime when your pack loads. They are not files you ship. +- The Summer SDK contract defines `Summer`, `SummerGame`, `SummerPlayer`, and + `SummerCharacter3D`. Local stubs let the project parse, and the export excludes those + stubs. A future production runtime is intended to provide the real classes, but uploaded + games cannot launch there today. **What is live today:** creating a game record, direct-to-storage artifact upload with server-side sha256 verification, the manual review queue, and authenticated release downloads. -**What is not live yet (do not promise these to your operator):** playing uploaded Godot games in the browser, playing them inside the desktop shell, hosted dedicated game servers for uploaded games, and the automated runtime sandbox. Multiplayer sessions in the current runtime run host-authoritatively over ENet; the `SummerMultiplayerPeer` transport (stock `@rpc` / `MultiplayerSynchronizer` compatibility) is a published contract still being built in the engine fork. +**What is not live yet (do not promise these to your operator):** playing uploaded Summer +games in the browser or desktop shell, hosted dedicated game servers for uploaded games, +automatic matchmaking, and the automated runtime sandbox. The examples use a +host-authoritative model, but no production transport is live. `SummerMultiplayerPeer` +(stock `@rpc` / `MultiplayerSynchronizer` compatibility) is a scaffolded contract still +being built. ## 2. Prerequisites — check all three before writing any code -1. **Godot 4.5.x.** Run `godot --version` (or find the binary, e.g. `/Applications/Godot.app/Contents/MacOS/Godot` on macOS). Any 4.5 build works; you only need it for headless export, no export templates required. If it is missing, ask your operator to install Godot 4.5 from `https://godotengine.org/download` before continuing. +1. **Summer Engine.** If it is missing, install it with + `npx -y summer-engine@latest install`. Resolve the installed executable and set + `SUMMER_ENGINE` to its path. On macOS the default is + `/Applications/Summer.app/Contents/MacOS/Summer`. Run + `"$SUMMER_ENGINE" --version` before continuing. 2. **A Summercraft access token.** Check for a `SUMMERCRAFT_ACCESS_TOKEN` environment variable or ask your operator for one. Without it every publish call returns `401 sign_in_required`. **Stop and ask before step 6 if you do not have it** — you can build and export everything first. Show your operator this if they do not know how to get one: > Sign in at `https://summercraft.ai` (create the account yourself — never let an agent handle your password). Then open your browser dev tools on that tab: Application → Cookies → `summercraft.ai`, and find the cookie whose name ends in `-auth-token` (it may be split into `.0`/`.1` chunks — concatenate their values in order). URL-decode the value; if the result starts with `base64-`, base64-decode the rest. Inside the JSON is an `access_token` field: that string is the Bearer token. It expires after about an hour, which is enough for one publish. There is no dedicated token page yet; this manual step is the current path. 3. **`curl` and a sha256 tool** (`shasum -a 256` or `sha256sum`). + + A bare upstream binary is not the default path. On locked CI infrastructure where Summer + Engine cannot be installed, use the explicitly labeled compatibility escape hatch in + [local testing](/api-reference/summer-sdk/testing-your-game-locally). It can validate + file-format behavior only and does not prove Summer SDK runtime compatibility. + + Auth model, exactly: every publish endpoint accepts `Authorization: Bearer ` (or a signed-in browser session cookie). A present-but-invalid Bearer token is a hard `401` — it never falls back to a cookie. If you get `401` with a token set, the token has expired: ask your operator for a fresh one. ## 3. Know the rules before you build @@ -35,14 +61,20 @@ Auth model, exactly: every publish endpoint accepts `Authorization: Bearer ` is `pending_review` in the manual review queue. A human reviews every submission; there is no automatic publish and no guaranteed review time. -2. When approved, the game becomes `published` and the release goes live; if rejected, the reason appears for the creator on `https://summercraft.ai/creator`. +2. When approved, the game and active release receive `published` catalog status; if rejected, the reason appears for the creator on `https://summercraft.ai/creator`. Published catalog status does not make the uploaded game playable yet. 3. The owner (and admins) can verify the stored artifact any time — response includes a short-lived (5 min) download URL plus the server-verified `sha256`: ```bash curl -sS "https://summercraft.ai/api/games/$GAME_ID/releases/1.0.0/download-url" \ -H "Authorization: Bearer $SUMMERCRAFT_ACCESS_TOKEN" ``` Other signed-in users can fetch it only after the game is published. -4. Playing uploaded Godot games in the browser or desktop shell, and hosted game servers, are not live yet — publishing today means entering the catalog pipeline, not instant playability. Do not claim otherwise. +4. Playing uploaded Summer games in the browser or desktop shell, hosted game servers, + automatic matchmaking, and the runtime sandbox are not live yet — publishing today + means entering the catalog pipeline, not instant playability. Do not claim otherwise. + The canonical status is + `https://docs.summerengine.com/knowledge-base/source-status.md#platform-capability-status`. ## 8. Updating the game later diff --git a/api-reference/summer-sdk.mdx b/api-reference/summer-sdk.mdx index c1be071..759c5c9 100644 --- a/api-reference/summer-sdk.mdx +++ b/api-reference/summer-sdk.mdx @@ -1,28 +1,64 @@ --- -title: "Creating Games on Summercraft" -description: "Summercraft is a powerful platform layer that provides multiplayer, persistence, and economy features. You bring the game, we bring the infrastructure." +title: "Summer SDK" +description: "The lifecycle hub for adding Summer SDK capabilities to a Summer game, testing locally, submitting for review, and updating." icon: "gamepad-2" --- -## Introduction to Summercraft +## Add platform capabilities to your Summer game -Summercraft is a place where you can play games made by the community in Summer Engine. It's a platform made to make it easy for developers to make and share their games without having to go through store experiences made +20 years ago. The Summer SDK works similar to Steams steamworks, and aims to make it more easy to build and share your games. Rather than forcing you into a rigid template or specific game type, Summercraft seamlessly integrates with your project to provide robust multiplayer infrastructure and backend services. +The **Summer SDK** is the creator-facing platform contract for a **Summer game**. Your +GDScript owns the gameplay, worlds, rules, and presentation. The SDK documents multiplayer, +player, persistence, economy, and submission interfaces. An interface being documented does +not mean its hosted runtime is production-live. -The mental model is simple: you build your game's unique design and systems, and plug in the Summer SDK to handle all the complex platform features. +Use only the capabilities your game needs. Templates are examples, not requirements. -## What Summercraft Handles +## Lifecycle -The Summer SDK provides out-of-the-box support for: + + + Start from the minimal SummerGame lifecycle and manifest. + + + Select player, teams, score, persistence, economy, UI, and audio surfaces. + + + Use Summer Engine first and validate before spending a publish request. + + + Produce a game-only pack and verify its digest and contents. + + + Choose the API or browser path and follow the human review state. + + + Keep the game identity stable, bump the version, retest, and resubmit. + + + +## What is available now + +- Create a Summer game record. +- Upload a game-only `.pck` directly to storage with server-side checksum verification. +- Enter the manual human review queue. +- Download releases through the authenticated release endpoint. -- **Multiplayer Runtime:** Server-authoritative networking and matchmaking infrastructure. -- **Player Management:** Unified player identity and session handling. -- **Backend Services:** Built-in APIs for data persistence and player economy. -- **Game Utilities:** Ready-to-use helpers for score tracking, teams, and match state. -- **Publishing Pipeline:** A streamlined submission, review, and deployment flow. +## What remains a contract or planned capability + +- Summer SDK lifecycle, player, sync, persistence, economy, teams, score, UI, and audio + interfaces are a creator contract under implementation. +- Player-facing browser and desktop-shell playback is not live. +- Hosted dedicated game servers and automatic matchmaking are not live. +- The automated production runtime sandbox is not live. +- `SummerMultiplayerPeer` is a published compatibility contract still being built. + +See [Product source & platform status](/knowledge-base/source-status#platform-capability-status) +for the single canonical status table. Do not infer deployment status from an SDK reference +page or example. ## What You Build -Because Summercraft manages the heavy lifting on the backend, you're free to focus purely on making a great game: +Your game remains responsible for its creative and gameplay layer: - **Core Gameplay:** Your unique mechanics, controls, and game loops. - **Worlds & Scenes:** Environments, levels, and visual rendering. @@ -46,19 +82,11 @@ Templates are examples, not requirements. - `SummerCharacter3D` is the optional 3D character template path. - For 2D/RTS/card/turn-based games, extend `SummerPlayer` directly and sync your own game model. -## Recommended Reading Order (Fresh AI / Fresh Dev) - -1. `SummerGame` and `Summer` basics -2. `SummerPlayer` contract and `set_synced` -3. subsystem modules you need (`data`, `economy`, `teams`, `score`) -4. local test runner flow -5. export/upload and banned API constraints. - -## API Sections +## Capability and reference pages - Point any AI coding agent at one prompt: build, export, and publish through the live API + Point any AI coding agent at one prompt: build, export, and submit through the live API Migrating from Crafty: every renamed class, autoload, manifest key, and path @@ -75,7 +103,7 @@ Templates are examples, not requirements. Optional platform modules: teams, score, data, economy, UI, audio, and signals - + Golden-path tutorial from blank project to .pck submission @@ -103,7 +131,7 @@ Templates are examples, not requirements. Export .pck, scanner rules, upload flow, review lifecycle, and updates - Two-process local workflow, multiplayer testing, and production-like validation loop + Summer Engine smoke checks, optional loopback testing, and the limits of local validation Game-only PCK export preset, upload pipeline, and update workflow @@ -119,3 +147,12 @@ Templates are examples, not requirements. ## Versioning Games declare a `summer_sdk` version in `manifest.json`. SDK changes are intended to be additive and backward-compatible. + + + + Return to the minimal GDScript and manifest contract. + + + Validate the Summer game with Summer Engine before export. + + diff --git a/api-reference/summer-sdk/ai-agent-playbook.mdx b/api-reference/summer-sdk/ai-agent-playbook.mdx index 620bcd2..b040df8 100644 --- a/api-reference/summer-sdk/ai-agent-playbook.mdx +++ b/api-reference/summer-sdk/ai-agent-playbook.mdx @@ -1,6 +1,6 @@ --- title: "AI Agent Playbook" -description: "Production contract for AI-generated Summercraft integrations: platform-first framing, required outputs, and acceptance checks." +description: "Output contract for AI-generated Summer SDK integrations: Summer-first framing, required files, submission checks, and runtime-status limits." icon: "bot" --- @@ -8,12 +8,14 @@ icon: "bot" Fresh AI sessions must be able to generate code that: -- runs in Summercraft runtime, +- conforms to the Summer SDK runtime contract, - passes static analysis + submission checks, - stays server-authoritative, - does not assume 3D template-only architecture. -This page is the strict contract for that. +This page is the strict output contract. It does not claim that player-facing playback, +hosted servers, matchmaking, or the production runtime sandbox is live. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). This page is the *output contract* (what generated code must look like). The *end-to-end instruction set* — build, validate, export, and publish through the live API — is the canonical agent prompt at [/agent-setup](/agent-setup), raw at `https://docs.summerengine.com/agent-setup/prompt.md`. Point agents there first. @@ -23,7 +25,7 @@ This page is the strict contract for that. Treat Summercraft as a platform layer: -- Build game logic in Summer/Godot. +- Build Summer game logic in Summer Engine. - Integrate `SummerGame` lifecycle + player synced state. - Use templates only when they fit the genre. @@ -129,7 +131,7 @@ An AI-generated game is "done" only if all checks pass: 5. Player path chosen explicitly (3D template or custom `SummerPlayer` subclass). 6. No blocked APIs appear in any `.gd` file. 7. Server-authoritative gameplay logic is on server paths. -8. Game can be exported to `.pck` and published through the [release API](/api-reference/summer-sdk/exporting-and-uploading-your-game) (release reaches `pending_review`). +8. Game can be exported to `.pck` and submitted through the [release API](/api-reference/summer-sdk/exporting-and-uploading-your-game) (release reaches `pending_review`). ## Safe Starter Prompt (for AI systems) @@ -157,4 +159,3 @@ Rules: - DO NOT use blocked APIs: OS.execute, OS.shell_open, OS.create_process, FileAccess, DirAccess, HTTPRequest, HTTPClient, JavaScriptBridge, ClassDB.instantiate, Thread.new. - Target summer_sdk "1.0". ``` - diff --git a/api-reference/summer-sdk/banned-apis-reference.mdx b/api-reference/summer-sdk/banned-apis-reference.mdx index 149d011..e1b8e7c 100644 --- a/api-reference/summer-sdk/banned-apis-reference.mdx +++ b/api-reference/summer-sdk/banned-apis-reference.mdx @@ -6,7 +6,9 @@ icon: "shield-alert" ## Why These APIs Are Blocked -Summercraft runs creator-submitted code on shared infrastructure. +Summercraft's submission policy is designed for creator code that may eventually run inside +a shared production sandbox. The static scanner and human review enforce these boundaries +today even though the automated production runtime sandbox is not live yet. To protect platform security and stability, submission blocks patterns that enable: @@ -29,23 +31,23 @@ If a blocked pattern appears in submitted source, upload fails, even when: |------|------|------| | `OS.execute` | Executes arbitrary system commands on server hosts. | Use Summer SDK gameplay/data APIs. | | `OS.shell_open` | Opens external shells/URLs and escapes runtime boundaries. | Use in-game UI flow; no direct OS shell access. | -| `OS.create_process` | Spawns unmanaged processes from game code. | Keep process control in platform runtime, not game scripts. | +| `OS.create_process` | Spawns unmanaged processes from game code. | Submitted packs cannot own process control; no production platform runtime is live yet. | | `OS.create_instance` | Creates new runtime instances outside allowed flow. | Use standard scene instantiation and SDK systems. | | `OS.kill` | Can terminate infrastructure or peer processes. | Use gameplay lifecycle APIs only. | -| `FileAccess` | Unrestricted read/write to filesystem. | Use `Summer.data` for persistence. | -| `DirAccess` | Directory traversal/manipulation on host filesystem. | Use SDK-managed storage paths via `Summer.data`. | -| `HTTPRequest` | Arbitrary outbound HTTP from game logic. | Use `Summer.data` / `Summer.economy` platform APIs. | +| `FileAccess` | Unrestricted read/write to filesystem. | Target the scaffolded `Summer.data` contract; production persistence is not live yet. | +| `DirAccess` | Directory traversal/manipulation on host filesystem. | Target the scaffolded `Summer.data` contract; production storage is not live yet. | +| `HTTPRequest` | Arbitrary outbound HTTP from game logic. | Target the scaffolded `Summer.data` / `Summer.economy` contracts; their production backends are not live yet. | | `HTTPClient` | Low-level custom network egress from untrusted scripts. | Use SDK networking and platform endpoints only. | | `JavaScriptBridge` | Bridge escape to browser/JS runtime. | Keep logic in GDScript + SDK only. | | `ClassDB.instantiate` | Dynamic class loading can bypass allowed surfaces. | Instantiate explicit scene/resources you control. | | `Thread.new` | Unmanaged concurrency can impact determinism/stability. | Use deterministic main-loop gameplay logic. | | `Mutex.new` | Same as above, often paired with unsafe concurrency patterns. | Keep gameplay state updates on main thread. | | `Semaphore.new` | Same as above; can hide blocking/synchronization hazards. | Use frame/tick-driven state machines. | -| `StreamPeerTCP` | Raw socket networking bypasses platform control. | Use built-in Summercraft networking flow. | -| `PacketPeerUDP` | Raw UDP bypasses platform-level auth/routing. | Use Summercraft transport and replication APIs. | -| `TCPServer` | Opens custom server sockets inside creator game scripts. | Use platform-managed game servers only. | -| `UDPServer` | Same as above for UDP. | Use platform-managed networking only. | -| `WebSocketPeer` | Arbitrary socket communication channel. | Use Summercraft-managed networking. | +| `StreamPeerTCP` | Raw socket networking bypasses the platform contract. | Use the Summer SDK transport contract when the production path is available. | +| `PacketPeerUDP` | Raw UDP bypasses platform-level auth/routing. | Use the Summer SDK transport and replication contract. | +| `TCPServer` | Opens custom server sockets inside creator game scripts. | Keep server ownership outside the submitted game pack. | +| `UDPServer` | Same as above for UDP. | Keep networking outside the submitted game pack. | +| `WebSocketPeer` | Arbitrary socket communication channel. | Use the Summer SDK transport contract when available. | | `.call(` | Reflection can be used to bypass direct API checks. | Explicit method calls on known safe objects. | | `.callv(` | Same reflection bypass risk. | Explicit typed calls. | | `.call_deferred(` | Reflection/deferred execution can hide unsafe paths. | Use explicit logic flow and signals. | @@ -54,8 +56,8 @@ If a blocked pattern appears in submitted source, upload fails, even when: | `Expression.new` | Runtime expression eval can execute dynamic untrusted code. | Static, explicit gameplay logic. | | `Expression(` | Same runtime eval surface. | Static logic and pre-defined scripts. | | `Marshalls.base64_to_variant` | Unsafe/deserialization abuse vector for crafted payloads. | Use validated JSON and typed schema checks. | -| `ResourceSaver` | Writes resource files at runtime; persistence boundary risk. | Use `Summer.data` for persisted state. | -| `ProjectSettings.load_resource_pack` | Runtime pack loading from game scripts is not allowed. | Let platform runtime load approved game packs. | +| `ResourceSaver` | Writes resource files at runtime; persistence boundary risk. | Target the scaffolded `Summer.data` contract; production persistence is not live yet. | +| `ProjectSettings.load_resource_pack` | Runtime pack loading from game scripts is not allowed. | Pack loading belongs to a future runtime; no production loader is live yet. | | `get_node("/root` | Root traversal can reach infrastructure internals. | Use scoped scene tree access in your game subtree. | | `get_node(\"/root` | Same root traversal risk (escaped quote variant). | Use local node paths. | | `get_tree().root` | Global root access to internals outside game boundary. | Access only local game nodes and SDK APIs. | @@ -95,6 +97,10 @@ When generating code from prompts: 3. Keep all file/network/process interactions out of creator game scripts. 4. Use explicit method calls instead of reflective invocation helpers. +The alternatives in this table are contract guidance, not a deployment-status promise. +Check [platform capability status](/knowledge-base/source-status#platform-capability-status) +before promising hosting, matchmaking, transport, persistence, or economy behavior. + ## Related Docs - [Exporting and Uploading Your Game](/api-reference/summer-sdk/exporting-and-uploading-your-game) diff --git a/api-reference/summer-sdk/build-your-first-summer-game.mdx b/api-reference/summer-sdk/build-your-first-summer-game.mdx index c20cf96..ea088d4 100644 --- a/api-reference/summer-sdk/build-your-first-summer-game.mdx +++ b/api-reference/summer-sdk/build-your-first-summer-game.mdx @@ -1,12 +1,18 @@ --- -title: "Build Your First Summercraft Game" -description: "Golden path: build a multiplayer-native game on the Summer SDK, test it locally, export a .pck, and submit it for review." +title: "Build Your First Summer Game" +description: "Build a multiplayer-native Summer game in GDScript with the Summer SDK, then continue to local testing and review." icon: "rocket" --- ## Multiplayer by default -Every Summercraft game is multiplayer-native. The default template is host-authoritative: the server runs the rules, clients render synced state, and a `min_players` of 1 means the same build is also a solo game. You do not write netcode — you write `SummerGame` hooks and synced state, and the platform runtime carries them over its host-authoritative transport (ENet today; the `SummerMultiplayerPeer` transport with stock `@rpc`/`MultiplayerSynchronizer` compatibility is a published contract still being built in the engine fork). +The Summer SDK contract is multiplayer-native. The default example is host-authoritative: +the server runs the rules, clients render synced state, and a +`min_players` of 1 means the same build is also a solo game. You write `SummerGame` hooks +and synced state in GDScript; the Summer SDK defines the creator-facing contract. +The SDK/runtime surfaces on this page are scaffolded, not a deployed hosted gameplay path. +Check [platform capability status](/knowledge-base/source-status#platform-capability-status) +before making production promises. What you build here: @@ -110,11 +116,15 @@ func score_point(player) -> void: ## Step 5: Local Test -Use the two-process test runner flow: +Start with the canonical one-process Summer Engine smoke checks. If your starter project +includes the optional loopback runner, also use it to exercise a local server/client path: -- starts local headless server, -- starts client and connects to localhost, -- validates real multiplayer behavior. +- the canonical agent prompt validates import, parsing, smoke execution, banned patterns, + and pack contents with local SDK stubs; +- the optional loopback runner starts a local headless server and connects a client to + localhost; +- neither path validates production platform services, ticket redemption, or hosted + matchmaking. Guide: [Testing Your Game Locally](/api-reference/summer-sdk/testing-your-game-locally). Building outside Summer Engine (agent/CLI workflow)? The same page covers stub-based validation, and the [/agent-setup](/agent-setup) prompt automates it. @@ -125,7 +135,9 @@ Export a game-only `.pck`, then publish it through the live release API (create - [Exporting and Uploading Your Game](/api-reference/summer-sdk/exporting-and-uploading-your-game) - [Submission Guide](/api-reference/summer-sdk/submission-guide) -A human reviews every release. Approval publishes the game; the release becomes downloadable through the authenticated download endpoint. Browser and desktop-shell play of uploaded Godot games are not live yet. +A human reviews every release. Approval assigns `published` catalog status and makes the +release available under the documented authenticated download rules. Browser and +desktop-shell play of uploaded Summer games are not live yet. ## What "Done" Looks Like @@ -133,5 +145,15 @@ A human reviews every release. Approval publishes the game; the release becomes - [ ] Server authority enforced (`Summer.is_server()`). - [ ] Player-visible state comes from `set_synced`. - [ ] Works with 1 player and with several (`min_players: 1`). -- [ ] Local test runner path passes. +- [ ] Canonical Summer Engine smoke checks pass. +- [ ] Optional local loopback runner passes when present. - [ ] Export contains only game files; release enters `pending_review`. + + + + Return to project creation and the GDScript starting point. + + + Use the lifecycle hub to select the SDK systems your game needs. + + diff --git a/api-reference/summer-sdk/exporting-and-uploading-your-game.mdx b/api-reference/summer-sdk/exporting-and-uploading-your-game.mdx index 8a4c74c..d09afe9 100644 --- a/api-reference/summer-sdk/exporting-and-uploading-your-game.mdx +++ b/api-reference/summer-sdk/exporting-and-uploading-your-game.mdx @@ -1,17 +1,19 @@ --- -title: "Exporting and Uploading Your Game" -description: "Export a game-only .pck, then publish it through the live Summercraft release API: create game, presigned upload, server-verified finalize, manual review." +title: "Export and Upload Your Summer Game" +description: "Use Summer Engine to export a game-only .pck, then upload it through the live release API for human review." icon: "upload" --- ## Goal -Produce a `.pck` that contains only your game content, then publish it for review. There are two live publish paths: +Produce a `.pck` that contains only your game content, then submit it for review. There are +two deployed submission paths: - **The release API** (this page, recommended — what agents and CI use): four HTTP calls against `https://summercraft.ai`, artifact limit 512 MiB. - **The browser submit page** at [summercraft.ai/submit](https://summercraft.ai/submit): upload `.pck` + `manifest.json` in the UI, artifact limit 2 GB, runs an automated static scanner at upload time. See [Submission Guide](/api-reference/summer-sdk/submission-guide). -Both end in the same place: a human reviews the release before anything goes live. No auto-publish. +Both end in the same place: a human reviews the release before its catalog status can +become `published`. No auto-publish, and no player-facing playback yet. Working agent-first? [/agent-setup](/agent-setup) has a paste-prompt that walks any coding agent through this entire page, including a verified project template. @@ -27,10 +29,11 @@ Use a preset that ships your game and nothing else: - `exclude_filter` covering infrastructure and local stubs (`sdk/*`, plus `core/*,server/*,client/*` if you develop inside the Summer Engine starter template) - `script_export_mode=0` — ship GDScript as readable text so review can read your source -Export headlessly (no export templates required for a pack export): +Export with the same Summer Engine executable used for local testing (no export templates +are required for a pack export): ```bash -godot --headless --path . --export-pack "Summer Game PCK" game.pck +"$SUMMER_ENGINE" --headless --path . --export-pack "Summer Game PCK" game.pck ``` Checks after export: @@ -68,7 +71,8 @@ Validate everything locally before touching these endpoints. ## 4) `POST /api/games/engine` — create the game record -Once per game, not per version. Creates a Godot game (`kind: "engine"`) as metadata; the artifact arrives through the release endpoints. +Once per game, not per version. Creates a Summer game record (`kind: "engine"`) as +metadata; the artifact arrives through the release endpoints. Request: @@ -162,7 +166,11 @@ Success `201`: } ``` -The release is **not live**: it serves only after an admin approves it and the game's active version moves. On a `checksum_mismatch` or `size_mismatch` the stored object is deleted (so the write-once key is free again for a correct re-upload) and no row is written. +The release is `pending_review`: it is available only to the owner and admins until an +admin approves it and the game's active version moves. Approval changes catalog/download +access; it does not make the game playable on the platform. On a `checksum_mismatch` or +`size_mismatch` the stored object is deleted (so the write-once key is free again for a +correct re-upload) and no row is written. Errors: `401 sign_in_required` · `400 invalid_request` · `404 game_not_found_or_forbidden` · `409 not_a_godot_game` · `409 no_upload_intent` (call upload-url first; declarations must match it exactly) · `409 artifact_missing` (the PUT never landed) · `413 artifact_too_large` · `400 size_mismatch` · `400 checksum_mismatch` · `409 version_exists` · `429 rate_limited` (its own budget) · `503 r2_not_configured` · `502 finalize_failed`. @@ -183,10 +191,17 @@ Success `200`: ## 9) Review lifecycle 1. Finalize → release `pending_review`; the admin queue is pinged. -2. A human reviews. Approval re-verifies the stored bytes against the checksum pinned at finalize, then points the game's active version at the release and publishes the game. Rejection records a reason, shown to you on [summercraft.ai/creator](https://summercraft.ai/creator); a live game stays live on its previously approved release. +2. A human reviews. Approval re-verifies the stored bytes against the checksum pinned at + finalize, then points the game's active version at the release and assigns `published` + catalog status. Rejection records a reason, shown to you on + [summercraft.ai/creator](https://summercraft.ai/creator); the previously approved catalog + release stays active. 3. There is no automated publish, no runtime sandbox yet, and no guaranteed review time. -**What approval does not (yet) mean:** browser play, desktop shell play, and hosted game servers for uploaded Godot games are not live. Approved releases are distributed through the authenticated download endpoint; play surfaces are in development. +**What approval does not (yet) mean:** browser play, desktop shell play, and hosted game +servers for uploaded Summer games are not live. Approved releases are distributed through +the authenticated download endpoint; play surfaces are in development. The canonical table +is [platform capability status](/knowledge-base/source-status#platform-capability-status). ## 10) Updating your game @@ -198,10 +213,11 @@ Releases are immutable — updating means a new one: Each update goes through review again. -## Related Docs - -- [Agent Setup](/agent-setup) — the paste-prompt that automates this page -- [Submission Guide](/api-reference/summer-sdk/submission-guide) — review lifecycle and the browser flow -- [Testing Your Game Locally](/api-reference/summer-sdk/testing-your-game-locally) -- [manifest.json Reference](/api-reference/summer-sdk/manifest-json-reference) -- [Banned APIs Reference](/api-reference/summer-sdk/banned-apis-reference) + + + Return to the Summer Engine validation loop. + + + Choose a submission path and understand review states. + + diff --git a/api-reference/summer-sdk/guides/making-a-2d-game-multiplayer.mdx b/api-reference/summer-sdk/guides/making-a-2d-game-multiplayer.mdx index e9ef021..1af42af 100644 --- a/api-reference/summer-sdk/guides/making-a-2d-game-multiplayer.mdx +++ b/api-reference/summer-sdk/guides/making-a-2d-game-multiplayer.mdx @@ -6,12 +6,16 @@ icon: "square" ## Platform Framing -You are not building a “Summercraft game type.” -You are building a 2D game in Summer/Godot and integrating the Summercraft platform layer: +You are building a 2D **Summer game** in **GDScript** and integrating the **Summer SDK** +platform contract: -- multiplayer runtime, -- server authority, -- data/economy/teams/score modules. +- host-authoritative game rules and synced state, +- player, data, economy, teams, and score interfaces, +- a submission contract for review. + +The hosted multiplayer runtime, automatic matchmaking, and player-facing play surfaces are +not production-live yet. See the canonical +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## Recommended Player Model @@ -97,4 +101,5 @@ Use only what you need: - [ ] 2D state is synced via `set_synced`. - [ ] Client only renders synced values. - [ ] Required manifest fields valid. -- [ ] Local test runner flow passes. +- [ ] Canonical Summer Engine smoke checks pass. +- [ ] Optional local loopback runner passes when present. diff --git a/api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer.mdx b/api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer.mdx index a72e2e4..ca785c3 100644 --- a/api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer.mdx +++ b/api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer.mdx @@ -6,15 +6,19 @@ icon: "layout-grid" ## Platform Framing -Turn-based and card games are first-class on Summercraft. +The Summer SDK contract supports turn-based and card-game models without requiring a 3D +character template. The hosted runtime and player-facing play surfaces are not +production-live yet. Use: - `SummerGame` for match lifecycle, -- `SummerPlayer` for connected player identity + synced state, +- `SummerPlayer` for the future player-identity and synced-state shape, - `set_synced` for turn/board/hand summaries. -No 3D character system is required. +No 3D character system is required. This is a scaffolded contract example; it does not run +on a production hosted runtime today. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## Minimal Player Setup diff --git a/api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector.mdx b/api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector.mdx index e32ffcb..65c5ab8 100644 --- a/api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector.mdx +++ b/api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector.mdx @@ -1,6 +1,6 @@ --- title: "Game Guide: Multiplayer FFA (Coin Collector)" -description: "How to make a 3D action game multiplayer on Summercraft using the optional SummerCharacter3D template." +description: "Build a 3D Summer game against the multiplayer SDK contract using the optional SummerCharacter3D template." icon: "swords" --- @@ -15,6 +15,9 @@ This is a full `SummerGame` example for a multiplayer free-for-all: - End-of-round winner announcement This guide uses the optional 3D template path (`player.tscn` rooted with `SummerCharacter3D`). +It demonstrates the SDK contract; it does not prove hosted runtime, matchmaking, or +player-facing play deployment. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## Scene Setup diff --git a/api-reference/summer-sdk/guides/multiplayer-persistence-rpg.mdx b/api-reference/summer-sdk/guides/multiplayer-persistence-rpg.mdx index 182b526..0aa4bb0 100644 --- a/api-reference/summer-sdk/guides/multiplayer-persistence-rpg.mdx +++ b/api-reference/summer-sdk/guides/multiplayer-persistence-rpg.mdx @@ -1,17 +1,22 @@ --- -title: "Game Guide: Multiplayer with Persistence (RPG/Quest)" -description: "How to add persistence and economy to a multiplayer game using Summer.data and Summer.economy." +title: "Contract Example: RPG Persistence and Economy" +description: "Author an RPG against the scaffolded Summer.data and Summer.economy interfaces without implying a live backend." icon: "database" --- ## What This Guide Covers -This guide shows a persistent multiplayer game loop: +This guide is a future-contract example for a persistent multiplayer game loop: -- Load player save data on join -- Keep inventory, quest progress, and level in persistent storage -- Auto-save while players are connected -- Award and spend crafties with `Summer.economy` +- express player-data loads and saves, +- model inventory, quest progress, and level, +- issue periodic contract-level save calls, +- model awards and spends through `Summer.economy`. + +There is no production gameplay runtime, persistence backend, economy rail, autosave, or +backend flush for uploaded games today. This example is not executable proof of those +services. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## Input Actions Used @@ -150,7 +155,7 @@ func _load_player_snapshot(player) -> void: Summer.data.save(player, "quest_progress", quest_progress) func _save_player_snapshot(player) -> void: - # Data API is write-through to in-memory cache; backend flush is handled by SDK. + # Contract example only: no production persistence backend or flush is live. var level = Summer.data.load(player, "level") var xp = Summer.data.load(player, "xp") var inventory = Summer.data.load(player, "inventory") diff --git a/api-reference/summer-sdk/guides/team-based-game.mdx b/api-reference/summer-sdk/guides/team-based-game.mdx index 3fbab6d..39da9a6 100644 --- a/api-reference/summer-sdk/guides/team-based-game.mdx +++ b/api-reference/summer-sdk/guides/team-based-game.mdx @@ -1,18 +1,23 @@ --- -title: "Game Guide: Team-Based Multiplayer" -description: "How to build team modes with Summer.teams and Summer.score, independent of genre." +title: "Contract Example: Team-Based Multiplayer" +description: "Author a team-mode model against the scaffolded Summer.teams and Summer.score interfaces." icon: "users" --- ## What This Guide Covers -This guide implements a red-vs-blue team mode: +This guide illustrates a red-vs-blue team-mode contract: - Team creation with `Summer.teams.create` - Team assignment and auto-balance - Team-specific spawn points - Team score via `Summer.score.add_team` +The hosted gameplay runtime, player connection flow, team service, and score service are not +production-live. The code is an authoring example for scaffolded interfaces, not runtime +proof. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). + ## Scene Setup Create `team_arena.tscn`: @@ -133,7 +138,7 @@ func _award_team_score(team_id: String, scorer) -> void: ## Genre Note -This team logic works for: +This team model can be adapted for: - 3D objective shooters, - 2D objective games, diff --git a/api-reference/summer-sdk/manifest-json-reference.mdx b/api-reference/summer-sdk/manifest-json-reference.mdx index fb48048..ad6e03b 100644 --- a/api-reference/summer-sdk/manifest-json-reference.mdx +++ b/api-reference/summer-sdk/manifest-json-reference.mdx @@ -1,17 +1,23 @@ --- title: "manifest.json Reference" -description: "Complete manifest.json field reference for Summercraft games: required keys, optional keys, and validated examples." +description: "Complete manifest.json field reference for Summer games submitted to Summercraft: required keys, optional keys, and validated examples." icon: "file-json" --- ## Overview -Every Summercraft game must include a `manifest.json` file at the root of the game pack. +Every Summer game submitted to Summercraft must include a `manifest.json` file at the root +of the game pack. -The browser submission flow validates required keys and types at upload time; on the API release path the same requirements are enforced by the runtime and by human review. Two runtime rules worth knowing: +The browser submission flow validates required keys and types at upload time. The release API +records and verifies the artifact; human review currently checks the game contract. The +production runtime and automated sandbox are not live, so the runtime rules below are +contract requirements rather than deployed enforcement: - `entry_scene` and `player_scene` are resolved **relative to the manifest's location** in the pack (manifest at the root means `"main.tscn"` → `res://main.tscn`). -- The entry scene's root script must `extends SummerGame`, or the runtime refuses to load the pack. +- The entry scene's root script must `extends SummerGame` for the future runtime contract. + +See [platform capability status](/knowledge-base/source-status#platform-capability-status). ## Required Fields @@ -23,7 +29,7 @@ These fields are required by submission validation: | `name` | string | Yes | Display name shown in platform surfaces. | | `version` | string | Yes | Semantic or creator-defined version string (for example `1.0.0`). | | `summer_sdk` | string | Yes | SDK version your game targets (for example `1.0`). | -| `entry_scene` | string | Yes | Main scene path/name loaded by the runtime. | +| `entry_scene` | string | Yes | Main scene path/name designated for the runtime contract. | | `min_players` | number | Yes | Minimum players required before start flow. | | `max_players` | number | Yes | Maximum concurrent players for a match. | @@ -35,7 +41,7 @@ These fields are required by submission validation: | `description` | string | No | Short game description. | | `tags` | string[] | No | Category/search tags. | | `genre` | string | No | Primary genre label. | -| `tick_rate` | number | No | Server sync tick hint (if supported by runtime config). | +| `tick_rate` | number | No | Future server-sync hint; no production runtime currently consumes it. | | `preview` | string | No | Preview asset path/name for discovery UI. | | `input_actions` | object | No | Input action metadata for UX/docs tooling. | diff --git a/api-reference/summer-sdk/naming.mdx b/api-reference/summer-sdk/naming.mdx index 0cc513b..3efb7c7 100644 --- a/api-reference/summer-sdk/naming.mdx +++ b/api-reference/summer-sdk/naming.mdx @@ -12,6 +12,8 @@ games written against the old names need a mechanical pass. This page is the single authority for what each old identifier became. If another document, comment, or older repository disagrees with the table below, the table wins. +Names in this mapping define the SDK contract; they do not imply a live hosted runtime. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). Renaming is mechanical but not free. `summer_sdk` is a **required** manifest key and @@ -26,9 +28,10 @@ document, comment, or older repository disagrees with the table below, the table | `Crafty` | `Summer` | Autoload registered at `/root/Summer` | | `res://sdk/crafty.gd` | `res://sdk/summer.gd` | Autoload script path | -`Summer` is the Summercraft platform singleton available inside a published game. It is -unrelated to **Summer Engine**, the editor you build in — the two never appear in the -same script. +`Summer` is the singleton defined by the Summercraft runtime contract for an approved +Summer game. Production playback is not live yet, so “defined by the contract” is not a +claim that uploaded games can currently launch. The singleton is unrelated to **Summer +Engine**, the editor you build in — the two never appear in the same script. ## Classes diff --git a/api-reference/summer-sdk/production-launch-runbook.mdx b/api-reference/summer-sdk/production-launch-runbook.mdx index cf40100..e7e4b08 100644 --- a/api-reference/summer-sdk/production-launch-runbook.mdx +++ b/api-reference/summer-sdk/production-launch-runbook.mdx @@ -1,6 +1,6 @@ --- title: "Production Launch Runbook" -description: "Single linear runbook for fresh AI/dev sessions: integrate SDK, validate locally, export safely, submit, and ship." +description: "Single linear runbook for fresh AI/dev sessions: integrate the SDK contract, validate locally, export safely, and submit for review." icon: "check-check" --- @@ -11,9 +11,12 @@ This page is the shortest safe route from “new game” to “submitted for rev ## Current Publishing Checklist (Most Important) - Build your creator gameplay scripts in `GDScript` for the current Summercraft publishing flow. -- Submit one exportable `.pck` package plus `manifest.json`. -- Keep total `.pck` package size at or under **2 GB**. -- If your build is larger than 2 GB, email [founders@summerengine.com](mailto:founders@summerengine.com) for large-upload onboarding. +- **Recommended release API:** submit a game-only `.pck` containing `manifest.json`; size + must be 1 KiB–512 MiB. +- **Browser submission:** upload the `.pck` and a separate `manifest.json`; the browser path + accepts up to 2 GB and runs the static scanner at upload time. +- Choose one path before exporting. A 2 GB browser limit does not raise the release API's + 512 MiB limit. ## Step 1: Validate Project Contract @@ -43,13 +46,17 @@ Reference: ## Step 4: Local Runtime Validation -Run through test-runner flow and confirm: +Run the canonical Summer Engine smoke checks. If the starter project includes the optional +loopback runner, run that separately and confirm: -- server starts + client connects, +- local server starts + local client connects, - player join/leave stable, - gameplay loop runs for 10+ minutes, - reconnect path works. +This is local loopback validation only. It does not prove production ticket redemption, +platform hosting, matchmaking, or the runtime sandbox. + Reference: - [/api-reference/summer-sdk/testing-your-game-locally](/api-reference/summer-sdk/testing-your-game-locally) @@ -59,8 +66,12 @@ Reference: - use game-only `.pck` preset. - update include filter to game folder. - confirm exported `.pck` includes only intended content. -- confirm package size <= **2 GB**. -- if package size exceeds 2 GB, contact [founders@summerengine.com](mailto:founders@summerengine.com) for large-upload onboarding. +- for the recommended release API, confirm package size is 1 KiB–512 MiB and that + `manifest.json` is inside the pack; +- for browser submission, confirm the `.pck` is at most 2 GB and keep the matching + `manifest.json` as the second upload; +- if neither path fits, contact [founders@summerengine.com](mailto:founders@summerengine.com) + before spending a submission attempt. Reference: @@ -68,16 +79,15 @@ Reference: ## Step 6: Submission Validation -Upload: - -- `.pck` -- `manifest.json` +Choose one submission path: -Expect: +- **Release API:** create game → mint upload URL → PUT `.pck` → finalize; expect + `pending_review`. +- **Browser:** upload `.pck` + separate `manifest.json`; expect status `review`, a + submission id, and no static-analysis violations. -- status `review`, -- submission id returned, -- no static analysis violations. +Neither path makes the game playable. Follow the canonical +[platform capability status](/knowledge-base/source-status#platform-capability-status). Reference: diff --git a/api-reference/summer-sdk/submission-guide.mdx b/api-reference/summer-sdk/submission-guide.mdx index 6b6ee40..1fa4f50 100644 --- a/api-reference/summer-sdk/submission-guide.mdx +++ b/api-reference/summer-sdk/submission-guide.mdx @@ -1,6 +1,6 @@ --- -title: "Submission Guide" -description: "The two live ways to submit a Summercraft game, what validation runs where, and how the manual review lifecycle works." +title: "Submit Your Summer Game for Review" +description: "Choose a deployed submission path for a Summer game, understand validation and human review, then follow the update loop." icon: "upload" --- @@ -12,7 +12,7 @@ icon: "upload" - No [banned APIs or reserved paths](/api-reference/summer-sdk/banned-apis-reference) - [Local testing](/api-reference/summer-sdk/testing-your-game-locally) passes -## The two live submission paths +## The two deployed submission paths ### Path A — the release API (recommended; agents and CI) @@ -59,12 +59,20 @@ Every submission is reviewed by a human. No auto-publish. |---|---| | `draft` | Game record exists, nothing submitted or approved yet | | `pending_review` / `review` | A release/submission is in the admin queue | -| `published` | Approved — the game is live on the platform with that release active | +| `published` | Approved catalog state — the release is active and downloadable under the documented access rules, but not yet playable on the platform | | `rejected` | Rejected with a written reason, shown to you on [summercraft.ai/creator](https://summercraft.ai/creator) | -On Path A, approval re-verifies the stored artifact against the checksum pinned at finalize before the game's active version moves — verification at upload is not trusted at approval time. A rejected release never takes down a live game: the previously approved release stays active. +On Path A, approval re-verifies the stored artifact against the checksum pinned at finalize +before the game's active version moves — verification at upload is not trusted at approval +time. A rejected update leaves the previously approved catalog release active. -**Honest status:** approval publishes your game on the platform and makes its release downloadable through the authenticated [download endpoint](/api-reference/summer-sdk/exporting-and-uploading-your-game). Playing uploaded Godot games in the browser or the desktop shell, and hosted dedicated game servers, are not live yet — do not tell players otherwise. +**Honest status:** approval publishes your game on the platform and makes its release +downloadable through the authenticated +[download endpoint](/api-reference/summer-sdk/exporting-and-uploading-your-game). Playing +uploaded Summer games in the browser or desktop shell, and hosted dedicated game servers, +automatic matchmaking, and the runtime sandbox are not live yet — do not tell players +otherwise. See the canonical +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## Updating an existing game @@ -74,7 +82,8 @@ Released versions are immutable. 2. Bump `manifest.version`; on Path A pass the same new version string to upload-url and finalize. 3. Re-export and re-submit. -Each update goes through review again. A live game stays live while its update waits. +Each update goes through review again. The previously approved catalog release stays active +while its update waits. ## Common submission errors @@ -86,9 +95,11 @@ Path A errors are self-describing JSON (`{ "error", "detail" }`) — the `detail - `Invalid manifest. Required: id, name, version, summer_sdk, entry_scene, min_players, max_players` - `Static analysis failed` (with violations list) -## Related Docs - -- [Exporting and Uploading Your Game](/api-reference/summer-sdk/exporting-and-uploading-your-game) -- [Testing Your Game Locally](/api-reference/summer-sdk/testing-your-game-locally) -- [Banned APIs Reference](/api-reference/summer-sdk/banned-apis-reference) -- [Agent Setup](/agent-setup) + + + Return to pack creation and the release API reference. + + + Keep the identity stable, bump the version, retest, and resubmit. + + diff --git a/api-reference/summer-sdk/subsystems-signals.mdx b/api-reference/summer-sdk/subsystems-signals.mdx index e07e537..42edbdf 100644 --- a/api-reference/summer-sdk/subsystems-signals.mdx +++ b/api-reference/summer-sdk/subsystems-signals.mdx @@ -11,7 +11,12 @@ Subsystems are optional tools. Use only what your game needs. This is the core platform framing: - your game logic stays yours, -- Summer SDK subsystems provide multiplayer/platform primitives. +- Summer SDK subsystems define multiplayer/platform interfaces. + +These are contract reference examples. The hosted gameplay runtime, persistence/economy +rail, matchmaking, and dedicated servers are not production-live yet. Check +[platform capability status](/knowledge-base/source-status#platform-capability-status) +before treating a documented method as a deployed hosted service. ## Teams diff --git a/api-reference/summer-sdk/summer-game.mdx b/api-reference/summer-sdk/summer-game.mdx index abb984d..eff0be9 100644 --- a/api-reference/summer-sdk/summer-game.mdx +++ b/api-reference/summer-sdk/summer-game.mdx @@ -1,12 +1,12 @@ --- title: "SummerGame" -description: "Required base class that connects your game to the Summercraft platform lifecycle." +description: "Required base class for the Summer SDK game-lifecycle contract." icon: "workflow" --- ## What Is `SummerGame`? -Every game published on Summercraft must extend `SummerGame`. +Every Summer game submitted through the Summer SDK contract must extend `SummerGame`. `SummerGame` is the contract between your game and the platform: @@ -15,6 +15,9 @@ Every game published on Summercraft must extend `SummerGame`. - timer/match control helpers, - server-authoritative movement helper for 3D templates. +This page documents an interface, not production deployment status. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). + ```gdscript extends SummerGame ``` @@ -63,7 +66,7 @@ apply_default_movement(player, delta, move_speed := 7.0, gravity := 20.0) -> voi - `_game_init()`: one-time setup (spawn points, static data, signal wiring). - `_game_start()`: begin active match flow. - `_game_end()`: finalize and cleanup. -- `_player_joined(player)`: attach defaults for a newly connected player. +- `_player_joined(player)`: future-runtime hook for attaching defaults when a player joins. - `_player_left(player)`: cleanup per-player transient state. ## Server-Authoritative Pattern diff --git a/api-reference/summer-sdk/summer-player.mdx b/api-reference/summer-sdk/summer-player.mdx index eb12f4d..7200e7e 100644 --- a/api-reference/summer-sdk/summer-player.mdx +++ b/api-reference/summer-sdk/summer-player.mdx @@ -1,12 +1,15 @@ --- -title: "SummerPlayer" -description: "Game-agnostic player contract: peer identity, synced state, and server-read input. Use SummerCharacter3D for built-in 3D character behavior." +title: "SummerPlayer Contract" +description: "Scaffolded player interface for peer identity, synced state, and server-read input, plus an optional SummerCharacter3D template." icon: "user" --- ## What Is `SummerPlayer`? -`SummerPlayer` is the minimal platform contract for a connected player. +`SummerPlayer` is the scaffolded platform contract for a future connected-player record. +The production gameplay runtime and transport are not live, so the signatures below are +authoring targets rather than deployed connection behavior. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). It is intentionally game-agnostic: @@ -14,7 +17,8 @@ It is intentionally game-agnostic: - no required health model, - no required scene structure. -This is what allows card games, RTS, 2D games, and 3D action games to all use the same multiplayer platform. +The contract is intended to support card games, RTS, 2D games, and 3D action games without +forcing one movement model. ## Core Contract (Signatures) @@ -32,7 +36,7 @@ get_synced(key: String) -> Variant ## Identity -Player identity fields are assigned by the platform during connection: +The future runtime contract assigns identity fields during connection: ```gdscript var peer = player.peer_id @@ -75,7 +79,7 @@ var score = player.get_synced("score") # client or server ## Input (Read On Server) -Each connected player has an input proxy you read on the server: +The future runtime contract gives a connected player an input proxy for server-side reads: ```gdscript var move = player.input.movement @@ -93,7 +97,7 @@ if player.input.is_action_just_pressed("interact"): For 3D action games, use `SummerCharacter3D` in your `player.tscn`. -It includes: +The template contract includes: - `CharacterBody3D` movement-compatible node type, - health fields (`health`, `max_health`, `is_alive`), diff --git a/api-reference/summer-sdk/summer.mdx b/api-reference/summer-sdk/summer.mdx index 1d629e6..9fc0cc2 100644 --- a/api-reference/summer-sdk/summer.mdx +++ b/api-reference/summer-sdk/summer.mdx @@ -1,14 +1,18 @@ --- -title: "Summer Singleton" -description: "Platform entrypoint for multiplayer runtime features: lifecycle helpers, players, spawning, context checks, and subsystems." +title: "Summer Singleton Contract" +description: "Scaffolded Summer SDK entrypoint for lifecycle helpers, players, spawning, context checks, and subsystem interfaces." icon: "box" --- ## What Is `Summer`? -`Summer` is the autoload singleton exposed by the SDK. +`Summer` is the autoload singleton defined by the Summer SDK contract. -Use it for platform-level operations that are not tied to one player object. +The methods below are scaffolded interface examples. Uploaded games cannot currently launch +in a production platform runtime, and hosted multiplayer, persistence, economy, matchmaking, +and sandboxing are not live. Use this page to author against the future contract, not as +evidence that a hosted service exists. See +[platform capability status](/knowledge-base/source-status#platform-capability-status). ## `Summer` vs Player Object @@ -72,11 +76,12 @@ if Summer.is_server(): update_game_state() ``` -Use `is_server()` and `is_client()` to keep gameplay authority on the server. +The contract uses `is_server()` and `is_client()` to express server authority. Local stubs +and loopback tests do not prove production authority enforcement. ## Subsystems -`Summer` exposes optional subsystem handles: +The `Summer` contract defines optional subsystem handles: - `Summer.teams` - `Summer.score` diff --git a/api-reference/summer-sdk/testing-your-game-locally.mdx b/api-reference/summer-sdk/testing-your-game-locally.mdx index 902f3d2..96ae040 100644 --- a/api-reference/summer-sdk/testing-your-game-locally.mdx +++ b/api-reference/summer-sdk/testing-your-game-locally.mdx @@ -1,6 +1,6 @@ --- -title: "Testing Your Game Locally" -description: "Press play, launch server+client automatically, and test your Summercraft game with production-like runtime behavior." +title: "Test Your Summer Game Locally" +description: "Use Summer Engine smoke checks and an optional local loopback runner; understand what neither path proves about production." icon: "flask-conical" --- @@ -8,45 +8,71 @@ icon: "flask-conical" Local testing should match production behavior as closely as possible. -In Summercraft, a published game runs on: +The canonical agent workflow exercises: -- the same Summer/Godot runtime, -- the same Summer SDK APIs, -- server-authoritative networking. +- Summer Engine, +- local Summer SDK stubs, +- project import, parsing, smoke execution, banned-pattern checks, and pack contents. -That is why the recommended workflow launches a local headless server and a client, instead of testing gameplay logic in a client-only setup. +It does **not** exercise the production Summer SDK runtime, ticket redemption, platform +services, or a destination game server. The separate starter-template loopback runner can +exercise a local server/client path, but it still does not prove those production paths. +See [platform capability status](/knowledge-base/source-status#platform-capability-status). -## Default Local Workflow +## Optional starter-template loopback workflow -Use the starter template test runner: +If your Summer Engine starter project includes its loopback runner: - `test_runner.gd` launches a headless server process. - It waits for startup. - It launches/loads the client flow and connects to `localhost:7777`. -This gives you a real multiplayer loop in one click. +This gives you a local multiplayer loop. It does not connect to Summercraft, redeem a +launch ticket, or validate hosted matchmaking, hosting, or sandboxing. - If it works in this local test-runner flow, it is much closer to how it will behave in production than single-process editor-only testing. + Use the loopback runner when it is present, but report it as local loopback validation, + not production-like or end-to-end platform validation. -## Building Outside Summer Engine (Agent / CLI Workflow) +## Agent and CLI workflow with Summer Engine -The test runner above ships with Summer Engine's Summercraft template. If you are building standalone — a coding agent, CI, or a bare Godot 4.5 install — the real SDK is not on disk, so full runtime testing is not available locally. What works instead, verified with Godot 4.5.1: +The [/agent-setup](/agent-setup) prompt installs and invokes Summer Engine directly, +supplies local SDK stubs for parsing, and runs a single-process import/smoke pass plus +banned-API and pack-content checks. It does not invoke the starter-template loopback runner. -1. Keep local **SDK stubs** in `sdk/` (excluded from export) that mirror the documented class surfaces, so every script parses. The [/agent-setup](/agent-setup) prompt contains ready-made stubs. -2. **Headless smoke run:** `godot --headless --path . --quit-after 120` must exit cleanly with no `SCRIPT ERROR` lines. A parse error here is the same error that will make the platform runtime refuse your pack. -3. **Banned-API self-check:** grep your game scripts (not the stubs) against the [blocked pattern list](/api-reference/summer-sdk/banned-apis-reference) before every upload — the API path has no upload-time scanner, so a violation costs you a manual review round-trip. -4. **Pack-content check:** export, then confirm the `.pck` stores only your game files plus `manifest.json` (the export log lists every stored file). +1. Keep local **SDK stubs** in `sdk/` and exclude them from export. +2. Run Summer Engine headlessly and fail on any `SCRIPT ERROR`. +3. Check game scripts against the [blocked pattern list](/api-reference/summer-sdk/banned-apis-reference). +4. Export and confirm the `.pck` contains only game files plus `manifest.json`. -This validates structure, parsing, and packaging — not gameplay against the real SDK. The review process runs your game on the real runtime; keep gameplay logic simple enough to survive the difference, and treat the smoke run as the floor, not the ceiling. +This validates structure, parsing, and packaging — not gameplay against a production Summer +SDK runtime. Review is currently human; uploaded games are not executed by a production +runtime or automated sandbox. Treat the smoke run as a structural floor, not platform or +gameplay proof. -## What Happens Under The Hood +## Advanced compatibility escape hatch -When you run the test runner: +On locked CI infrastructure where Summer Engine cannot be installed, an operator may supply +a bare upstream Godot binary for syntax, import, and pack-format checks. This is an advanced +compatibility path, not creator onboarding: + +- match the **current upstream base** shown in the + [generated compatibility reference](/reference/compatibility); +- do not treat that number as a Summer Engine product version or a measured project minimum; +- set `UPSTREAM_ENGINE` explicitly rather than silently falling back from Summer Engine; +- do not claim this validates Summer SDK runtime behavior. + +```bash +"$UPSTREAM_ENGINE" --headless --path . --quit-after 120 +``` + +## What the optional loopback runner does + +When you run a starter project that includes the loopback runner: 1. The runner detects your game slug from `manifest.json`. -2. It starts Summer/Godot in headless mode with server args: +2. It starts Summer Engine in headless mode with server args: - `--server` - `--game-id ` - `--port 7777` @@ -67,15 +93,15 @@ To make local testing reliable: You have two practical options: -### Option A: First client via test runner, additional clients from editor +### Option A: First client via an available loopback runner, additional clients from editor -1. Start the first instance with test runner (starts server + client). +1. Start the first instance with the loopback runner (starts server + client). 2. Launch another editor instance. 3. Run the client scene and connect to `localhost:7777` using your quick-connect flow. ### Option B: Team testing on same network -1. One teammate runs the test runner (hosts local server). +1. One teammate runs the loopback runner (hosts local server). 2. Share host IP and port. 3. Other teammates run client mode and connect to that host. @@ -120,8 +146,11 @@ Check: - no editor-only assumptions in gameplay code, - no banned/blocked APIs used by generated code. -## Related Docs - -- [manifest.json Reference](/api-reference/summer-sdk/manifest-json-reference) -- [Exporting and Uploading Your Game](/api-reference/summer-sdk/exporting-and-uploading-your-game) -- [Banned APIs Reference](/api-reference/summer-sdk/banned-apis-reference) + + + Return to the capability and lifecycle hub. + + + Produce and verify a game-only pack. + + diff --git a/api-reference/summer-sdk/updating-your-game.mdx b/api-reference/summer-sdk/updating-your-game.mdx new file mode 100644 index 0000000..d959a31 --- /dev/null +++ b/api-reference/summer-sdk/updating-your-game.mdx @@ -0,0 +1,30 @@ +--- +title: "Update an Existing Summer Game" +description: "Keep a Summer game identity stable, bump its version, retest with Summer Engine, and submit a new immutable release for review." +icon: "refresh-cw" +--- + +Released artifacts are immutable. An update is a new reviewed release for the same +**Summer game**, not a replacement of the bytes already approved. Keep the **Summer SDK** +contract and stable identifiers while changing the versioned game content. + +## Update loop + +1. Keep `manifest.id` stable. On the release API path, reuse the same `gameId`. +2. Bump `manifest.version`; pass the same version to upload-url and finalize. +3. Make the GDScript or asset changes needed for the update. +4. Run the [Summer Engine local test flow](/api-reference/summer-sdk/testing-your-game-locally). +5. Re-export the game-only `.pck` and recompute its SHA-256 and byte count. +6. Submit the new version through the [review flow](/api-reference/summer-sdk/submission-guide). + +Each update goes through human review. The previously approved release stays active while +the update is pending or if the new release is rejected. + + + + Review submission paths and platform states. + + + Return to the test loop before exporting another release. + + diff --git a/compatibility/SUMMER_ENGINE_COMPATIBILITY.source.txt b/compatibility/SUMMER_ENGINE_COMPATIBILITY.source.txt new file mode 100644 index 0000000..e8c1a1c --- /dev/null +++ b/compatibility/SUMMER_ENGINE_COMPATIBILITY.source.txt @@ -0,0 +1,51 @@ + + +# Summer Engine compatibility reference + +## Product identity + +**Summer Engine** is the product. Its release identity is platform-staggered and is not the +same thing as the upstream technical base. + +| Platform | Summer Engine release | Authoritative source | +|---|---:|---| +| macOS | `0.5.58` | `modules/1summer_engine/summer_version.h` → `SUMMER_VERSION_MACOS` | +| Windows | `0.5.59` | `modules/1summer_engine/summer_version.h` → `SUMMER_VERSION_WINDOWS` | + +## Upstream technical base + +| Field | Value | +|---|---| +| Current upstream base | `4.6.1` (`stable`) | +| Planned next upstream base | `4.7.1` | +| Planned target evidence | User-approved decision recorded in `compatibility/summer-engine.json` | +| Upstream policy | `continuous-upstream` | +| Build evidence | `version.py` | + +The upstream base is a technical compatibility and lineage fact. It is not the Summer Engine +product name or product release version. Summer follows upstream continuously; neither the +current nor planned upstream number is a permanent Summer identity. + +## Runtime and project compatibility + +- Runtime compatibility: Unmeasured; no version is claimed. +- Minimum project compatibility: Unmeasured; no version is claimed. +- Recommended project compatibility: Unmeasured; no version is claimed. + +Unmeasured values are intentionally `null` in the machine-readable contract. Do not infer a +minimum from `project.godot`, copied prose, or an older skill. + +## Language boundary + +- Creator product: **Summer Engine** +- Creator output: **Summer game** +- Default creator language: **GDScript** +- Technical compatibility product: **Godot Engine** +- Rule: Use Godot references for technical compatibility, migration, upstream contribution, attribution, and legal contexts—not as the Summer product identity. + +## Verification + +Verified on `2026-07-30` against: + +- `modules/1summer_engine/summer_version.h` +- `version.py` diff --git a/compatibility/source.json b/compatibility/source.json new file mode 100644 index 0000000..530769d --- /dev/null +++ b/compatibility/source.json @@ -0,0 +1,13 @@ +{ + "schemaVersion": 1, + "repository": "SummerEngine/SummerEngine", + "commit": "b44e47792819fb402a2984cd79c7023cc8aa57f8", + "manifestPath": "compatibility/summer-engine.json", + "manifestGitBlobSha": "2cd944bb2fea49930fffd63a1db9f4a27e57b41f", + "manifestSha256": "741bd8237868a395cad89bfa1c5a70ef5ca2cfcc829674047cab1b9e180c054a", + "generatedReferencePath": "compatibility/generated/SUMMER_ENGINE_COMPATIBILITY.md", + "generatedReferenceSnapshot": "compatibility/SUMMER_ENGINE_COMPATIBILITY.source.txt", + "generatedReferenceGitBlobSha": "e8c1a1cbcde450b2ce700e13d98ab4a67c60d9fb", + "generatedReferenceSha256": "6d92477fcffd2a0ff7ab8d665c542b9669f7514fa9c2e3f7d97cbadcf2a83963", + "syncedOn": "2026-07-30" +} diff --git a/compatibility/summer-engine.json b/compatibility/summer-engine.json new file mode 100644 index 0000000..2cd944b --- /dev/null +++ b/compatibility/summer-engine.json @@ -0,0 +1,68 @@ +{ + "schemaVersion": 1, + "product": { + "name": "Summer Engine", + "releaseIdentity": { + "state": "measured", + "strategy": "platform-staggered", + "source": "modules/1summer_engine/summer_version.h", + "platforms": { + "macos": { + "displayName": "macOS", + "define": "SUMMER_VERSION_MACOS" + }, + "windows": { + "displayName": "Windows", + "define": "SUMMER_VERSION_WINDOWS" + } + } + } + }, + "upstreamBase": { + "name": "Godot Engine", + "current": { + "version": "4.6.1", + "source": "version.py" + }, + "plannedNext": { + "state": "planned", + "version": "4.7.1", + "evidence": [ + "compatibility/summer-engine.json" + ] + }, + "policy": "continuous-upstream", + "productIdentity": false + }, + "runtimeCompatibility": { + "state": "unmeasured", + "version": null, + "evidence": [] + }, + "projectCompatibility": { + "minimum": { + "state": "unmeasured", + "version": null, + "evidence": [] + }, + "recommended": { + "state": "unmeasured", + "version": null, + "evidence": [] + } + }, + "verification": { + "verifiedOn": "2026-07-30", + "evidence": [ + "modules/1summer_engine/summer_version.h", + "version.py" + ] + }, + "languagePolicy": { + "creatorProduct": "Summer Engine", + "creatorGame": "Summer game", + "defaultCreatorLanguage": "GDScript", + "technicalCompatibilityProduct": "Godot Engine", + "godotUsage": "Use Godot references for technical compatibility, migration, upstream contribution, attribution, and legal contexts—not as the Summer product identity." + } +} diff --git a/docs.json b/docs.json index d0f5c3d..9d39ee9 100644 --- a/docs.json +++ b/docs.json @@ -45,11 +45,32 @@ "icon": "book-open", "groups": [ { - "group": "Getting Started", + "group": "Start here", "pages": [ "index", + "essentials/installation", "quickstarts/fresh-project", - "quickstarts/existing-godot", + "api-reference/summer-sdk/build-your-first-summer-game" + ] + }, + { + "group": "Summer SDK", + "pages": [ + "api-reference/summer-sdk" + ] + }, + { + "group": "Test and publish", + "pages": [ + "api-reference/summer-sdk/testing-your-game-locally", + "api-reference/summer-sdk/exporting-and-uploading-your-game", + "api-reference/summer-sdk/submission-guide", + "api-reference/summer-sdk/updating-your-game" + ] + }, + { + "group": "Other ways to start", + "pages": [ "quickstarts/ai-game-dev", "quickstarts/web-game", "quickstarts/pc-game", @@ -63,7 +84,6 @@ { "group": "Essentials", "pages": [ - "essentials/installation", "essentials/authentication", "essentials/account-billing", "essentials/pricing", @@ -102,9 +122,8 @@ ] }, { - "group": "Engine Migration", + "group": "Other Engine Migration", "pages": [ - "migration/godot", "quickstarts/unity-migration", "quickstarts/unreal-migration" ] @@ -116,16 +135,6 @@ "automation/authoring" ] }, - { - "group": "Extending Summer", - "pages": [ - "extending/overview", - "extending/editor-plugins", - "extending/gdextension", - "extending/modules", - "extending/plugin-library" - ] - }, { "group": "Reference", "pages": [ @@ -187,34 +196,47 @@ "icon": "code", "groups": [ { - "group": "Agent Setup", - "pages": [ - "agent-setup", - "agent-setup/prompt" - ] - }, - { - "group": "Creating Games on Summercraft", + "group": "Summer SDK reference", "pages": [ - "api-reference/summer-sdk", - "api-reference/summer-sdk/naming", "api-reference/summer-sdk/summer", "api-reference/summer-sdk/summer-game", "api-reference/summer-sdk/summer-player", "api-reference/summer-sdk/subsystems-signals", - "api-reference/summer-sdk/build-your-first-summer-game", "api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector", "api-reference/summer-sdk/guides/multiplayer-persistence-rpg", "api-reference/summer-sdk/guides/team-based-game", "api-reference/summer-sdk/guides/making-a-2d-game-multiplayer", - "api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer", + "api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer" + ] + }, + { + "group": "Automation", + "pages": [ + "agent-setup", + "agent-setup/prompt", + "api-reference/summer-sdk/ai-agent-playbook" + ] + }, + { + "group": "Reference", + "pages": [ "api-reference/summer-sdk/manifest-json-reference", - "api-reference/summer-sdk/production-launch-runbook", - "api-reference/summer-sdk/submission-guide", - "api-reference/summer-sdk/testing-your-game-locally", - "api-reference/summer-sdk/exporting-and-uploading-your-game", "api-reference/summer-sdk/banned-apis-reference", - "api-reference/summer-sdk/ai-agent-playbook" + "api-reference/summer-sdk/naming", + "reference/compatibility", + "api-reference/summer-sdk/production-launch-runbook" + ] + }, + { + "group": "Migration and extensions", + "pages": [ + "quickstarts/existing-godot", + "migration/godot", + "extending/overview", + "extending/editor-plugins", + "extending/gdextension", + "extending/modules", + "extending/plugin-library" ] }, { diff --git a/essentials/faq.mdx b/essentials/faq.mdx index 2acce11..781aa0d 100644 --- a/essentials/faq.mdx +++ b/essentials/faq.mdx @@ -23,8 +23,8 @@ Common questions about Summer, organized by topic. Each question links to a deta ## Technical - Yes. Open your project and continue working with AI assistance. No conversion required. - They work perfectly. Open them in Summer and continue development. All scenes, scripts, and plugins work as before. + Summer uses familiar formats, but project compatibility ranges are not fully measured. Commit first and verify imports, plugins, native extensions, and exports. + Open a committed copy in Summer Engine and review the first import. Version-sensitive plugins and native extensions need explicit testing. Claude, GPT-5, Gemini, Meshy, ElevenLabs, and more. Choose your models in settings. Great for prototyping and indie games. Learn the tradeoffs and when to use human artists. Yes. Describe what you want and Summer Engine writes the code. AI game dev and vibe coding for games. diff --git a/essentials/installation.mdx b/essentials/installation.mdx index 70b6045..20377ad 100644 --- a/essentials/installation.mdx +++ b/essentials/installation.mdx @@ -1,22 +1,9 @@ --- -title: "Installation" -description: "Download and install Summer on your machine" +title: "Install Summer Engine" +description: "Install Summer Engine on macOS or Windows, verify the editor, and continue to your first Summer game." icon: "download" --- -## Project Compatibility - -Summer works with existing projects, tutorials, libraries, and extensions. Open your projects directly. No conversion needed. - -**What works out of the box:** -- All standard project files and structures -- Official documentation and tutorials -- Third-party libraries and plugins -- Community assets and tools -- Export templates for web, desktop, and mobile - -**Version tracking:** Summer maintains compatibility with current project formats. - ## System Requirements Summer runs on Windows and macOS with the following minimum requirements: @@ -26,14 +13,14 @@ Summer runs on Windows and macOS with the following minimum requirements: - **Storage**: 2GB available space - **Graphics**: OpenGL 3.3 support -## Download Summer +## Download Summer Engine - Get the latest version of Summer from our website + Get the latest Summer Engine installer from our website. ### Alternative: Install via CLI @@ -41,10 +28,16 @@ Summer runs on Windows and macOS with the following minimum requirements: If you use Cursor, Claude Code, or any MCP-compatible AI tool, you can install Summer Engine from the command line: ```bash -npx summer-engine install +npx -y summer-engine@latest install ``` -This downloads and installs the engine to your system (macOS: `/Applications/Summer.app`, Windows: default install location). No npm global install required. `npx` runs it on demand. After install, run `npx summer-engine login` and `npx summer-engine run` to get started. +This downloads and installs Summer Engine (macOS: `/Applications/Summer.app`; Windows: +the installer-selected location). No global npm install is required. After installation: + +```bash +npx -y summer-engine@latest login +npx -y summer-engine@latest run +``` For MCP setup (connecting your IDE to Summer Engine), see [MCP Setup](/mcp/setup). @@ -57,8 +50,8 @@ For MCP setup (connecting your IDE to Summer Engine), see [MCP Setup](/mcp/setup Double-click the downloaded file and follow the installation wizard. - - Open Summer from your applications folder or start menu. + + Open Summer Engine from your applications folder or Start menu. Click "New Project" and choose a template to get started. @@ -71,16 +64,21 @@ Once installed, you can verify everything is working by: 1. Opening Summer 2. Creating a new project from a template -3. Testing the AI chat functionality with a simple request like "Add a cube to the scene" +3. Testing the AI chat with a request such as “Add a cube to the scene” If you encounter any issues, check our [troubleshooting guide](/desktop/troubleshooting) or reach out on [Discord](https://discord.gg/yUpgtxnZky). -## Next Steps +## Existing-project compatibility - - Learn how to use AI to build your first game elements - +Summer Engine uses standard project files. Compatibility, migration, extensions, and the +measured upstream base live in the dedicated [compatibility reference](/reference/compatibility). +Do not infer a project-version minimum from a copied setup guide. + + + + Review the complete creator journey. + + + Create a project and begin with GDScript. + + diff --git a/extending/gdextension.mdx b/extending/gdextension.mdx index 933aeaf..67ad2ef 100644 --- a/extending/gdextension.mdx +++ b/extending/gdextension.mdx @@ -1,6 +1,6 @@ --- title: "GDExtension" -description: "Summer runs stock Godot 4.6.1 GDExtension binaries unmodified. The ABI is byte-identical to upstream, unsigned third-party libraries load in the shipped macOS editor, and the only real friction is that godot-cpp has no 4.6 branch." +description: "Summer's current GDExtension ABI matches its pinned upstream 4.6.1 base; learn the verified binary path, platform limits, and the current godot-cpp branch gap." icon: "puzzle" --- diff --git a/extending/modules.mdx b/extending/modules.mdx index ad32b3d..45a7b43 100644 --- a/extending/modules.mdx +++ b/extending/modules.mdx @@ -1,6 +1,6 @@ --- title: "Custom Modules" -description: "How Summer itself is built as a Godot C++ module, why external developers cannot add one, and what to use instead. Includes the init-level and TOOLS_ENABLED discipline that decides whether a class survives into an exported game." +description: "How Summer's internal C++ module is built, why external developers cannot add one, and what to use instead. Includes the init-level and TOOLS_ENABLED discipline that decides whether a class survives into an exported game." icon: "boxes" --- diff --git a/extending/overview.mdx b/extending/overview.mdx index 20764c3..4c63366 100644 --- a/extending/overview.mdx +++ b/extending/overview.mdx @@ -4,9 +4,10 @@ description: "Summer is an extensible engine. Three ways to add capability: GDSc icon: "blocks" --- -Summer is a fork of Godot 4.6.1-stable with an unmodified `core/`. Everything Godot's -extension system does, Summer does, and the extension points are the same ones you -already know. +Summer Engine is the product. Its current upstream technical base is Godot Engine +4.6.1-stable with an unmodified `core/`, so extension compatibility is intentionally close +to that pinned upstream base. Summer follows upstream continuously; 4.6.1 is a compatibility +fact, not the Summer Engine product version. There are three of them. They differ in what they can reach, what they cost to build, and whether you can use them at all. @@ -14,7 +15,7 @@ and whether you can use them at all. | You want to | Use | Language | Needs a compiler | Available to you | |---|---|---|---|---| | Drive the editor: bakes, forced reimports, custom docks, registering autoloads, anything under `EditorInterface` | [Editor plugin](/extending/editor-plugins) | GDScript | No | **Yes, today** | -| Add fast native types, wrap a C/C++/Rust library, or do heavy per-frame work | [GDExtension](/extending/gdextension) | C++, Rust, others | Yes | **Yes**, ABI-identical to stock Godot 4.6.1 | +| Add fast native types, wrap a C/C++/Rust library, or do heavy per-frame work | [GDExtension](/extending/gdextension) | C++, Rust, others | Yes | **Conditional** — the current ABI base is measured, but each binary/platform combination needs a load test | | Change the engine itself: new servers, new core types, editor internals | [Engine module](/extending/modules) | C++ | Yes, plus engine source | **No.** Summer's engine source is not public | If you are an agent, or you are automating Summer, the answer is almost always the @@ -49,8 +50,10 @@ headless-editor hazard Native shared libraries loaded from a `.gdextension` file. No engine recompile, no custom binary — the same mechanism stock Godot uses. -Summer branches from the 4.6.1-stable tag, so the GDExtension ABI is the stock 4.6.1 -ABI. A library built against godot-cpp for 4.6 loads in Summer. +Summer branches from the 4.6.1-stable tag, so the current GDExtension ABI target is the +upstream 4.6.1 ABI. That does not prove an arbitrary library works: match the exact API, +architecture, operating system, compiler/runtime dependencies, and signing requirements, +then run a real load/export test. Building, loading, and shipping native extensions in Summer @@ -62,8 +65,8 @@ C++ compiled directly into the binary. This requires building the engine from so and [Summer's engine source is not public](/knowledge-base/source-status), so modules are not an option for external developers today. -The page exists because the distinction matters when you are reading Godot -documentation and deciding which extension mechanism a tutorial is describing. +The page exists because the distinction matters when an upstream tutorial describes an +extension mechanism. What modules are, why they are internal-only in Summer, and what to use instead @@ -71,15 +74,17 @@ What modules are, why they are internal-only in Summer, and what to use instead ## Using community Godot addons -Most Godot 4 addons work in Summer unchanged. Judge one by these rules rather than by -whether it names Summer anywhere: +Community addons are candidates, not blanket-compatible inventory. Pure GDScript addons are +usually lower-risk than native extensions, but Summer's minimum and recommended project +compatibility ranges remain unmeasured. Judge every addon by these rules: - **Godot 4.6 or 4.x, pure GDScript, `@tool` + `EditorPlugin`** — the safe case. No ABI, no compilation, no signing. Install into `addons/` and enable it like any plugin you wrote yourself. - **Godot 4.x with a GDExtension binary** — depends on the addon shipping a build for - 4.6 and for your platform. The ABI is stock, so if it loads in Godot 4.6 it loads in - Summer. Check [GDExtension](/extending/gdextension) before assuming. + 4.6 and for your platform. A successful upstream load is useful evidence, not proof of a + Summer load or export. Check [GDExtension](/extending/gdextension), then test the exact + binary in a committed copy. - **Godot 3.x** — dead. The 3.x plugin API does not exist in 4.x. This is not a Summer limitation; the same addon fails on stock Godot 4. - **Anything shipped as an engine module or a custom engine build** — cannot be used. diff --git a/extending/plugin-library.mdx b/extending/plugin-library.mdx index 7b3b80e..d879c7d 100644 --- a/extending/plugin-library.mdx +++ b/extending/plugin-library.mdx @@ -1,13 +1,15 @@ --- title: "Plugin Library" -description: "A curated, verified list of community Godot 4 addons that fit Summer's compatibility rules — dialogue, behaviour trees, cameras, terrain, testing and debug tools — plus the reusable test for judging any plugin yourself." +description: "A curated list of community addons that fit Summer's current compatibility rules, plus a reusable test for judging any plugin yourself." icon: "library" --- -Summer is Godot 4.6.1 with an unmodified `core/`, so the community's Godot 4 addons are -your addons. Drop one into `addons/`, enable it, and it behaves exactly as it does on -stock Godot — see [Extending Summer](/extending/overview) for why, and -[Editor Plugins](/extending/editor-plugins) for how to write your own. +Summer Engine's current upstream technical base is Godot Engine 4.6.1 with an unmodified +`core/`, so compatible community addons can be used in a Summer project. Drop one into +`addons/`, enable it, and test it against the current Summer Engine release — see +[Extending Summer](/extending/overview) for the compatibility rules, and +[Editor Plugins](/extending/editor-plugins) for how to write your own. The upstream number +is not the Summer Engine product version, and Summer follows upstream continuously. This page is a **curated list, not a marketplace**. There is no installer, no registry and no ranking. It is a short set of addons whose repositories we checked, alongside the diff --git a/guides/working-with-documentation.mdx b/guides/working-with-documentation.mdx index 735b819..b41f698 100644 --- a/guides/working-with-documentation.mdx +++ b/guides/working-with-documentation.mdx @@ -11,7 +11,7 @@ Imagine trying to build a game without knowing what functions are available, wha **Documentation gives Summer Engine the "missing manual" for game development.** When you ask Summer Engine to help with something, it needs to know: -- What Godot functions actually exist and how they work +- Which Summer Engine APIs actually exist and how they work - Current best practices that have evolved since its last training - Real examples from working games - Solutions to common problems that other developers have figured out @@ -21,7 +21,8 @@ Without documentation access, Summer Engine can only guess. With it, Summer Engi ## Types of Documentation Context ### External Documentation -- **Official Framework Docs**: Godot documentation, Unity manuals, Unreal Engine docs +- **Official Engine and Framework Docs**: Summer Engine docs first, plus relevant upstream + API documentation, Unity manuals, and Unreal Engine docs when the project calls for them - **API References**: Language specifications, library documentation - **Community Resources**: Tutorials, Stack Overflow discussions, GitHub issues @@ -36,11 +37,14 @@ Summer Engine has access to a vast library of game development knowledge that it ### Summer Engine's Research Tools -**Godot's Official Documentation** -Summer Engine can read and understand Godot's complete documentation. When you ask about something specific, Summer Engine doesn't guess - it looks up the exact API, properties, and examples. +**Summer Engine and upstream API documentation** +Summer Engine starts with its own documentation. For APIs inherited from its upstream +technical base, it can also consult the relevant Godot Engine API documentation. Match that +research to the current [compatibility reference](/reference/compatibility) instead of +turning an upstream number into the Summer Engine product version. **Community Knowledge Base** -Summer Engine has access to curated examples of common Godot workflows: +Summer Engine has access to curated examples of common engine workflows: - How to set up different camera systems - Material and shader best practices - Physics body configurations @@ -50,7 +54,8 @@ Summer Engine has access to curated examples of common Godot workflows: **Real-Time Web Research** Summer Engine can search current tutorials, forums, and resources: ``` -"Find the latest Godot 4.6 shader examples for water effects" +"Find current Summer Engine shader examples for water effects and verify inherited APIs +against the compatibility reference" "Look up multiplayer synchronization techniques" "Search for performance optimization tips for 2D games" ``` @@ -63,7 +68,7 @@ Summer Engine also learns from how you write code, what patterns you use, and ho When you know specific documentation exists, reference it directly: ``` -Following the Godot documentation for CharacterBody2D, +Following the Summer Engine API documentation for CharacterBody2D, implement a player controller with proper collision detection Use the move_and_slide() method as described in the official docs ``` @@ -73,9 +78,9 @@ Use the move_and_slide() method as described in the official docs Reference documentation patterns for consistency: ``` -Create a custom Resource class following Godot's documentation patterns -Implement the _get_property_list() method as shown in the Godot docs -Use @export annotations according to Godot 4 best practices +Create a custom Resource class following Summer Engine's documented patterns +Implement the _get_property_list() method as shown in the engine API docs +Use @export annotations according to current GDScript best practices ``` ## Internal Documentation Integration @@ -106,7 +111,7 @@ Write comprehensive code documentation that Summer Engine can reference: ## Player controller handling movement, jumping, and basic interactions ## ## This class manages all player input and translates it into game actions. -## It follows the standard CharacterBody2D pattern from Godot 4.x documentation. +## It follows the standard CharacterBody2D pattern in the Summer Engine API documentation. ## ## Dependencies: ## - InputManager for input handling @@ -192,9 +197,9 @@ This will help us design the API before writing code. When referencing external documentation, specify versions: ``` -Using Godot 4.6 documentation for implementing custom resources +Using the current Summer Engine compatibility reference and API docs for custom resources Follow the GDScript 2.0 syntax guidelines -Reference the latest Godot networking tutorial for multiplayer setup +Reference current engine networking documentation for multiplayer setup ``` ### Link Documentation to Implementation @@ -255,9 +260,9 @@ Document project setup procedures: # Development Environment Setup ## Prerequisites -- Summer Engine 4.6 or later +- A current Summer Engine release compatible with this project - Git for version control -- Recommended: VS Code with Godot Tools extension +- Recommended: VS Code with GDScript language support ## Project Setup 1. Clone the repository: `git clone [repo-url]` diff --git a/index.mdx b/index.mdx index 68e7f0b..1ba5aaa 100644 --- a/index.mdx +++ b/index.mdx @@ -1,39 +1,63 @@ --- -title: "Summer Engine: Build Games with AI, Compatible with Godot 4" -description: "Describe your game in plain English and Summer Engine writes the code, scenes, and assets. Compatible with Godot 4, connects to your IDE through MCP, CLI, and API." +title: "Summer Engine: Build a Summer game with AI" +description: "Install Summer Engine, create a Summer game in GDScript, add Summer SDK capabilities, test locally, and publish." icon: "sparkles" --- -Summer Engine is an AI game engine and coding agent, built to make it as fun to make games as it is to play them. Describe what you want to build or change in natural language and Summer Engine will write the code for you and help you create the first game assets for your game. -Instead of bouncing between ChatGPT, VS Code, and your game engine, you work in one unified environment where AI understands your entire game project and can modify scenes, code, and assets through natural language commands. +Summer Engine is the AI game engine for building a **Summer game**. Start in the editor, +write gameplay in **GDScript**, add the **Summer SDK** capabilities your game needs, then +test and publish from one documented path. + +Describe what you want to build or change in natural language. Summer Engine can work across +your scenes, scripts, and assets while you review the changes in the same project. **What makes Summer Engine different:** -- **Works with existing projects**: Open your projects and keep working. Tutorials, libraries, and extensions work out of the box. -- **No lock-in**: Your projects stay yours. Open them in Summer Engine or your preferred editor anytime. +- **One creator path**: Install, create, integrate the Summer SDK, test, publish, and update. +- **GDScript by default**: Start with the creator language used throughout these guides. +- **Portable source**: Your project stays yours. Familiar formats improve portability, but + editor-version, import, plugin, native-extension, and export compatibility still need + verification. - **Project Intelligence**: AI understands your scenes, scripts, assets, and game logic -- **Safe Operations**: Changes go through safe APIs, so nothing breaks unexpectedly +- **Reviewable Operations**: Changes go through editor APIs; review the diff and test the project after each operation - **Privacy controls**: Pro accounts can enable Privacy Mode to opt out of training-data use -## Quickstarts +## Start here -Get started in 5 minutes. Pick your path: +Follow this path in order: - - - Point Claude Code, Cursor, Codex, or any agent at one prompt: it builds a multiplayer Godot game and submits it to Summercraft for review + + + Install the editor on macOS or Windows and verify it opens. - - Use Summer Agent in Summer Engine: build a complete game with full AI assistance, no coding required + + Create a project and make GDScript your default gameplay language. + + + Add the minimal game structure and connect the Summer SDK. + + + Choose multiplayer, player, persistence, economy, and publishing capabilities. + + + Validate the Summer game before using a limited publish request. + + + Export a game-only pack, submit it for human review, and follow the update path. - - Start from scratch and build your first game with Summer Agent in minutes + + +## Other ways to start + + + + Use the canonical prompt to build a Summer game with Summer Engine and the Summer SDK. + + + Use Summer Agent to draft scenes and GDScript, then review and test the generated work. CLI lets Claude Code, Cursor, Devin Desktop install and run Summer Engine. You chat in your IDE; the AI uses MCP tools. - - Open your existing project in Summer Engine and get Summer Agent assistance immediately - Build and export a Windows game with Summer Agent @@ -61,6 +85,9 @@ Get started in 5 minutes. Pick your path: Rebuild your Unreal project in Summer Engine with Summer Agent + + Use the compatibility and migration path instead of the new-creator sequence. + ## How Do I Make Games with My IDE? @@ -109,7 +136,7 @@ Deep dives into Summer Engine's capabilities: Create 2D art, 3D models, and audio with AI - Export to Steam, itch.io, Mac, Windows, mobile, and consoles + Prepare an export with the templates and toolchains installed for your target. Store submission remains creator-controlled. @@ -122,7 +149,7 @@ Common questions about Summer Engine: The AI game engine. Build games by describing them. - Yes. Open your project and continue working with AI assistance. + Commit a copy first, then verify the editor, imports, plugins, native extensions, and exports against the compatibility reference. Privacy Mode is available on paid plans. When enabled, code is never stored by model providers or used for training. @@ -131,7 +158,7 @@ Common questions about Summer Engine: Great for prototyping and indie games. Learn the tradeoffs. - Yes. Describe what you want and Summer Engine writes the code. + Start in natural language. Summer Agent can draft scenes and GDScript while you review, test, and integrate the result. Founders respond personally. Discord, email, and more. @@ -178,8 +205,8 @@ Summer Engine brings AI directly into your game development workflow. Whether yo Summer Engine is designed for everyone who wants to make games. It combines the ease of "vibe coding" with the power of a professional game engine. ### For Creators & Vibe Coders -- **No code required**: Build complete games just by describing them in plain English -- **Instant Assets**: Generate 3D models, music, and sound effects on the fly +- **Start in natural language**: Ask Summer Agent to draft scenes and GDScript, then review and test the result +- **Documented asset workflow**: Follow the asset-generation guide for currently supported providers, licensing, and quality tradeoffs - **Learn as you go**: Watch how Summer Engine builds things to learn game development naturally - **Focus on fun**: Skip the boilerplate and get straight to the gameplay @@ -189,7 +216,7 @@ Summer Engine is designed for everyone who wants to make games. It combines the - **Code Quality**: AI writes clean, structured GDScript that follows best practices - **Accelerated Workflow**: Handle tedious tasks instantly so you can focus on architecture and polish -Summer Engine removes boilerplate, accelerates iteration, and handles the hard parts, while giving you the option to dive as deep as you want. We integrate every new AI breakthrough (image, 3D, video models) within 24 hours of release. +Summer Engine removes boilerplate and accelerates iteration while giving you the option to dive as deep as you want. New models are evaluated before they are exposed; availability is documented instead of promised on a fixed schedule. - Open your projects as-is. Keep your plugins, docs, and muscle memory. + Evaluate a committed copy of an existing project. Familiar formats and concepts reduce + migration work; verify imports, plugins, native extensions, and exports against the + current Summer Engine release. diff --git a/knowledge-base/godot-compatibility.mdx b/knowledge-base/godot-compatibility.mdx index 3e579d4..0219d95 100644 --- a/knowledge-base/godot-compatibility.mdx +++ b/knowledge-base/godot-compatibility.mdx @@ -1,22 +1,34 @@ --- title: "Is Summer Engine compatible with my existing project?" -description: "Yes. Open your project and continue working with AI assistance. No conversion required." +description: "Summer uses familiar upstream-compatible formats, while minimum and recommended project compatibility ranges remain unmeasured." icon: "question" --- -## Yes, Completely Compatible +## Start with the measured compatibility contract -Summer Engine works with industry-standard project formats. You can open any existing Godot project in Summer Engine and continue working on it immediately. No conversion, no migration, no lock-in. +Summer Engine uses familiar text scene, resource, script, and project formats. The current +upstream technical base is 4.6.1, the planned next base is 4.7.1, and Summer follows upstream +continuously. The minimum and recommended project compatibility ranges are not yet measured, +so this page does not promise that every historical project opens unchanged. -## What Works Out of the Box +## What to evaluate -**All existing Godot projects.** Summer Engine is built on the Godot codebase. Your `.tscn` scene files, `.gd` scripts, `.tres` resources, and `project.godot` configuration are identical. A `git diff` between a Summer Engine-edited file and a Godot-edited file shows only your changes. No proprietary metadata injection. +**Portable source formats.** `.tscn` scenes, `.gd` scripts, `.tres` resources, and +`project.godot` configuration use familiar upstream-derived formats. This is a format fact, +not proof that every file produced by every upstream release loads unchanged. Commit before +the first open, then review import and configuration changes normally. -**Third-party libraries and plugins.** Most Godot plugins work in Summer Engine without changes. Plugins that modify the editor interface may need updates for AI integration, but the vast majority work as-is. +**Third-party libraries and plugins.** Pure GDScript addons are the safest case. Native +extensions, custom editor integrations, and addons pinned to a different upstream version +need explicit compatibility testing. -**Export templates.** Web, desktop (Windows, Mac, Linux), and mobile (iOS, Android) export all work. You can build for any platform Summer Engine supports. +**Export targets.** Verify the installed templates and run an exported-build smoke test for +each target. Do not infer web, desktop, mobile, or native-extension compatibility from the +upstream base alone. -**Team workflows.** Team members can use Summer Engine and vanilla Godot interchangeably. An artist opens the project in Godot to edit scenes; a programmer opens the same project in Summer Engine for AI assistance. Both commit to the same repo. No merge conflicts from tooling differences. +**Team workflows.** Mixed-editor teams can share the repository when they pin compatible +versions and review generated changes. Shared formats reduce friction; they do not guarantee +zero differences between editors or importers. ## What Happens When You Open Your Project @@ -27,11 +39,15 @@ Summer Engine works with industry-standard project formats. You can open any exi ## Zero Lock-in -Summer Engine projects *are* Godot projects. Identical file formats. If Summer Engine disappeared tomorrow, your project would open in Godot 4 without modification. You'd lose AI assistance, but your game, code, and assets would be unaffected. +Your Summer game remains yours: GDScript, text scenes, resources, and assets stay in +documented formats. Opening them in another compatible editor may require an import pass and +does not carry Summer-only AI or platform surfaces. ## Version Compatibility -Summer Engine supports Godot 4.x project formats. Projects from Godot 3.x need the standard Godot 3→4 migration process before opening in Summer Engine. +Use the generated [Compatibility & upstream](/reference/compatibility) page for the current +base and measured claims. Projects from Godot Engine 3.x need the upstream 3→4 migration +before they can be evaluated against Summer Engine's current base. ## Related diff --git a/knowledge-base/godot-projects.mdx b/knowledge-base/godot-projects.mdx index 005ac13..e280133 100644 --- a/knowledge-base/godot-projects.mdx +++ b/knowledge-base/godot-projects.mdx @@ -1,10 +1,13 @@ --- -title: "What if I have existing projects?" -description: "They work perfectly. Open them in Summer and continue development. All scenes, scripts, and plugins work as before." +title: "What if I have an existing project?" +description: "Open a compatible project in Summer Engine, review the first import, and continue building a Summer game." icon: "question" --- -**They work perfectly.** Just open them in Summer and continue development. All your scenes, scripts, assets, and plugins will work exactly as before, plus you get AI assistance. +Open a committed copy in Summer Engine and review the first import. GDScript, text scenes, +resources, and assets use familiar formats; native extensions, editor plugins, and +version-sensitive imports still need compatibility testing. The generated +[compatibility reference](/reference/compatibility) is the source of truth. ## Related diff --git a/knowledge-base/multiplayer.mdx b/knowledge-base/multiplayer.mdx index a80f454..095f0d5 100644 --- a/knowledge-base/multiplayer.mdx +++ b/knowledge-base/multiplayer.mdx @@ -4,11 +4,15 @@ description: "Yes, with limitations. Basic multiplayer networking works with AI icon: "question" --- -**Yes, with limitations.** Summer Engine supports multiplayer game development through its Godot foundation, which includes a mature networking stack. +**Yes, with limitations.** Summer Engine includes multiplayer APIs and transports for games +you run and deploy yourself. Hosted Summercraft multiplayer is a separate platform +capability and is not production-live yet. ## What Works Today -- **High-level multiplayer API**: Godot's `MultiplayerPeer`, `MultiplayerSpawner`, and `MultiplayerSynchronizer` nodes all work in Summer. The AI can help you set these up through natural language. +- **High-level multiplayer API**: `MultiplayerPeer`, `MultiplayerSpawner`, and + `MultiplayerSynchronizer` all work in Summer Engine. The AI can help you set them up + through natural language. - **ENet and WebSocket transports**: Local LAN multiplayer and WebSocket-based online multiplayer are both supported out of the box. - **RPC and state synchronization**: Remote procedure calls (`@rpc`) and automatic property synchronization work as expected. Ask the AI to set up synchronized variables and it will generate the correct annotations. - **Dedicated server exports**: You can export headless server builds for Linux deployment. @@ -19,10 +23,16 @@ The AI assistant can generate multiplayer boilerplate, set up lobby systems, con ## Current Limitations -- **No built-in matchmaking or relay servers**: Summer does not yet provide hosted multiplayer infrastructure. You need to bring your own server or use a service like [Summercraft](/api-reference/summer-sdk) for web-based multiplayer games. +- **No built-in matchmaking or relay servers**: Summer does not yet provide production + hosted multiplayer infrastructure. Bring your own server for a game you operate today. - **Complex netcode patterns**: Advanced techniques like client-side prediction, rollback, and lag compensation require manual implementation. The AI can assist but these are inherently complex. - **Testing**: Multiplayer testing requires running multiple instances manually. -## Summer SDK for Web Multiplayer +## Summer SDK platform contract -If you are building a web-based multiplayer game, the [Summer SDK](/api-reference/summer-sdk) provides a managed multiplayer backend with automatic matchmaking, persistence, and server hosting. This is the easiest path to online multiplayer in Summer. +The [Summer SDK](/api-reference/summer-sdk) documents the creator-facing contract for +host-authoritative gameplay, synced state, persistence, economy, and submission. The +submission and review APIs are live. Player-facing playback, hosted dedicated game servers, +automatic matchmaking, and the production runtime sandbox are not live yet. Track the +canonical [platform capability status](/knowledge-base/source-status#platform-capability-status) +before making launch promises. diff --git a/knowledge-base/source-status.mdx b/knowledge-base/source-status.mdx index a3b9871..964f660 100644 --- a/knowledge-base/source-status.mdx +++ b/knowledge-base/source-status.mdx @@ -1,10 +1,14 @@ --- -title: "What is open in Summer Engine?" -description: "The exact split between Summer's open agent layer, free desktop app, and paid hosted services." +title: "Product Source & Platform Status" +description: "The canonical status for Summer Engine source access and live, scaffolded, or planned Summercraft platform capabilities." icon: "badge-check" +capabilityStatus: "canonical" --- -Summer's AI-agent layer is MIT open source. The Summer Engine desktop app is free to download and use, but its source code is not public right now. Hosted Summer AI, asset generation, storage, multiplayer, orchestration, and cloud services are paid Summer services. +Summer's AI-agent layer is MIT open source. The Summer Engine desktop app is free to +download and use, but its source code is not public right now. This page is also the single +canonical status source for Summercraft capabilities: reference pages describe contracts, +while this page says whether the supporting production path is live. ## What is open today? @@ -24,13 +28,43 @@ The Summer Engine desktop app is free to download and use. Local MCP workflows a ## What is paid? -Hosted Summer services are paid because they run cloud infrastructure and model calls: +Live hosted Summer services are paid because they run cloud infrastructure and model calls: - Hosted Summer AI - Asset generation - Cloud storage - Orchestration -- Managed multiplayer + +Managed multiplayer is planned as a paid hosted service; it is not production-live today. + +## Platform capability status + +| Capability | Status | What that means today | +|---|---|---| +| Create Summer game records | **Live** | Authenticated creators can create a game record through the Summercraft API. | +| Upload and verify a game-only `.pck` | **Live** | Direct-to-storage upload, server-side SHA-256 verification, and immutable release records are deployed. | +| Browser submission and static scanner | **Live** | The signed-in submit page accepts a `.pck` plus `manifest.json` and runs pattern-based static analysis before creating a review submission. | +| Manual review queue | **Live** | A submission can enter human review; there is no automatic approval. | +| Authenticated release download | **Live** | Owners and admins can retrieve pending releases; published catalog releases follow the documented access rules. | +| Summer SDK gameplay and subsystem interfaces | **Scaffold** | The GDScript contract and examples exist, but documented interfaces do not prove the hosted runtime path is deployed. | +| `SummerMultiplayerPeer` transport | **Scaffold** | The compatibility contract is published and implementation is in progress. | +| Browser or desktop-shell play for uploaded games | **Planned** | A `published` catalog status does not make an uploaded game playable. | +| Hosted dedicated game servers | **Planned** | Creators must not promise managed hosting to players. | +| Automatic matchmaking and relay | **Planned** | No production matchmaking or relay service is available for uploaded Summer games. | +| Automated production runtime sandbox | **Planned** | Submission review is manual; the production sandbox path is still being built. | +| Production gameplay runtime | **Planned** | Uploaded and approved packs do not execute in a Summercraft gameplay runtime today. | +| Hosted persistence and economy | **Scaffold** | `Summer.data` and `Summer.economy` are contract surfaces; no hosted backend durably stores player data or runs the economy rail today. | + +Status words are deliberate: + +- **Live** means the production path is deployed and documented. +- **Scaffold** means a contract, adapter, or tested local surface exists without a complete + production path. +- **Planned** means creators and agents must not promise the capability. + +See [Summer SDK](/api-reference/summer-sdk) for contracts and +[Submit Your Summer Game for Review](/api-reference/summer-sdk/submission-guide) for the +currently deployed submission flow. ## Is the engine app open source? diff --git a/knowledge-base/what-is-summer.mdx b/knowledge-base/what-is-summer.mdx index 215d05c..df91038 100644 --- a/knowledge-base/what-is-summer.mdx +++ b/knowledge-base/what-is-summer.mdx @@ -1,6 +1,6 @@ --- -title: "What is Summer Engine? The AI Game Engine Compatible with Godot 4" -description: "Summer Engine is the AI game engine where you build games by describing them in plain English. Compatible with Godot 4, with AI that understands your whole project." +title: "What is Summer Engine?" +description: "Summer Engine is the AI game engine where you build a Summer game in GDScript with AI that understands your whole project." icon: "question" --- @@ -8,6 +8,11 @@ icon: "question" Summer Engine is **the AI game engine**. It's not just a game engine with a plugin bolted on. It's a professional engine built from the ground up for AI, where the AI understands your entire project and can modify scenes, code, and assets through natural language commands. +You make a **Summer game** in **GDScript**. When you need multiplayer, player identity, +persistence, economy, or submission surfaces, you integrate the **Summer SDK**. Summer is +the product creators install and use; upstream lineage belongs in the +[compatibility reference](/reference/compatibility), not in the product name. + **Think of it as Cursor for game development.** Instead of juggling ChatGPT, VS Code, and another engine, you work in one unified environment. You describe what you want; Summer Engine writes the code, creates assets, and modifies your game directly. ## How Summer Engine Differs from Other Approaches diff --git a/mcp/overview.mdx b/mcp/overview.mdx index 60bf139..f8ff028 100644 --- a/mcp/overview.mdx +++ b/mcp/overview.mdx @@ -15,7 +15,7 @@ Summer Engine is an AI game engine. Describe what you want in natural language ( icon="sparkles" href="/quickstarts/ai-game-dev" > - Build a complete game with full AI assistance, no coding required + Ask AI to draft scenes and GDScript, then review, test, and iterate on the result --- @@ -179,7 +179,9 @@ Summer Engine's MCP server exposes its tools over the Model Context Protocol. Th Summer Engine gives you: - **A full MCP toolset**: Scene (AddNode, SetProp, SaveScene, etc.), Debug and Play (Play, Stop, diagnostics, script and debugger errors, and screenshot the viewport or running game), Project (settings, input, import, context), Asset Library (search and import), Generation (image, 3D, audio, video, motion), and Summer Cloud (push, pull, restore, conflicts) -- **Works with existing projects**: No conversion. Tutorials, plugins, and assets work as-is. +- **Evaluate existing projects**: Familiar source formats reduce migration work, but + compatibility ranges are not fully measured. Commit first and verify imports, tutorials, + plugins, native extensions, and exports against the current Summer Engine release. - **CLI + MCP + API**: Install via CLI, control via MCP, same local API under the hood - **One workflow**: Whether you use the built-in chat, Cursor, Claude Code, Devin Desktop, Antigravity, Codex, VS Code, or Zed, the operations are identical diff --git a/mcp/vscode.mdx b/mcp/vscode.mdx index 71bdf10..df9f7eb 100644 --- a/mcp/vscode.mdx +++ b/mcp/vscode.mdx @@ -1,12 +1,12 @@ --- -title: "Godot AI Coding in VS Code with Summer Engine" -description: "Connect Summer Engine's MCP server to VS Code or GitHub Copilot and build games compatible with Godot 4 right inside Microsoft's editor and Copilot's AI agent." +title: "Build Summer Games in VS Code" +description: "Connect Summer Engine's MCP server to VS Code or GitHub Copilot and build a Summer game from Microsoft's editor and Copilot's AI agent." icon: "square-code" --- {/* Do not reintroduce a hardcoded MCP tool count here. The tool list grows every release and a baked-in number has already gone stale twice. */} -## Summer Engine in VS Code & GitHub Copilot +## Summer Engine in VS Code and GitHub Copilot VS Code and GitHub Copilot's coding agent support MCP (Model Context Protocol). With Summer Engine's integration, the AI can control your game engine: add nodes to scenes, set properties, import assets, run the game, and debug, all from within your coding workflow. diff --git a/migration/godot.mdx b/migration/godot.mdx index a2bec63..9788e4f 100644 --- a/migration/godot.mdx +++ b/migration/godot.mdx @@ -1,30 +1,39 @@ --- -title: "Move Your Godot Project to Summer Engine in Minutes" -description: "Bring your existing Godot 4 projects, settings, and shortcuts into Summer Engine and keep building with an AI that knows your whole game. Compatible with Godot 4." +title: "Move an Existing Project to Summer Engine" +description: "Open an existing upstream-compatible project in Summer Engine, verify it against the current compatibility contract, and continue as a Summer game." icon: "arrow-right" --- -## Godot Migration +## Move to Summer Engine -Summer Engine is based upon the Godot codebase, allowing us to focus on making the best AI-powered game development experience while maintaining a familiar editing environment. This makes it easy to migrate your existing Godot settings to Summer Engine. +Summer Engine is the product you install and use. Its current upstream technical base is +Godot Engine 4.6.1, and Summer follows upstream continuously. That lineage preserves familiar +project formats and editing concepts, but it is not the Summer Engine product version and +does not change the identity of your Summer game. + +Check the generated [compatibility reference](/reference/compatibility) before migrating. +It distinguishes measured facts from project-compatibility claims that have not yet been +measured. ## Profile Migration -If you're familiar with Godot, you'll feel right at home in Summer Engine. The interface, node system, and scripting work exactly the same way you're used to. +If you are coming from Godot Engine, the node, scene, resource, and GDScript concepts are +familiar. Summer Engine adds its own AI workflow and product surfaces, so verify plugins, +editor customizations, and export behavior instead of assuming every detail is identical. ## What's the Same -Everything you know about Godot still applies in Summer Engine: +The portable foundation includes: -- **Node system** - All the same nodes, properties, and relationships -- **GDScript** - Your existing scripts work without changes -- **Scene structure** - `.tscn` files are byte-for-byte identical -- **Project settings** - Same export options and configurations -- **Asset pipeline** - Import settings and resource formats unchanged +- **Node and scene concepts** — familiar nodes, properties, and relationships +- **GDScript** — the default creator language in Summer Engine +- **Text scene and resource formats** — `.tscn`, `.tres`, and `.gd` +- **Project configuration** — `project.godot` +- **Asset import metadata** — verify on first open because importers can change upstream ## Zero Lock-in -Summer Engine projects ARE Godot projects. Identical file formats: +Summer games use upstream-compatible project formats: | Format | Description | |--------|-------------| @@ -33,23 +42,28 @@ Summer Engine projects ARE Godot projects. Identical file formats: | `.tres` / `.res` | Resource files | | `project.godot` | Project configuration | -**No proprietary formats. No metadata injection.** A `git diff` between a Summer Engine-edited file and a Godot-edited file shows only your changes. +Summer does not require a proprietary replacement for these files. Keep the project in +version control and review the first Summer Engine import diff before accepting it. ### Team Workflows -Team members can use Summer Engine and vanilla Godot interchangeably: -- Artist opens project in Godot, edits scenes -- Programmer opens same project in Summer Engine, uses AI assistance -- Both commit to the same repo -- No merge conflicts from tooling differences +Mixed-editor teams can share source formats, but should pin compatible versions and review +generated import metadata: + +- a collaborator may open the project in the compatible upstream editor, +- a creator opens the same repository in Summer Engine, +- both commit project files to the same repository, +- the team resolves real file changes through its normal review process. ### Worst Case -Summer Engine disappears tomorrow? Your project opens in Godot 4 without modification. You lose AI assistance. Your game, code, and assets are unaffected. +Your GDScript, text scenes, resources, and assets remain in documented formats. Opening them +in another compatible editor may require an import pass and will not provide Summer-only AI +or platform surfaces. ## What's Different -Summer Engine adds AI capabilities on top of the familiar Godot experience: +Summer Engine adds its own AI-native workflow to the familiar technical foundation: ### AI Chat Panel @@ -68,12 +82,12 @@ Instead of manually clicking through menus: ## Project Compatibility -Your existing Godot projects work in Summer Engine: +To try an existing Godot Engine project in Summer Engine: 1. **File → Open Project** (or use Project Manager) - 2. **Browse to your Godot project folder** + 2. **Browse to the existing project folder** 3. **Select project.godot file** 4. **Click "Open"** @@ -93,15 +107,20 @@ Your existing Godot projects work in Summer Engine: - Most Godot plugins work in Summer Engine without changes. However, plugins that modify the editor interface may need updates for AI integration. + Pure GDScript addons are the safest case. Native extensions and editor integrations are + version-sensitive; use [Extending Summer](/extending/overview) before enabling them. - Yes! Summer Engine projects are standard Godot projects. You can open them in regular Godot anytime. + The source formats are upstream-compatible. Pin the compatible upstream version, commit + first, and expect an import pass; Summer-only AI and platform surfaces will not be present. - Summer Engine supports Godot 4.x project formats. Projects from Godot 3.x will need the standard Godot 3→4 migration process. + The current upstream technical base is 4.6.1 and the planned next base is 4.7.1. Summer + follows upstream continuously. The project minimum is currently unmeasured, so do not + replace that fact with a blanket “Godot 4.x” compatibility promise. See + [Compatibility & upstream](/reference/compatibility). diff --git a/package.json b/package.json index 37d69da..45f6d45 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,14 @@ "node": ">=20" }, "scripts": { - "check": "node scripts/check-docs.mjs" + "check": "npm run check:compatibility && npm run check:language && npm run check:capabilities && npm run check:policy-fixtures && npm run check:routes && node scripts/check-docs.mjs", + "check:capabilities": "node scripts/check-capabilities.mjs", + "check:policy-fixtures": "node scripts/check-policy-fixtures.mjs", + "check:compatibility": "node scripts/sync-engine-compatibility.mjs --check", + "check:external-links": "node scripts/check-external-links.mjs", + "check:language": "node scripts/check-language.mjs", + "check:routes": "node scripts/check-routes.mjs", + "generate:compatibility": "node scripts/sync-engine-compatibility.mjs", + "generate:routes": "node scripts/check-routes.mjs --write" } } diff --git a/publishing/steam.mdx b/publishing/steam.mdx index 3df6117..6a2b21e 100644 --- a/publishing/steam.mdx +++ b/publishing/steam.mdx @@ -172,7 +172,11 @@ Summer Engine supports Steamworks integration for advanced features: 4. Follow GodotSteam docs for achievement/leaderboard setup - GodotSteam works **identically** in Summer Engine - all Godot Steam tutorials apply directly. + GodotSteam is a native, version-sensitive integration. Do not assume identical behavior or + that every upstream tutorial applies. Match the plugin build to Summer Engine's current + upstream base, test it in a committed copy, then verify achievements, overlay, input, + cloud saves, and exports on every target platform. See + [GDExtension compatibility](/extending/gdextension). --- @@ -420,4 +424,3 @@ Players love games that get updates! Here's how: **Need help with Steam?** [Discord](https://discord.gg/yUpgtxnZky) • [X/Twitter @SummerEngineCom](https://x.com/SummerEngineCom) • founders@summerengine.com - diff --git a/quickstarts/ai-game-dev.mdx b/quickstarts/ai-game-dev.mdx index 414d4cb..961800e 100644 --- a/quickstarts/ai-game-dev.mdx +++ b/quickstarts/ai-game-dev.mdx @@ -1,16 +1,16 @@ --- title: "How do I make a game with Summer Agent?" -description: "Build a complete game with Summer Agent in Summer Engine. Full AI assistance, no coding required." +description: "Use Summer Agent to draft scenes and GDScript in Summer Engine, then review, test, and iterate." icon: "sparkles" --- ## Make a Game with Summer Agent -Summer Engine lets you build complete games by describing what you want. Use **Summer Agent**—the built-in AI assistant in Summer Engine—to write code, create assets, and set up your game. No coding experience required. +Summer Engine lets you begin in natural language. Use **Summer Agent**—the built-in AI assistant in Summer Engine—to draft code, create supported assets, and set up game systems. Review the changes, test the game, and learn or edit GDScript when the generated result needs correction. ## What is Summer Agent? -**Summer Agent** is Summer Engine's native AI assistant (like Cursor Agent in Cursor). You describe your game in plain English and Summer Agent does the technical work. You focus on the creative vision; Summer Agent handles the implementation. +**Summer Agent** is Summer Engine's native AI assistant (like Cursor Agent in Cursor). You describe the next change in plain English and Summer Agent drafts the implementation. You remain responsible for reviewing the diff, testing behavior, and deciding what ships. ## Step 1: Get Summer Engine diff --git a/quickstarts/existing-godot.mdx b/quickstarts/existing-godot.mdx index 4300b29..ca1ed4a 100644 --- a/quickstarts/existing-godot.mdx +++ b/quickstarts/existing-godot.mdx @@ -1,12 +1,14 @@ --- title: "I have an existing project. How do I add Summer Engine?" -description: "Open your existing project in Summer Engine and get AI assistance immediately. No conversion required." +description: "Evaluate an existing upstream-compatible project in Summer Engine, review the first import, and verify version-sensitive integrations." icon: "folder" --- ## Use Summer Engine with Your Existing Project -Summer Engine works with industry-standard project formats. Open your project and continue working, with AI assistance. +Summer Engine uses familiar upstream-derived project formats, but its minimum and recommended +project compatibility ranges remain unmeasured. Work from a committed copy, open it in +Summer Engine, and treat the first import as a compatibility evaluation. ## Step 1: Download and Install Summer Engine @@ -33,16 +35,19 @@ Summer Engine works with industry-standard project formats. Open your project an -## What Works Out of the Box +## What to expect -- **All your scenes, scripts, and assets**: No conversion needed -- **Third-party libraries and plugins**: Most work without changes -- **Export templates**: Web, desktop, and mobile export all supported -- **Team workflows**: Team members can use Summer Engine and the standard editor interchangeably +- **GDScript, text scenes, resources, and assets** use familiar formats. +- **Third-party libraries and plugins** need explicit testing when they are native, + editor-integrated, or version-pinned. +- **Imports and exports** should be verified on the target Summer Engine release. +- **Team workflows** should pin compatible editor versions and review generated diffs. ## Zero Lock-in -Your project files stay in standard formats. You can open the same project in the standard editor anytime. No proprietary formats, no metadata injection. +Your project files stay in documented formats. Commit before the first open so imports and +configuration changes are reviewable. See +[Compatibility & upstream](/reference/compatibility) for current measured facts. ## Next Steps diff --git a/quickstarts/fresh-project.mdx b/quickstarts/fresh-project.mdx index b811607..6efa84a 100644 --- a/quickstarts/fresh-project.mdx +++ b/quickstarts/fresh-project.mdx @@ -1,12 +1,13 @@ --- -title: "How do I start a fresh project?" -description: "Start from scratch and build your first AI-powered game in 5 minutes" +title: "Create your first Summer game" +description: "Create a Summer Engine project, use GDScript by default, and continue into the Summer SDK." icon: "rocket" --- -## Welcome to Summer Engine +## Create a Summer game -Summer Engine is The AI Game Engine. We make game development as fun as playing games. No coding experience? No problem. Just tell Summer Engine what you want to build. +Start with an empty Summer Engine project. GDScript is the default creator language in this +journey; the next guide adds the Summer SDK contract used for testing and publishing. ## Step 1: Download Summer Engine @@ -36,12 +37,12 @@ Getting Summer Engine on your computer is super easy. -## Step 2: Build Your First Game +## Step 2: Build Your First Summer Game This is where the magic happens. Let's create something awesome! - + 1. **Click "New Project"** → Give it a fun name like "My Amazing Game" 2. **Choose a location** → Anywhere on your computer is fine 3. **Click "Create & Open"** → Summer Engine opens with a chat window on the right @@ -86,20 +87,14 @@ Summer Engine combines a familiar game editor with AI superpowers. -## Next Steps +## Continue the canonical path - - Start from a template instead of blank: shooter, RPG, platformer, horror, and more + + Return to installation and verification. - - Learn what Summer Engine can do in your project - - - Create 2D art, 3D models, and audio with AI - - - Export your game to PC, Mac, mobile, or web + + Add the creator-facing SDK contract to your Summer game. diff --git a/reference/compatibility.mdx b/reference/compatibility.mdx new file mode 100644 index 0000000..a479d8f --- /dev/null +++ b/reference/compatibility.mdx @@ -0,0 +1,62 @@ +--- +title: "Compatibility & upstream" +description: "Generated Summer Engine product-release and upstream compatibility facts from the pinned engine contract." +icon: "git-compare-arrows" +generated: true +generator: compatibility/source.json +--- + +{/* Generated by scripts/sync-engine-compatibility.mjs. Do not edit by hand. */} + +This reference is generated from the Summer Engine compatibility contract at +`SummerEngine/SummerEngine:compatibility/summer-engine.json`, commit `b44e47792819fb402a2984cd79c7023cc8aa57f8`. The checked-in input is verified against SHA-256 +`741bd8237868a395cad89bfa1c5a70ef5ca2cfcc829674047cab1b9e180c054a`; docs builds do not fetch mutable remote data. + +## Product identity + +**Summer Engine** is the product. Creators make a **Summer game** in +**GDScript** and use the **Summer SDK** for platform capabilities. +The product release is platform-staggered and separate from the upstream technical base. + +| Platform | Summer Engine release | Authoritative engine source | +|---|---:|---| +| macOS | `0.5.58` | `modules/1summer_engine/summer_version.h` → `SUMMER_VERSION_MACOS` | +| Windows | `0.5.59` | `modules/1summer_engine/summer_version.h` → `SUMMER_VERSION_WINDOWS` | + +## Upstream technical base + +| Field | Value | +|---|---| +| Current upstream base | `4.6.1` | +| Planned next upstream base | `4.7.1` | +| Policy | `continuous-upstream` | +| Build evidence | `version.py` | +| Verified | `2026-07-30` | + +The upstream base is a compatibility and lineage fact, not the Summer Engine product version. +Summer follows upstream continuously; neither the current nor planned upstream number is a +permanent Summer identity. + +## Runtime and project compatibility + +- Runtime compatibility: Unmeasured; no version is claimed. +- Minimum project compatibility: Unmeasured; no version is claimed. +- Recommended project compatibility: Unmeasured; no version is claimed. + +Unmeasured values are intentionally `null` in the source contract. Do not infer a minimum +from `project.godot`, copied prose, or an older setup guide. + +## Where upstream terminology belongs + +Godot references remain in migration, plugin and GDExtension compatibility, upstream +contribution, attribution, and legal contexts. Default creator onboarding installs and uses +Summer Engine. + + + + Review creator-facing names and stable wire identifiers. + + + Bring an existing Godot project into Summer Engine. + + diff --git a/scripts/check-capabilities.mjs b/scripts/check-capabilities.mjs new file mode 100644 index 0000000..a3962d6 --- /dev/null +++ b/scripts/check-capabilities.mjs @@ -0,0 +1,191 @@ +#!/usr/bin/env node + +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { scanCapabilityClaims } from "./docs-policy-core.mjs"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const policy = JSON.parse(readFileSync(join(ROOT, "scripts/docs-capability-policy.json"), "utf8")); +const config = JSON.parse(readFileSync(join(ROOT, "docs.json"), "utf8")); +const errors = []; + +if (policy.schemaVersion !== 2) { + errors.push(`unsupported capability policy schema ${JSON.stringify(policy.schemaVersion)}`); +} +const capabilityIds = new Set(); +for (const capability of policy.claimCapabilities ?? []) { + if (capabilityIds.has(capability.id)) { + errors.push(`duplicate capability policy id: ${capability.id}`); + } + capabilityIds.add(capability.id); + for (const field of ["id", "label", "state"]) { + if (typeof capability[field] !== "string" || !capability[field].trim()) { + errors.push(`capability policy ${capability.id ?? ""} is missing ${field}`); + } + } + for (const field of ["subjectAliases", "statusTerms", "disclaimerPatterns"]) { + if (!Array.isArray(capability[field]) || capability[field].length === 0) { + errors.push(`capability policy ${capability.id ?? ""} needs a non-empty ${field}`); + } + } + const assertionCount = + (capability.assertionVerbs?.length ?? 0) + + (capability.assertionTerms?.length ?? 0) + + (capability.assertionPatterns?.length ?? 0); + if (assertionCount === 0) { + errors.push(`capability policy ${capability.id ?? ""} needs assertion verbs or terms`); + } +} + +const navigation = []; +function collectNavigation(node) { + if (Array.isArray(node)) { + for (const value of node) collectNavigation(value); + return; + } + if (!node || typeof node !== "object") return; + for (const [key, value] of Object.entries(node)) { + if (key === "pages" && Array.isArray(value)) { + for (const page of value) { + if (typeof page === "string") navigation.push(page); + else collectNavigation(page); + } + } else { + collectNavigation(value); + } + } +} +collectNavigation(config.navigation); + +const routeToFile = (route) => (route === "index" ? "index.mdx" : `${route.replace(/^\//, "")}.mdx`); +const publicFiles = navigation.map(routeToFile); +const publicSet = new Set(publicFiles); +const canonicalPage = policy.canonicalPage; +const disclosureIndicators = (policy.scaffoldDisclosureIndicators ?? []).map( + (pattern) => new RegExp(pattern), +); +const disclosureExemptions = new Map( + (policy.scaffoldDisclosureExemptions ?? []).map((entry) => [entry.file, entry]), +); + +if (!publicSet.has(canonicalPage)) { + errors.push(`canonical capability page is not discoverable in public navigation: ${canonicalPage}`); +} + +let canonicalRaw = ""; +try { + canonicalRaw = readFileSync(join(ROOT, canonicalPage), "utf8"); +} catch { + errors.push(`canonical capability page is missing: ${canonicalPage}`); +} + +if (canonicalRaw && !canonicalRaw.includes(policy.canonicalFrontmatter)) { + errors.push(`${canonicalPage} is missing canonical marker ${JSON.stringify(policy.canonicalFrontmatter)}`); +} +for (const term of policy.requiredCanonicalTerms ?? []) { + if (!canonicalRaw.includes(term)) { + errors.push(`${canonicalPage} is missing required capability status ${JSON.stringify(term)}`); + } +} +for (const required of policy.requiredCapabilityStatuses ?? []) { + const capability = (policy.claimCapabilities ?? []).find((entry) => entry.id === required.id); + if (!capability) { + errors.push(`required capability policy is missing: ${required.id}`); + continue; + } + for (const field of ["label", "state"]) { + if (capability[field] !== required[field]) { + errors.push( + `required capability policy ${required.id} has ${field} ${JSON.stringify(capability[field])}; ` + + `expected ${JSON.stringify(required[field])}`, + ); + } + } + const canonicalRow = `| ${required.label} | **${required.state}** |`; + if (!canonicalRaw.includes(canonicalRow)) { + errors.push(`${canonicalPage} is missing required policy row ${JSON.stringify(canonicalRow)}`); + } +} + +let canonicalMarkers = 0; +let statusTables = 0; +for (const file of publicFiles) { + let raw; + try { + raw = readFileSync(join(ROOT, file), "utf8"); + } catch { + errors.push(`cannot scan public capability route: ${file}`); + continue; + } + + if (raw.includes(policy.canonicalFrontmatter)) canonicalMarkers++; + const ownsPlatformStatus = + file === canonicalPage || + /^(?:agent-setup(?:\/|\.mdx)|api-reference\/summer-sdk(?:\/|\.mdx)|knowledge-base\/multiplayer\.mdx)/.test( + file, + ); + if (ownsPlatformStatus && /^\|\s*Capability\s*\|\s*Status\s*\|/im.test(raw)) { + statusTables++; + if (file !== canonicalPage) { + errors.push(`${file} defines a secondary capability/status table; link to ${canonicalPage} instead`); + } + } + + for (const claim of scanCapabilityClaims(raw, policy)) { + errors.push( + `${file}:${claim.line} [${claim.capability}:${claim.state}] ${JSON.stringify(claim.text)} — ${claim.help}`, + ); + } + + const hasScaffoldContract = disclosureIndicators.some((pattern) => pattern.test(raw)); + const exemption = disclosureExemptions.get(file); + if ( + hasScaffoldContract && + file !== canonicalPage && + !raw.includes("knowledge-base/source-status") && + !exemption + ) { + errors.push(`${file} names scaffolded SDK/runtime surfaces but does not link to ${canonicalPage}`); + } +} + +if (canonicalMarkers !== 1) { + errors.push(`expected exactly one canonical capability marker across public routes, found ${canonicalMarkers}`); +} +if (statusTables !== 1) { + errors.push(`expected exactly one Capability/Status table across public routes, found ${statusTables}`); +} + +for (const [file, exemption] of disclosureExemptions) { + if (!publicSet.has(file)) errors.push(`scaffold disclosure exemption is not a public route: ${file}`); + for (const field of ["owner", "reason"]) { + if (typeof exemption[field] !== "string" || !exemption[field].trim()) { + errors.push(`scaffold disclosure exemption ${file} is missing ${field}`); + } + } +} + +for (const requirement of policy.requiredRouteTerms ?? []) { + if (!publicSet.has(requirement.file)) { + errors.push(`required capability-policy route is not public: ${requirement.file}`); + continue; + } + const raw = readFileSync(join(ROOT, requirement.file), "utf8"); + for (const term of requirement.terms ?? []) { + if (!raw.includes(term)) { + errors.push(`${requirement.file} is missing required policy term ${JSON.stringify(term)}`); + } + } +} + +if (errors.length) { + console.error(`capability guard: FAIL (${errors.length})`); + for (const error of errors) console.error(` ${error}`); + process.exit(1); +} + +console.log( + `capability guard: PASS ${publicFiles.length} public routes, one canonical status source, ` + + `${(policy.claimCapabilities ?? []).length} semantic capability policies, route-aware scaffold disclosures`, +); diff --git a/scripts/check-external-links.mjs b/scripts/check-external-links.mjs new file mode 100644 index 0000000..1b7aa03 --- /dev/null +++ b/scripts/check-external-links.mjs @@ -0,0 +1,111 @@ +#!/usr/bin/env node + +import { readFileSync, readdirSync } from "node:fs"; +import { dirname, join, relative, sep } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const ALL = process.argv[2] === "--all"; + +if (process.argv.length > (ALL ? 3 : 2)) { + console.error("usage: node scripts/check-external-links.mjs [--all]"); + process.exit(2); +} + +const walkMdx = (directory, output = []) => { + for (const entry of readdirSync(directory, { withFileTypes: true })) { + if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "scripts") continue; + const path = join(directory, entry.name); + if (entry.isDirectory()) walkMdx(path, output); + else if (entry.name.endsWith(".mdx")) output.push(path); + } + return output; +}; + +const files = ALL + ? walkMdx(ROOT) + : [ + "index.mdx", + "essentials/installation.mdx", + "quickstarts/fresh-project.mdx", + "agent-setup.mdx", + "agent-setup/prompt.mdx", + "reference/compatibility.mdx", + "api-reference/summer-sdk.mdx", + "api-reference/summer-sdk/build-your-first-summer-game.mdx", + "api-reference/summer-sdk/testing-your-game-locally.mdx", + "api-reference/summer-sdk/exporting-and-uploading-your-game.mdx", + "api-reference/summer-sdk/submission-guide.mdx", + "api-reference/summer-sdk/updating-your-game.mdx", + ].map((file) => join(ROOT, file)); + +const sources = new Map(); +for (const file of files) { + const relativePath = relative(ROOT, file).split(sep).join("/"); + const raw = readFileSync(file, "utf8"); + const matches = [ + ...raw.matchAll(/(? { + while (queue.length) { + const [url, referencedBy] = queue.shift(); + try { + const response = await fetch(url.split("#")[0], { + redirect: "follow", + headers: { + "User-Agent": "SummerEngine-docs-link-check/1.0", + Range: "bytes=0-0", + }, + signal: AbortSignal.timeout(15_000), + }); + results.push({ + url, + status: response.status, + ok: response.status >= 200 && response.status < 400, + restricted: response.status === 401 || response.status === 403, + referencedBy, + }); + await response.body?.cancel(); + } catch (error) { + results.push({ url, status: String(error?.message ?? error), ok: false, restricted: false, referencedBy }); + } + } +}); + +await Promise.all(workers); +results.sort((left, right) => left.url.localeCompare(right.url, "en")); + +const restricted = results.filter((result) => result.restricted); +for (const result of restricted) { + console.warn( + `external link warning: ${result.status} ${result.url} ` + + `(access-controlled or bot-protected; ${[...result.referencedBy].sort().join(", ")})`, + ); +} + +const failures = results.filter((result) => !result.ok && !result.restricted); +for (const failure of failures) { + console.error( + `external link: ${failure.status} ${failure.url} (${[...failure.referencedBy].sort().join(", ")})`, + ); +} + +if (failures.length) { + console.error(`external links: FAIL ${failures.length}/${results.length}`); + process.exit(1); +} + +console.log( + `external links: PASS ${results.length} unique URLs across ${files.length} ${ALL ? "all" : "changed"} routes` + + `${restricted.length ? ` (${restricted.length} access-controlled warning)` : ""}`, +); diff --git a/scripts/check-language.mjs b/scripts/check-language.mjs new file mode 100644 index 0000000..6115dbf --- /dev/null +++ b/scripts/check-language.mjs @@ -0,0 +1,245 @@ +#!/usr/bin/env node + +import { existsSync, readFileSync, readdirSync } from "node:fs"; +import { dirname, join, relative, sep } from "node:path"; +import { fileURLToPath } from "node:url"; +import { scanCompatibilityClaims, scanIdentityText } from "./docs-policy-core.mjs"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const ALLOWLIST_PATH = join(ROOT, "scripts/docs-language-allowlist.json"); +const CONFIG_PATH = join(ROOT, "docs.json"); +const COMPATIBILITY_PATH = join(ROOT, "compatibility/summer-engine.json"); +const allowlist = JSON.parse(readFileSync(ALLOWLIST_PATH, "utf8")); +const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8")); +const compatibility = JSON.parse(readFileSync(COMPATIBILITY_PATH, "utf8")); + +if (allowlist.schemaVersion !== 1) { + console.error(`language guard: unsupported allowlist schema ${JSON.stringify(allowlist.schemaVersion)}`); + process.exit(1); +} + +const walkMdx = (directory, output = []) => { + for (const entry of readdirSync(directory, { withFileTypes: true })) { + if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "scripts") continue; + const path = join(directory, entry.name); + if (entry.isDirectory()) walkMdx(path, output); + else if (entry.name.endsWith(".mdx")) output.push(path); + } + return output; +}; + +const navigation = []; +function collectNavigation(node) { + if (Array.isArray(node)) { + for (const value of node) collectNavigation(value); + return; + } + if (!node || typeof node !== "object") return; + for (const [key, value] of Object.entries(node)) { + if (key === "pages" && Array.isArray(value)) { + for (const page of value) { + if (typeof page === "string") navigation.push(page); + else collectNavigation(page); + } + } else { + collectNavigation(value); + } + } +} +collectNavigation(config.navigation); + +const routeToFile = (route) => (route === "index" ? "index.mdx" : `${route.replace(/^\//, "")}.mdx`); +const publicFiles = new Set(navigation.map(routeToFile)); +const technicalGodotMetadataFiles = new Set(allowlist.technicalGodotMetadataFiles ?? []); +const currentUpstream = String(compatibility?.upstreamBase?.current?.version ?? ""); +const currentFeature = currentUpstream.match(/^(\d+\.\d+)(?:\.|$)/)?.[1]; + +const maskComments = (value) => + value + .replace(/\{\s*\/\*[\s\S]*?\*\/\s*\}/g, (match) => match.replace(/[^\n]/g, " ")) + .replace(//g, (match) => match.replace(/[^\n]/g, " ")); + +function proseLines(raw) { + const lines = maskComments(raw).split("\n"); + const output = lines.map(() => ""); + let inFrontmatter = lines[0]?.trim() === "---"; + let inFence = null; + + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + + if (inFrontmatter) { + if (index > 0 && line.trim() === "---") { + inFrontmatter = false; + continue; + } + const field = line.match(/^(title|description)\s*:\s*(.*)$/); + if (field) output[index] = field[2].replace(/^["']|["']$/g, ""); + continue; + } + + const fence = line.match(/^\s*(`{3,}|~{3,})/); + if (inFence) { + if (fence && fence[1][0] === inFence[0] && fence[1].length >= inFence.length) inFence = null; + continue; + } + if (fence) { + inFence = fence[1]; + continue; + } + + output[index] = line + .replace(/`[^`]*`/g, " ") + .replace(/\]\([^)]*\)/g, "]") + .replace(/\b(?:href|src|url)\s*=\s*["'][^"']*["']/g, " "); + } + + return output; +} + +function frontmatterMetadata(raw) { + const lines = maskComments(raw).split("\n"); + if (lines[0]?.trim() !== "---") return []; + const output = []; + for (let index = 1; index < lines.length && lines[index].trim() !== "---"; index++) { + const field = lines[index].match(/^(title|description)\s*:\s*(.*)$/); + if (field) output.push({ line: index + 1, field: field[1], value: field[2].replace(/^["']|["']$/g, "") }); + } + return output; +} + +const rules = [ + { + id: "lowercase-gdscript", + pattern: /\bgdscript\b/g, + help: "Spell the language GDScript in prose; lowercase is reserved for fenced-code tags, paths, and identifiers.", + }, +]; + +const exceptions = allowlist.exceptions ?? []; +const usedExceptions = new Map(exceptions.map((exception, index) => [index, 0])); +const errors = []; + +function consumeException(rule, file, match) { + const exceptionIndex = exceptions.findIndex( + (exception, index) => + exception.rule === rule && + exception.file === file && + exception.match === match && + usedExceptions.get(index) < exception.maxOccurrences, + ); + if (exceptionIndex < 0) return false; + usedExceptions.set(exceptionIndex, usedExceptions.get(exceptionIndex) + 1); + return true; +} + +if (!currentFeature) { + errors.push("compatibility/summer-engine.json is missing a valid upstreamBase.current.version"); +} + +const duplicateRoutes = [...new Set(navigation.filter((route, index) => navigation.indexOf(route) !== index))]; +for (const route of duplicateRoutes) errors.push(`docs.json contains duplicate public route ${route}`); +for (const file of publicFiles) { + if (!existsSync(join(ROOT, file))) errors.push(`docs.json public route is missing its source file: ${file}`); +} +for (const file of technicalGodotMetadataFiles) { + if (!publicFiles.has(file)) errors.push(`technicalGodotMetadataFiles entry is not a public navigation route: ${file}`); +} + +for (let index = 0; index < exceptions.length; index++) { + const exception = exceptions[index]; + for (const field of ["rule", "file", "match", "owner", "reason"]) { + if (typeof exception[field] !== "string" || !exception[field].trim()) { + errors.push(`allowlist exception ${index} is missing ${field}`); + } + } + if (!Number.isInteger(exception.maxOccurrences) || exception.maxOccurrences < 1) { + errors.push(`allowlist exception ${index} must have a positive maxOccurrences`); + } +} + +for (const absolute of walkMdx(ROOT)) { + const file = relative(ROOT, absolute).split(sep).join("/"); + const raw = readFileSync(absolute, "utf8"); + const lines = proseLines(raw); + + for (const metadata of frontmatterMetadata(raw)) { + if (/\bGodot\b/i.test(metadata.value) && !technicalGodotMetadataFiles.has(file)) { + errors.push( + `${file}:${metadata.line} [godot-led-metadata] ${metadata.field}=${JSON.stringify(metadata.value)} — ` + + "Lead public metadata with Summer Engine; allow Godot only on owned compatibility, migration, or extension routes.", + ); + } + } + + for (const violation of scanIdentityText(raw, { currentFeature })) { + if (consumeException(violation.rule, file, violation.match)) continue; + errors.push( + `${file}:${violation.line} [${violation.rule}] ${JSON.stringify(violation.match)} — ${violation.help}`, + ); + } + for (const violation of scanCompatibilityClaims(raw)) { + if (consumeException(violation.rule, file, violation.match)) continue; + errors.push( + `${file}:${violation.line} [${violation.rule}] ${JSON.stringify(violation.match)} — ${violation.help}`, + ); + } + + for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { + const line = lines[lineIndex]; + for (const rule of rules) { + rule.pattern.lastIndex = 0; + for (const match of line.matchAll(rule.pattern)) { + if (consumeException(rule.id, file, match[0])) continue; + errors.push(`${file}:${lineIndex + 1} [${rule.id}] ${JSON.stringify(match[0])} — ${rule.help}`); + } + } + } +} + +const scannedPublicFiles = new Set( + walkMdx(ROOT) + .map((absolute) => relative(ROOT, absolute).split(sep).join("/")) + .filter((file) => publicFiles.has(file)), +); +for (const file of publicFiles) { + if (!scannedPublicFiles.has(file)) errors.push(`language guard did not scan public route source: ${file}`); +} + +for (let index = 0; index < exceptions.length; index++) { + const exception = exceptions[index]; + const used = usedExceptions.get(index); + if (used !== exception.maxOccurrences) { + errors.push( + `allowlist exception ${index} expected ${exception.maxOccurrences} occurrence(s), found ${used}: ` + + `${exception.file} [${exception.rule}] ${JSON.stringify(exception.match)}`, + ); + } +} + +for (const requirement of allowlist.requiredTerms ?? []) { + const absolute = join(ROOT, requirement.file); + let prose; + try { + prose = proseLines(readFileSync(absolute, "utf8")).join("\n"); + } catch { + errors.push(`required-term file is missing: ${requirement.file}`); + continue; + } + for (const term of requirement.terms ?? []) { + if (!prose.includes(term)) errors.push(`${requirement.file} is missing required creator term ${JSON.stringify(term)}`); + } +} + +if (errors.length) { + console.error(`language guard: FAIL (${errors.length})`); + for (const error of errors) console.error(` ${error}`); + process.exit(1); +} + +console.log( + `language guard: PASS ${navigation.length} public routes, raw creator prompts/code/config + prose, ` + + `${rules.length} prose-only rule, ` + + `${exceptions.length} owned exceptions, ${(allowlist.requiredTerms ?? []).length} canonical routes, ` + + `project/config feature tag ${currentFeature}`, +); diff --git a/scripts/check-policy-fixtures.mjs b/scripts/check-policy-fixtures.mjs new file mode 100644 index 0000000..65bc47d --- /dev/null +++ b/scripts/check-policy-fixtures.mjs @@ -0,0 +1,84 @@ +#!/usr/bin/env node + +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { + scanCapabilityClaims, + scanCompatibilityClaims, + scanIdentityText, +} from "./docs-policy-core.mjs"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const fixtures = JSON.parse(readFileSync(join(ROOT, "scripts/policy-fixtures.json"), "utf8")); +const capabilityPolicy = JSON.parse( + readFileSync(join(ROOT, "scripts/docs-capability-policy.json"), "utf8"), +); +const currentFeature = "4.6"; +const errors = []; + +if (fixtures.schemaVersion !== 1) errors.push(`unsupported fixture schema ${fixtures.schemaVersion}`); + +for (const fixture of fixtures.languageReject ?? []) { + const found = new Set(scanIdentityText(fixture.text, { currentFeature }).map((item) => item.rule)); + for (const rule of fixture.rules ?? []) { + if (!found.has(rule)) errors.push(`${fixture.name}: expected language rule ${rule} to reject mutation`); + } +} +for (const fixture of fixtures.languageAllow ?? []) { + const found = scanIdentityText(fixture.text, { currentFeature }); + if (found.length) { + errors.push(`${fixture.name}: expected language fixture to pass, found ${found.map((item) => item.rule).join(", ")}`); + } +} + +for (const fixture of fixtures.compatibilityReject ?? []) { + const found = new Set(scanCompatibilityClaims(fixture.text).map((item) => item.rule)); + for (const rule of fixture.rules ?? []) { + if (!found.has(rule)) errors.push(`${fixture.name}: expected compatibility rule ${rule} to reject mutation`); + } +} +for (const fixture of fixtures.compatibilityAllow ?? []) { + const found = scanCompatibilityClaims(fixture.text); + if (found.length) { + errors.push( + `${fixture.name}: expected compatibility fixture to pass, found ` + + found.map((item) => item.rule).join(", "), + ); + } +} + +for (const fixture of fixtures.capabilityReject ?? []) { + const found = new Set( + scanCapabilityClaims(fixture.text, capabilityPolicy).map((item) => item.capability), + ); + for (const capability of fixture.capabilities ?? []) { + if (!found.has(capability)) { + errors.push(`${fixture.name}: expected capability ${capability} to reject mutation`); + } + } +} +for (const fixture of fixtures.capabilityAllow ?? []) { + const found = scanCapabilityClaims(fixture.text, capabilityPolicy); + if (found.length) { + errors.push( + `${fixture.name}: expected capability fixture to pass, found ` + + found.map((item) => item.capability).join(", "), + ); + } +} + +if (errors.length) { + console.error(`policy mutation fixtures: FAIL (${errors.length})`); + for (const error of errors) console.error(` ${error}`); + process.exit(1); +} + +console.log( + `policy mutation fixtures: PASS ${(fixtures.languageReject ?? []).length} language rejects, ` + + `${(fixtures.languageAllow ?? []).length} language allows, ` + + `${(fixtures.compatibilityReject ?? []).length} compatibility rejects, ` + + `${(fixtures.compatibilityAllow ?? []).length} compatibility allows, ` + + `${(fixtures.capabilityReject ?? []).length} capability rejects, ` + + `${(fixtures.capabilityAllow ?? []).length} capability allows`, +); diff --git a/scripts/check-routes.mjs b/scripts/check-routes.mjs new file mode 100644 index 0000000..4618b17 --- /dev/null +++ b/scripts/check-routes.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const CONFIG_PATH = join(ROOT, "docs.json"); +const SNAPSHOT_PATH = join(ROOT, "scripts/docs-routes.snapshot.json"); +const WRITE = process.argv[2] === "--write"; + +if (process.argv.length > (WRITE ? 3 : 2)) { + console.error("usage: node scripts/check-routes.mjs [--write]"); + process.exit(2); +} + +const config = JSON.parse(readFileSync(CONFIG_PATH, "utf8")); +const navigation = []; + +function collectPages(node) { + if (Array.isArray(node)) { + for (const value of node) collectPages(value); + return; + } + if (!node || typeof node !== "object") return; + for (const [key, value] of Object.entries(node)) { + if (key === "pages" && Array.isArray(value)) { + for (const page of value) { + if (typeof page === "string") navigation.push(page); + else collectPages(page); + } + } else { + collectPages(value); + } + } +} + +collectPages(config.navigation); +const duplicates = [...new Set(navigation.filter((page, index) => navigation.indexOf(page) !== index))]; +if (duplicates.length) { + console.error(`route snapshot: duplicate navigation routes: ${duplicates.join(", ")}`); + process.exit(1); +} + +const redirects = (config.redirects ?? []).map(({ source, destination }) => ({ source, destination })); +const snapshot = { + schemaVersion: 1, + navigation, + redirects, +}; +const rendered = JSON.stringify(snapshot, null, 2) + "\n"; + +if (WRITE) { + writeFileSync(SNAPSHOT_PATH, rendered, "utf8"); + console.log(`generated scripts/docs-routes.snapshot.json (${navigation.length} routes, ${redirects.length} redirects)`); +} else { + let actual; + try { + actual = readFileSync(SNAPSHOT_PATH, "utf8"); + } catch { + console.error("route snapshot: missing scripts/docs-routes.snapshot.json; run `npm run generate:routes`"); + process.exit(1); + } + if (actual !== rendered) { + console.error("route snapshot: stale; inspect docs.json and run `npm run generate:routes`"); + process.exit(1); + } + console.log(`route snapshot: PASS ${navigation.length} unique routes, ${redirects.length} redirects`); +} diff --git a/scripts/docs-capability-policy.json b/scripts/docs-capability-policy.json new file mode 100644 index 0000000..7de4f58 --- /dev/null +++ b/scripts/docs-capability-policy.json @@ -0,0 +1,274 @@ +{ + "schemaVersion": 2, + "canonicalPage": "knowledge-base/source-status.mdx", + "canonicalFrontmatter": "capabilityStatus: \"canonical\"", + "requiredCanonicalTerms": [ + "## Platform capability status", + "| Create Summer game records | **Live** |", + "| Browser submission and static scanner | **Live** |", + "| Summer SDK gameplay and subsystem interfaces | **Scaffold** |", + "| Browser or desktop-shell play for uploaded games | **Planned** |", + "| Hosted dedicated game servers | **Planned** |", + "| Automatic matchmaking and relay | **Planned** |", + "| Automated production runtime sandbox | **Planned** |", + "| Production gameplay runtime | **Planned** |", + "| Hosted persistence and economy | **Scaffold** |" + ], + "requiredCapabilityStatuses": [ + { + "id": "production-runtime", + "label": "Production gameplay runtime", + "state": "Planned" + }, + { + "id": "hosted-persistence-economy", + "label": "Hosted persistence and economy", + "state": "Scaffold" + } + ], + "claimCapabilities": [ + { + "id": "uploaded-game-playback", + "label": "Uploaded-game browser and desktop-shell playback", + "state": "Planned", + "subjectAliases": [ + "\\buploaded\\s+(?:Summer\\s+games?|creator\\s+builds?|games?|builds?)\\b", + "\\bbrowser\\s+(?:or\\s+desktop[- ]shell\\s+)?play(?:back)?\\b", + "\\bdesktop[- ]shell\\s+play(?:back)?\\b", + "\\bplayer-facing\\s+(?:play|playback|launch)\\b", + "\\bweb client\\b" + ], + "assertionVerbs": [], + "assertionPatterns": [ + "\\b(?:players?\\s+)?can\\s+(?:launch|play)\\b", + "\\b(?:is|are)\\s+ready\\s+(?:for\\s+(?:players?\\s+to\\s+)?|to\\s+)?(?:launch|play)\\b" + ], + "assertionTerms": [ + "\\bplayable\\b", + "\\boperational\\b", + "\\bproduction[- ]live\\b" + ], + "statusTerms": ["\\bPlanned\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bmust\\s+not\\s+promise\\b" + ] + }, + { + "id": "managed-matchmaking", + "label": "Managed matchmaking and relay", + "state": "Planned", + "subjectAliases": [ + "\\bmatchmaking\\b", + "\\brelay(?: service| server)?s?\\b", + "\\bplayers?\\b.{0,50}\\blobb(?:y|ies)\\b" + ], + "assertionVerbs": ["pair", "provide", "offer", "handle", "manage"], + "assertionTerms": [ + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bPlanned\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bmust\\s+not\\s+promise\\b" + ] + }, + { + "id": "hosted-game-servers", + "label": "Hosted dedicated game servers", + "state": "Planned", + "subjectAliases": [ + "\\b(?:hosted|managed|dedicated)\\b.{0,50}\\b(?:game\\s+)?servers?\\b", + "\\bserver hosting\\b", + "\\bcloud game instances?\\b" + ], + "assertionVerbs": [], + "assertionPatterns": [ + "\\b(?:we|Summer|Summercraft|the platform|platform)\\s+(?:runs?|provisions?|provides?|offers?|manages?|hosts?)\\b", + "\\b(?:servers?|instances?)\\s+(?:are|is)\\s+(?:run|running|provisioned|provided|available|live|operational|deployed)\\b" + ], + "assertionTerms": [ + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bPlanned\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bmust\\s+not\\s+promise\\b" + ] + }, + { + "id": "production-sandbox", + "label": "Automated production runtime sandbox", + "state": "Planned", + "subjectAliases": [ + "\\b(?:automated\\s+)?(?:production\\s+)?runtime sandbox\\b", + "\\bautomated sandbox\\b", + "\\buploaded packs?\\b.{0,50}\\bin production\\b" + ], + "assertionVerbs": ["execute", "run", "isolate", "scan"], + "assertionTerms": [ + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bPlanned\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bmust\\s+not\\s+promise\\b" + ] + }, + { + "id": "summer-multiplayer-transport", + "label": "SummerMultiplayerPeer production transport", + "state": "Scaffold", + "subjectAliases": [ + "\\bSummerMultiplayerPeer\\b", + "\\bSummer(?:'s|’s) multiplayer peer\\b", + "\\bproduction transport\\b" + ], + "assertionVerbs": ["power", "provide", "handle", "run", "implement"], + "assertionTerms": [ + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\bworking\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bScaffold(?:ed)?\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bcontract(?:-level)?\\s+(?:example|only|requirement|interface|behavior)\\b" + ] + }, + { + "id": "production-runtime", + "label": "Production gameplay runtime", + "state": "Planned", + "subjectAliases": [ + "\\b(?:production(?: gameplay)?|platform|Summercraft)\\s+runtime\\b", + "\\bapproved packs?\\b", + "\\breview process\\b" + ], + "assertionAfterSubject": true, + "assertionBeforeSubjectPatterns": [ + "\\b(?:runs?|ran|running|loads?|loaded|loading|executes?|executed|executing)\\b.{0,80}\\bapproved packs?\\b" + ], + "assertionVerbs": ["execute", "load", "run", "enforce", "refuse", "assign", "connect"], + "assertionTerms": [ + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bPlanned\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bcontract(?:-level)?\\s+(?:example|only|requirement|interface|behavior)\\b", + "\\bmust\\s+not\\s+promise\\b" + ] + }, + { + "id": "hosted-persistence-economy", + "label": "Hosted persistence and economy", + "state": "Scaffold", + "subjectAliases": [ + "\\bSummer\\.(?:data|economy)\\b", + "\\bSummer storage\\b", + "\\bhosted persistence and economy\\b", + "\\bpersistence backend\\b", + "\\beconomy rail\\b", + "\\bbackend flush\\b" + ], + "assertionVerbs": ["persist", "store", "write", "keep"], + "objectRequiredAssertionVerbs": ["persist", "store", "write", "keep"], + "objectRequiredAssertionPatterns": [ + "\\bauto-?saves?\\b" + ], + "assertionObjectHeads": [ + "save", + "saves", + "data", + "progress", + "state", + "inventory", + "balance", + "economy" + ], + "assertionPrepositionalObjectPatterns": [ + "\\bto\\s+durable storage\\b" + ], + "coreferenceObjectHeads": [ + "save", + "saves", + "data", + "progress", + "state", + "inventory", + "balance" + ], + "coreferenceAntecedentBarrierPatterns": [ + "\\bexamples?\\b", + "\\bdocs?\\b", + "\\bdocumentation\\b", + "\\breferences?\\b" + ], + "objectPronounPatterns": [ + "\\bthem\\b" + ], + "objectPronounAssertionContextPatterns": [ + "\\bdurabl(?:e|y)\\b", + "\\bproduction\\b", + "\\bbetween\\s+(?:production\\s+)?sessions\\b", + "\\bpersist(?:s|ed|ing|ence|ent)?\\b" + ], + "assertionTerms": [ + "\\bhandled\\b", + "\\bdurable\\b", + "\\blive\\b", + "\\bavailable\\b", + "\\bdeployed\\b", + "\\boperational\\b" + ], + "statusTerms": ["\\bScaffold(?:ed)?\\b", "\\bnot\\s+(?:production[- ]?)?live\\b"], + "disclaimerPatterns": [ + "\\b(?:does|do)\\s+not\\s+(?:claim|mean|prove|imply)\\b", + "\\bcontract(?:-level)?\\s+(?:example|only|requirement|interface|behavior)\\b" + ] + } + ], + "scaffoldDisclosureIndicators": [ + "\\bSummerMultiplayerPeer\\b", + "\\bSummerGame\\b", + "\\bSummerPlayer\\b", + "\\bSummerCharacter3D\\b", + "\\bSummer\\.(?:data|economy|teams|score|input|ui|audio)\\b", + "\\bset_synced\\b", + "\\bget_synced\\b" + ], + "scaffoldDisclosureExemptions": [ + { + "file": "changelog/overview.mdx", + "owner": "docs-changelog", + "reason": "Historical release notes name SDK symbols but do not serve as current capability reference." + } + ], + "requiredRouteTerms": [ + { + "file": "api-reference/summer-sdk/production-launch-runbook.mdx", + "terms": [ + "Recommended release API", + "1 KiB–512 MiB", + "Browser submission", + "up to 2 GB", + "does not raise the release API's" + ] + } + ] +} diff --git a/scripts/docs-language-allowlist.json b/scripts/docs-language-allowlist.json new file mode 100644 index 0000000..d7375ee --- /dev/null +++ b/scripts/docs-language-allowlist.json @@ -0,0 +1,66 @@ +{ + "schemaVersion": 1, + "technicalGodotMetadataFiles": [ + "extending/gdextension.mdx" + ], + "exceptions": [ + { + "rule": "godot-game", + "file": "publishing/consoles.mdx", + "match": "Godot games", + "maxOccurrences": 1, + "owner": "docs-publishing", + "reason": "Technical platform-holder prerequisite describing an applicant's prior Switch publishing record." + }, + { + "rule": "lowercase-gdscript", + "file": "mcp/skills.mdx", + "match": "gdscript", + "maxOccurrences": 1, + "owner": "docs-mcp", + "reason": "Literal gdscript-patterns skill identifier; the adjacent prose spells GDScript correctly." + } + ], + "requiredTerms": [ + { + "file": "index.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript", "Summer SDK"] + }, + { + "file": "essentials/installation.mdx", + "terms": ["Summer Engine", "Summer game"] + }, + { + "file": "quickstarts/fresh-project.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript", "Summer SDK"] + }, + { + "file": "api-reference/summer-sdk/build-your-first-summer-game.mdx", + "terms": ["Summer game", "GDScript", "Summer SDK"] + }, + { + "file": "api-reference/summer-sdk.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript", "Summer SDK"] + }, + { + "file": "api-reference/summer-sdk/testing-your-game-locally.mdx", + "terms": ["Summer Engine", "Summer game", "Summer SDK"] + }, + { + "file": "api-reference/summer-sdk/exporting-and-uploading-your-game.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript"] + }, + { + "file": "api-reference/summer-sdk/submission-guide.mdx", + "terms": ["Summer game", "GDScript"] + }, + { + "file": "api-reference/summer-sdk/updating-your-game.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript", "Summer SDK"] + }, + { + "file": "agent-setup/prompt.mdx", + "terms": ["Summer Engine", "Summer game", "GDScript", "Summer SDK"] + } + ] +} diff --git a/scripts/docs-policy-core.mjs b/scripts/docs-policy-core.mjs new file mode 100644 index 0000000..514f95c --- /dev/null +++ b/scripts/docs-policy-core.mjs @@ -0,0 +1,608 @@ +const maskComments = (value) => + value + .replace(/\{\s*\/\*[\s\S]*?\*\/\s*\}/g, (match) => match.replace(/[^\n]/g, " ")) + .replace(//g, (match) => match.replace(/[^\n]/g, " ")); + +const identityRules = [ + { + id: "godot-game", + pattern: /\bGodot games?\b/gi, + help: "Use Summer game in creator-facing prose and prompts.", + }, + { + id: "godot-sdk", + pattern: /\bGodot SDK\b/gi, + help: "The creator-facing platform contract is the Summer SDK.", + }, + { + id: "summer-godot-product", + pattern: /\bSummer\s*\/\s*Godot\b/gi, + help: "Call the creator product Summer Engine.", + }, + { + id: "default-godot-45", + pattern: + /(?:\b(?:install|download|require|required|prerequisite|use|run)\b.{0,100}\bGodot(?: Engine)?\s+4\.5\b|\bGodot(?: Engine)?\s+4\.5\b.{0,100}\b(?:install|download|required|prerequisite|use|run)\b)/gi, + help: "Default onboarding installs Summer Engine; the pinned current upstream feature tag is not 4.5.", + }, + { + id: "godot-product-equivalence", + pattern: + /\b(?:Summer(?: Engine)? (?:is|projects? are) Godot|Summer games? (?:are|is) Godot|Godot is (?:the )?Summer Engine)\b/gi, + help: "Upstream lineage is a compatibility fact, not Summer product identity.", + }, + { + id: "upstream-as-product-version", + pattern: /\bSummer Engine\s+4\.\d+(?:\.\d+)?\b/gi, + help: "Do not present the upstream technical base as the Summer Engine product release.", + }, + { + id: "unqualified-broad-platform-export", + pattern: + /^(?=.{0,300}\b(?:export|publish)\b)(?=.{0,300}\bSteam\b)(?=.{0,300}\bitch\.io\b)(?=.{0,300}\b(?:mobile|consoles?)\b).+$/gim, + help: "Name the installed target templates/toolchains and keep store submission creator-controlled.", + }, + { + id: "no-code-complete-game", + pattern: + /^(?=.{0,240}\b(?:build|make|create)\b.{0,60}\bcomplete games?\b)(?=.{0,240}\b(?:without writing code|no cod(?:e|ing) (?:needed|required))\b).+$/gim, + help: "Natural-language generation still requires creator review, testing, and integration.", + }, + { + id: "fixed-24h-model-promise", + pattern: + /^(?=.{0,300}\b(?:all|every)\b)(?=.{0,300}\b(?:AI|image|3D|video|models?|breakthrough)\b)(?=.{0,300}\b(?:within|in)?\s*(?:24\s+hours?|one day)\b).+$/gim, + help: "Document evaluated provider availability instead of promising every new model on a fixed schedule.", + }, +]; + +export function scanIdentityText(raw, { currentFeature } = {}) { + const errors = []; + const masked = maskComments(raw); + const lines = masked.split("\n"); + + for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { + const line = lines[lineIndex]; + for (const rule of identityRules) { + rule.pattern.lastIndex = 0; + for (const match of line.matchAll(rule.pattern)) { + errors.push({ + rule: rule.id, + line: lineIndex + 1, + match: match[0], + help: rule.help, + }); + } + } + } + + if (currentFeature) { + const featurePattern = /config\/features\s*=\s*PackedStringArray\(\s*"(\d+\.\d+)"/g; + for (const match of masked.matchAll(featurePattern)) { + if (match[1] === currentFeature) continue; + errors.push({ + rule: "stale-project-feature", + line: masked.slice(0, match.index).split("\n").length, + match: match[0], + help: + `Project/config examples must use the current upstream feature tag ${currentFeature}; ` + + "Summer Engine follows upstream continuously.", + }); + } + } + + return errors; +} + +const compatibilityRules = [ + { + id: "blanket-works-perfectly", + pattern: + /\bworks?\b(?:\s+in\s+Summer)?\s+(?:perfectly|identically|exactly|as-is|unchanged|without changes)\b/gi, + help: "Compatibility ranges are unmeasured; require a committed-copy test and explicit caveats.", + }, + { + id: "blanket-no-conversion", + pattern: /\bno conversion required\b/gi, + help: "Familiar formats do not prove zero conversion or import work for every project.", + }, + { + id: "blanket-all-assets", + pattern: + /\b(?:all|every)\b.{0,80}\b(?:existing projects?|scenes?|scripts?|plugins?|tutorials?|assets?)\b.{0,80}\b(?:work|works|open|compatible|apply)\b/gi, + help: "Avoid universal compatibility claims; name measured formats and version-sensitive checks.", + }, + { + id: "blanket-completely-compatible", + pattern: /\bcompletely compatible\b/gi, + help: "Project minimum and recommended compatibility ranges are unmeasured.", + }, + { + id: "blanket-open-as-is", + pattern: /\bopen\b.{0,50}\bprojects?\s+as-is\b/gi, + help: "Opening an existing project is a compatibility evaluation, not an as-is guarantee.", + }, + { + id: "blanket-open-and-continue", + pattern: + /\bopen\b.{0,60}\b(?:existing\s+)?projects?\b.{0,80}\b(?:continue working|keep (?:building|working))\b/gi, + help: "Opening an existing project is a compatibility evaluation; require a committed-copy test and explicit checks.", + }, + { + id: "blanket-transitive-load", + pattern: /\bif it loads\b.{0,100}\bit loads\b/gi, + help: "An upstream load is evidence, not proof for Summer, another platform, or export.", + }, +]; + +export function scanCompatibilityClaims(raw) { + const errors = []; + for (const claim of claimGroups(raw)) { + for (const clause of claim.clauses) { + for (const rule of compatibilityRules) { + rule.pattern.lastIndex = 0; + for (const match of clause.matchAll(rule.pattern)) { + if (isLocallyNegated(clause, match.index)) continue; + if (isLocallyModal(clause, match.index)) continue; + errors.push({ + rule: rule.id, + line: claim.line, + match: match[0], + help: rule.help, + }); + } + } + } + } + return errors; +} + +function sentenceUnits(raw) { + const lines = maskComments(raw).split("\n"); + const visible = lines.map(() => ""); + let inFrontmatter = lines[0]?.trim() === "---"; + + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + if (inFrontmatter) { + if (index > 0 && line.trim() === "---") { + inFrontmatter = false; + continue; + } + const field = line.match(/^(title|description)\s*:\s*(.*)$/); + if (field) visible[index] = field[2].replace(/^["']|["']$/g, ""); + continue; + } + + const fence = line.match(/^\s*(`{3,}|~{3,})/); + if (fence) { + continue; + } + + visible[index] = line + .replace(/\]\([^)]*\)/g, "]") + .replace(/\b(?:href|src|url)\s*=\s*["'][^"']*["']/g, " "); + } + + const segments = []; + let paragraph = []; + let paragraphStart = 1; + const flush = () => { + if (!paragraph.length) return; + const text = paragraph.join(" "); + for (const sentence of text.split(/(?<=[.!?])\s+/)) { + const trimmed = sentence.trim(); + if (trimmed) segments.push({ line: paragraphStart, text: trimmed }); + } + paragraph = []; + }; + + for (let index = 0; index < visible.length; index++) { + const line = visible[index].trim(); + if (!line) { + flush(); + continue; + } + if (/^(?:#{1,6}\s|[-*+]\s|\d+\.\s|\||<)/.test(line)) { + flush(); + for (const sentence of line.split(/(?<=[.!?])\s+/)) { + if (sentence.trim()) segments.push({ line: index + 1, text: sentence.trim() }); + } + continue; + } + if (!paragraph.length) paragraphStart = index + 1; + paragraph.push(line); + } + flush(); + return segments; +} + +const splitClauses = (text) => + text + .split( + /\s*(?:;|,\s*(?:but|yet|however|nevertheless)\b|\b(?:but|however|nevertheless)\b|(? clause.trim()) + .filter(Boolean); + +function claimGroups(raw) { + return sentenceUnits(raw).map((sentence) => ({ + line: sentence.line, + text: sentence.text, + clauses: splitClauses(sentence.text), + })); +} + +const LOCAL_NEGATION = + /(?:^|\b)(?:not|never|cannot|can't|couldn't|doesn't|does\s+not|do\s+not|did\s+not|isn't|is\s+not|aren't|are\s+not|won't|will\s+not|must\s+not|no|without|rather\s+than|instead\s+of)(?:\s+[\w'’.-]+){0,7}\s*$/i; +const LOCAL_MODAL = /(?:^|\b)(?:may|might|could)(?:\s+[\w'’.-]+){0,4}\s*$/i; +const LOCAL_HYPOTHETICAL = + /(?:^|\b)(?:if|assuming|supposing)(?:\s+[\w'’.-]+){0,10}\s*$/i; +const ASSERTION_SCOPE_BREAK = + /\b(?:and|but|however|nevertheless|while|whereas|then)\b|(? pattern.test(scope)); +} + +function beginsWithCapabilityAnaphor(text) { + const value = text + .replace(/^(?:[-*+>#|]|\d+\.)+\s*/, "") + .replace(/^(?:but|yet|however|nevertheless),?\s+/i, "") + .replace(/^[,:\s]+/, "") + .trim(); + return ( + /^(?:it|they)\b/i.test(value) || + /^(?:this|that)\s+(?:is|was|remains?|runs?|loads?|executes?|provides?|keeps?|stores?|writes?|capability|service|runtime|backend|transport|system|feature|path)\b/i.test( + value, + ) || + /^(?:these|those)\s+(?:are|were|remain|run|load|execute|provide|keep|store|write|capabilities|services|runtimes|backends|transports|systems|features|paths)\b/i.test( + value, + ) + ); +} + +const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +const irregularVerbForms = new Map([ + ["keep", ["keep", "keeps", "kept", "keeping"]], + ["run", ["run", "runs", "ran", "running"]], + ["write", ["write", "writes", "wrote", "written", "writing"]], +]); + +function regularVerbForms(verb) { + const forms = new Set([verb]); + if (verb.endsWith("e")) { + forms.add(`${verb}s`); + forms.add(`${verb}d`); + forms.add(`${verb.slice(0, -1)}ing`); + } else if (/(?:s|x|z|ch|sh)$/.test(verb)) { + forms.add(`${verb}es`); + forms.add(`${verb}ed`); + forms.add(`${verb}ing`); + } else if (verb.endsWith("y") && !/[aeiou]y$/.test(verb)) { + forms.add(`${verb.slice(0, -1)}ies`); + forms.add(`${verb.slice(0, -1)}ied`); + forms.add(`${verb}ing`); + } else { + forms.add(`${verb}s`); + forms.add(`${verb}ed`); + forms.add(`${verb}ing`); + } + return [...forms]; +} + +const verbPattern = (verb) => { + const forms = irregularVerbForms.get(verb) ?? regularVerbForms(verb); + return new RegExp(`\\b(?:${forms.map(escapeRegex).join("|")})\\b`, "gi"); +}; + +const compile = (patterns, flags = "i") => + (patterns ?? []).map((pattern) => new RegExp(pattern, flags)); + +function compileCapability(capability) { + const objectRequiredVerbs = new Set(capability.objectRequiredAssertionVerbs ?? []); + return { + ...capability, + aliasPatterns: compile(capability.subjectAliases), + assertionPatterns: [ + ...compile(capability.assertionPatterns, "gi").map((pattern) => ({ + pattern, + kind: "pattern", + requiresObject: false, + })), + ...compile(capability.objectRequiredAssertionPatterns, "gi").map((pattern) => ({ + pattern, + kind: "pattern", + requiresObject: true, + })), + ...compile(capability.assertionTerms, "gi").map((pattern) => ({ + pattern, + kind: "term", + requiresObject: false, + })), + ...(capability.assertionVerbs ?? []).map((verb) => ({ + pattern: verbPattern(verb), + kind: "verb", + requiresObject: objectRequiredVerbs.has(verb), + })), + ], + assertionObjectHeads: new Set( + (capability.assertionObjectHeads ?? []).map((head) => head.toLocaleLowerCase("en-US")), + ), + assertionPrepositionalObjectPatterns: compile( + capability.assertionPrepositionalObjectPatterns, + ), + coreferenceObjectHeads: new Set( + (capability.coreferenceObjectHeads ?? []).map((head) => head.toLocaleLowerCase("en-US")), + ), + coreferenceAntecedentBarrierPatterns: compile( + capability.coreferenceAntecedentBarrierPatterns, + ), + objectPronounPatterns: compile(capability.objectPronounPatterns), + objectPronounAssertionContextPatterns: compile( + capability.objectPronounAssertionContextPatterns, + ), + statusPatterns: compile(capability.statusTerms), + disclaimerPatterns: compile(capability.disclaimerPatterns), + assertionBeforeSubjectPatterns: compile(capability.assertionBeforeSubjectPatterns), + }; +} + +function clauseHasAlias(clause, capability) { + return capability.aliasPatterns.some((pattern) => pattern.test(clause)); +} + +function firstAliasIndex(clause, capability) { + let first = Number.POSITIVE_INFINITY; + for (const pattern of capability.aliasPatterns) { + const match = clause.match(pattern); + if (match?.index < first) first = match.index; + } + return first; +} + +function assertionMatches(clause, capability) { + const matches = []; + for (const assertion of capability.assertionPatterns) { + const { pattern } = assertion; + pattern.lastIndex = 0; + for (const match of clause.matchAll(pattern)) { + matches.push({ + index: match.index, + text: match[0], + kind: assertion.kind, + requiresObject: assertion.requiresObject, + }); + } + } + return matches.sort((a, b) => a.index - b.index); +} + +function assertionTermIsPredicate(clause, assertion, capability) { + if (assertion.kind !== "term") return true; + const prefix = localAssertionPrefix(clause, assertion.index).trim(); + if ( + /(?:^|\b)(?:is|are|was|were|remains?|becomes?|stays?)(?:\s+(?:not|never|currently|presently|production[- ]?))*\s*$/i.test( + prefix, + ) + ) { + return true; + } + + for (const alias of capability.aliasPatterns) { + const match = clause.match(alias); + if (!match || match.index > assertion.index) continue; + const gap = clause.slice(match.index + match[0].length, assertion.index); + const normalizedGap = gap.replace(/^(?:\s|[*_`|:()-])+|(?:\s|[*_`|:()-])+$/g, ""); + if ( + !normalizedGap || + /^(?:is|are|was|were|remains?|becomes?|stays?)(?:\s+(?:not|never|currently|presently|production[- ]?))*$/i.test( + normalizedGap, + ) + ) { + return true; + } + } + return prefix.replace(/^[,:\s]+/, "").length === 0; +} + +const DIRECT_OBJECT_BOUNDARY = + /[,;.!?]|\b(?:in|on|at|for|with|without|from|to|into|onto|of|about|regarding|showing|describing|during|between|across|through|via|as|while|when|if|but|yet|however|and|or)\b/i; + +function directObjectInfo(clause, assertion) { + const tail = clause.slice(assertion.index + assertion.text.length); + const boundary = tail.search(DIRECT_OBJECT_BOUNDARY); + const phrase = (boundary === -1 ? tail : tail.slice(0, boundary)) + .replace(/[*_`|:[\](){}]/g, " ") + .trim(); + const tokens = phrase.toLocaleLowerCase("en-US").match(/[a-z][a-z'’-]*/g) ?? []; + while ( + tokens.length && + (tokens.at(-1).endsWith("ly") || + ["today", "now", "currently", "automatically"].includes(tokens.at(-1))) + ) { + tokens.pop(); + } + return { head: tokens.at(-1) ?? null, phrase }; +} + +function assertionHasCompatibleObject( + clause, + assertion, + capability, + { allowObjectPronoun = false } = {}, +) { + if (!assertion.requiresObject) return true; + const { head } = directObjectInfo(clause, assertion); + if (head && capability.assertionObjectHeads.has(head)) return true; + const scope = localAssertionScope(clause, assertion.index); + if ( + capability.assertionPrepositionalObjectPatterns.some((pattern) => pattern.test(scope)) + ) { + return true; + } + return ( + allowObjectPronoun && + head !== null && + capability.objectPronounPatterns.some((pattern) => pattern.test(head)) && + capability.objectPronounAssertionContextPatterns.some((pattern) => pattern.test(scope)) + ); +} + +function compatibleAssertionMatches(clause, capability, options = {}) { + return assertionMatches(clause, capability).filter( + (assertion) => + assertionTermIsPredicate(clause, assertion, capability) && + assertionHasCompatibleObject(clause, assertion, capability, options), + ); +} + +function beginsWithEllipticalCapabilityPredicate(clause, capability, options = {}) { + const value = clause + .replace(/^(?:[-*+>#|]|\d+\.)+\s*/, "") + .replace(/^(?:but|yet|however|nevertheless),?\s+/i, "") + .replace(/^[,:\s]+/, "") + .trim(); + return compatibleAssertionMatches(value, capability, options).some((assertion) => { + if (assertion.index === 0) return true; + const prefix = value.slice(0, assertion.index).trim(); + return /^(?:(?:is|are|was|were|remains?|becomes?|can|could|may|might|will|would|does|do)\b(?:\s+\w+){0,2})$/i.test( + prefix, + ); + }); +} + +function introducesExplicitCoreferenceObject(clause, capability) { + return compatibleAssertionMatches(clause, capability).some( + (assertion) => { + if (!assertion.requiresObject) return false; + const object = directObjectInfo(clause, assertion); + return ( + object.head !== null && + capability.coreferenceObjectHeads.has(object.head) && + !capability.coreferenceAntecedentBarrierPatterns.some((pattern) => + pattern.test(object.phrase), + ) + ); + }, + ); +} + +function isLocallyDisclaimed(clause, assertionIndex, capability) { + const prefix = localAssertionPrefix(clause, assertionIndex); + return capability.disclaimerPatterns.some((pattern) => pattern.test(prefix)); +} + +export function scanCapabilityClaims(raw, policy) { + const errors = []; + const capabilities = (policy.claimCapabilities ?? []).map(compileCapability); + let previousSentenceCapabilities = []; + + for (const claim of claimGroups(raw)) { + const firstClauseIsAnaphoric = beginsWithCapabilityAnaphor(claim.clauses[0] ?? ""); + let carriedCapabilities = firstClauseIsAnaphoric ? previousSentenceCapabilities : []; + let sentenceCapabilities = carriedCapabilities; + let priorClauseObjectCapabilities = new Set(); + for (const clause of claim.clauses) { + const explicitCapabilities = capabilities.filter((capability) => + clauseHasAlias(clause, capability), + ); + const ellipticalCapabilities = carriedCapabilities.filter((capability) => + beginsWithEllipticalCapabilityPredicate(clause, capability, { + allowObjectPronoun: priorClauseObjectCapabilities.has(capability.id), + }), + ); + const activeCapabilities = explicitCapabilities.length + ? explicitCapabilities + : beginsWithCapabilityAnaphor(clause) + ? carriedCapabilities + : ellipticalCapabilities; + if (explicitCapabilities.length) { + carriedCapabilities = explicitCapabilities; + sentenceCapabilities = explicitCapabilities; + } else if (activeCapabilities.length) { + sentenceCapabilities = activeCapabilities; + } + + for (const capability of activeCapabilities) { + const aliasIndex = firstAliasIndex(clause, capability); + const assertions = compatibleAssertionMatches(clause, capability, { + allowObjectPronoun: priorClauseObjectCapabilities.has(capability.id), + }).filter( + (assertion) => + !capability.assertionAfterSubject || + !Number.isFinite(aliasIndex) || + assertion.index > aliasIndex || + capability.assertionBeforeSubjectPatterns.some((pattern) => + pattern.test(clause.slice(assertion.index)), + ), + ); + const hasStatus = capability.statusPatterns.some((pattern) => pattern.test(clause)); + if (!assertions.length && hasStatus) continue; + + const positive = assertions.find( + (assertion) => + !isLocallyNegated(clause, assertion.index) && + !isLocallyDisclaimed(clause, assertion.index, capability) && + !isLocallyModal(clause, assertion.index) && + !isLocallyHypothetical(clause, assertion.index) && + !isLocalOrPrivateTestAssertion(clause, assertion.index), + ); + if (!positive) continue; + + errors.push({ + capability: capability.id, + state: capability.state, + line: claim.line, + text: clause, + assertion: positive.text, + help: + `${capability.label} is ${capability.state}. Describe a contract/example or link to the ` + + "canonical status instead of implying deployed production behavior.", + }); + } + priorClauseObjectCapabilities = new Set( + explicitCapabilities + .filter((capability) => introducesExplicitCoreferenceObject(clause, capability)) + .map((capability) => capability.id), + ); + } + previousSentenceCapabilities = sentenceCapabilities; + } + + return errors; +} diff --git a/scripts/docs-routes.snapshot.json b/scripts/docs-routes.snapshot.json new file mode 100644 index 0000000..9b644d4 --- /dev/null +++ b/scripts/docs-routes.snapshot.json @@ -0,0 +1,268 @@ +{ + "schemaVersion": 1, + "navigation": [ + "index", + "essentials/installation", + "quickstarts/fresh-project", + "api-reference/summer-sdk/build-your-first-summer-game", + "api-reference/summer-sdk", + "api-reference/summer-sdk/testing-your-game-locally", + "api-reference/summer-sdk/exporting-and-uploading-your-game", + "api-reference/summer-sdk/submission-guide", + "api-reference/summer-sdk/updating-your-game", + "quickstarts/ai-game-dev", + "quickstarts/web-game", + "quickstarts/pc-game", + "quickstarts/mac-game", + "quickstarts/ios-game", + "quickstarts/android-game", + "quickstarts/console-game", + "quickstarts/playstation-game", + "essentials/authentication", + "essentials/account-billing", + "essentials/pricing", + "essentials/first-chat", + "essentials/faq", + "auto-mode/auto", + "auto-mode/premium", + "auto-mode/models", + "ai-tools/design-mode", + "ai-tools/operations", + "ai-tools/subagents", + "ai-tools/skills", + "ai-tools/memory", + "ai-tools/rag-search", + "ai-tools/mcp-asset-search", + "art-system/overview", + "art-system/ai-generation", + "art-system/gallery", + "art-system/collections", + "art-system/licensing", + "quickstarts/unity-migration", + "quickstarts/unreal-migration", + "automation/headless", + "automation/authoring", + "desktop/troubleshooting", + "mcp/overview", + "mcp/setup", + "mcp/cursor", + "mcp/claude-code", + "mcp/devin-desktop", + "mcp/antigravity", + "mcp/codex", + "mcp/gemini", + "mcp/github-copilot", + "mcp/opencode", + "mcp/local-models", + "mcp/vscode", + "mcp/zed", + "mcp/cli", + "mcp/cli-reference", + "mcp/cloud-cli", + "mcp/tools-reference", + "mcp/building-a-game", + "mcp/skills", + "api-reference/summer-sdk/summer", + "api-reference/summer-sdk/summer-game", + "api-reference/summer-sdk/summer-player", + "api-reference/summer-sdk/subsystems-signals", + "api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector", + "api-reference/summer-sdk/guides/multiplayer-persistence-rpg", + "api-reference/summer-sdk/guides/team-based-game", + "api-reference/summer-sdk/guides/making-a-2d-game-multiplayer", + "api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer", + "agent-setup", + "agent-setup/prompt", + "api-reference/summer-sdk/ai-agent-playbook", + "api-reference/summer-sdk/manifest-json-reference", + "api-reference/summer-sdk/banned-apis-reference", + "api-reference/summer-sdk/naming", + "reference/compatibility", + "api-reference/summer-sdk/production-launch-runbook", + "quickstarts/existing-godot", + "migration/godot", + "extending/overview", + "extending/editor-plugins", + "extending/gdextension", + "extending/modules", + "extending/plugin-library", + "api-reference/mcp", + "guides/working-with-context", + "guides/large-codebases", + "guides/working-with-documentation", + "guides/web-development", + "guides/github-from-changes-dock", + "guides/summer-cloud", + "publishing/overview", + "publishing/macos-export", + "publishing/windows-export", + "publishing/local-testing", + "publishing/steam", + "publishing/itch-io", + "publishing/consoles", + "publishing/troubleshooting", + "knowledge-base/what-is-summer", + "knowledge-base/summer-vs-chatgpt", + "knowledge-base/beginners-or-professionals", + "knowledge-base/production-games", + "knowledge-base/learning-curve", + "knowledge-base/aaa-games", + "knowledge-base/source-status", + "knowledge-base/summer-vs-other-tools", + "knowledge-base/godot-compatibility", + "knowledge-base/godot-projects", + "knowledge-base/ai-models", + "knowledge-base/ai-asset-quality", + "knowledge-base/ai-game-dev", + "knowledge-base/specialist-agents", + "knowledge-base/project-intelligence", + "knowledge-base/ai-operations-limitations", + "knowledge-base/multiplayer", + "knowledge-base/custom-assets", + "knowledge-base/web-games", + "knowledge-base/unity-unreal-migration", + "knowledge-base/privacy-and-code-safety", + "knowledge-base/pricing", + "knowledge-base/support", + "knowledge-base/no-experience", + "knowledge-base/publish-steam", + "knowledge-base/export-mobile", + "changelog/overview", + "security/overview", + "security/privacy-mode" + ], + "redirects": [ + { + "source": "/api-reference/coming-soon", + "destination": "/api-reference/mcp" + }, + { + "source": "/ai-tools/mcp-setup", + "destination": "/mcp/setup" + }, + { + "source": "/ai-tools/cursor-setup", + "destination": "/mcp/cursor" + }, + { + "source": "/ai-tools/claude-code-setup", + "destination": "/mcp/claude-code" + }, + { + "source": "/ai-tools/windsurf-setup", + "destination": "/mcp/devin-desktop" + }, + { + "source": "/mcp/windsurf", + "destination": "/mcp/devin-desktop" + }, + { + "source": "/ai-tools/cli-reference", + "destination": "/mcp/cli-reference" + }, + { + "source": "/ai-tools/tools-reference", + "destination": "/mcp/tools-reference" + }, + { + "source": "/ai-tools/building-a-game", + "destination": "/mcp/building-a-game" + }, + { + "source": "/cli", + "destination": "/mcp/cli" + }, + { + "source": "/quickstart", + "destination": "/quickstarts/fresh-project" + }, + { + "source": "/mcp/Root", + "destination": "/mcp/cursor" + }, + { + "source": "/Applications/Summer.app", + "destination": "/essentials/installation" + }, + { + "source": "/mcp/projects/racer", + "destination": "/mcp/cli-reference" + }, + { + "source": "/knowledge-base/whats-next", + "destination": "/knowledge-base/what-is-summer" + }, + { + "source": "/api-reference/crafty-sdk", + "destination": "/api-reference/summer-sdk" + }, + { + "source": "/api-reference/crafty-sdk/crafty", + "destination": "/api-reference/summer-sdk/summer" + }, + { + "source": "/api-reference/crafty-sdk/crafty-game", + "destination": "/api-reference/summer-sdk/summer-game" + }, + { + "source": "/api-reference/crafty-sdk/crafty-player", + "destination": "/api-reference/summer-sdk/summer-player" + }, + { + "source": "/api-reference/crafty-sdk/build-your-first-crafty-game", + "destination": "/api-reference/summer-sdk/build-your-first-summer-game" + }, + { + "source": "/api-reference/crafty-sdk/subsystems-signals", + "destination": "/api-reference/summer-sdk/subsystems-signals" + }, + { + "source": "/api-reference/crafty-sdk/manifest-json-reference", + "destination": "/api-reference/summer-sdk/manifest-json-reference" + }, + { + "source": "/api-reference/crafty-sdk/production-launch-runbook", + "destination": "/api-reference/summer-sdk/production-launch-runbook" + }, + { + "source": "/api-reference/crafty-sdk/submission-guide", + "destination": "/api-reference/summer-sdk/submission-guide" + }, + { + "source": "/api-reference/crafty-sdk/testing-your-game-locally", + "destination": "/api-reference/summer-sdk/testing-your-game-locally" + }, + { + "source": "/api-reference/crafty-sdk/exporting-and-uploading-your-game", + "destination": "/api-reference/summer-sdk/exporting-and-uploading-your-game" + }, + { + "source": "/api-reference/crafty-sdk/banned-apis-reference", + "destination": "/api-reference/summer-sdk/banned-apis-reference" + }, + { + "source": "/api-reference/crafty-sdk/ai-agent-playbook", + "destination": "/api-reference/summer-sdk/ai-agent-playbook" + }, + { + "source": "/api-reference/crafty-sdk/guides/multiplayer-ffa-coin-collector", + "destination": "/api-reference/summer-sdk/guides/multiplayer-ffa-coin-collector" + }, + { + "source": "/api-reference/crafty-sdk/guides/multiplayer-persistence-rpg", + "destination": "/api-reference/summer-sdk/guides/multiplayer-persistence-rpg" + }, + { + "source": "/api-reference/crafty-sdk/guides/team-based-game", + "destination": "/api-reference/summer-sdk/guides/team-based-game" + }, + { + "source": "/api-reference/crafty-sdk/guides/making-a-2d-game-multiplayer", + "destination": "/api-reference/summer-sdk/guides/making-a-2d-game-multiplayer" + }, + { + "source": "/api-reference/crafty-sdk/guides/making-a-turn-based-or-card-game-multiplayer", + "destination": "/api-reference/summer-sdk/guides/making-a-turn-based-or-card-game-multiplayer" + } + ] +} diff --git a/scripts/policy-fixtures.json b/scripts/policy-fixtures.json new file mode 100644 index 0000000..ad5a42e --- /dev/null +++ b/scripts/policy-fixtures.json @@ -0,0 +1,429 @@ +{ + "schemaVersion": 1, + "languageReject": [ + { + "name": "fenced Godot onboarding identity", + "text": "```text\nInstall Godot 4.5 and build a Godot game with the Godot SDK.\n```", + "rules": ["default-godot-45", "godot-game", "godot-sdk"] + }, + { + "name": "stale fenced project feature", + "text": "```ini\nconfig/features=PackedStringArray(\"4.5\")\n```", + "rules": ["stale-project-feature"] + }, + { + "name": "upstream version used as product release", + "text": "Install Summer Engine 4.6.1 and start building.", + "rules": ["upstream-as-product-version"] + }, + { + "name": "unqualified broad platform export", + "text": "Export to Steam, itch.io, Mac, Windows, mobile, and consoles.", + "rules": ["unqualified-broad-platform-export"] + }, + { + "name": "complete no-code game promise", + "text": "No coding required: build complete games just by describing them.", + "rules": ["no-code-complete-game"] + }, + { + "name": "without-code complete game paraphrase", + "text": "Build a complete game without writing code.", + "rules": ["no-code-complete-game"] + }, + { + "name": "no-code-needed complete game paraphrase", + "text": "No code needed: make complete games from a prompt.", + "rules": ["no-code-complete-game"] + }, + { + "name": "publish platform order paraphrase", + "text": "Publish to mobile, consoles, Steam, and itch.io.", + "rules": ["unqualified-broad-platform-export"] + }, + { + "name": "export platform order paraphrase", + "text": "Export your game to consoles, mobile, Steam, and itch.io.", + "rules": ["unqualified-broad-platform-export"] + }, + { + "name": "fixed model integration promise", + "text": "We integrate every new AI image, 3D, and video breakthrough within 24 hours.", + "rules": ["fixed-24h-model-promise"] + }, + { + "name": "one-day model integration paraphrase", + "text": "We add every new image and 3D model in one day.", + "rules": ["fixed-24h-model-promise"] + } + ], + "languageAllow": [ + { + "name": "narrow upstream compatibility fact", + "text": "Summer Engine's current upstream technical base is Godot Engine 4.6.1." + }, + { + "name": "literal project filename and current feature", + "text": "```ini\n# project.godot\nconfig/features=PackedStringArray(\"4.6\")\n```" + }, + { + "name": "godot-cpp technical literal", + "text": "Build the extension with the godot-cpp bindings pinned to the compatible ABI." + } + ], + "compatibilityReject": [ + { + "name": "FAQ perfect compatibility mutation", + "text": "They work perfectly. All scenes, scripts, and plugins work as before.", + "rules": ["blanket-works-perfectly", "blanket-all-assets"] + }, + { + "name": "zero-conversion mutation", + "text": "Open any existing project. No conversion required.", + "rules": ["blanket-no-conversion"] + }, + { + "name": "GodotSteam universal tutorial mutation", + "text": "GodotSteam works identically in Summer Engine and all tutorials apply.", + "rules": ["blanket-works-perfectly", "blanket-all-assets"] + }, + { + "name": "caveat prefix cannot exempt absolute", + "text": "Plugins may vary, but GodotSteam works identically and all tutorials apply directly.", + "rules": ["blanket-works-perfectly", "blanket-all-assets"] + }, + { + "name": "unchanged addon mutation", + "text": "Most Godot 4 addons work in Summer unchanged.", + "rules": ["blanket-works-perfectly"] + }, + { + "name": "transitive native load mutation", + "text": "If it loads in Godot 4.6 it loads in Summer.", + "rules": ["blanket-transitive-load"] + }, + { + "name": "root as-is mutation", + "text": "Open your projects as-is.", + "rules": ["blanket-open-as-is"] + }, + { + "name": "open and continue mutation", + "text": "Open your project and continue working with AI assistance.", + "rules": ["blanket-open-and-continue"] + }, + { + "name": "open and keep building mutation", + "text": "Open an existing project and keep building with AI.", + "rules": ["blanket-open-and-continue"] + } + ], + "compatibilityAllow": [ + { + "name": "measured compatibility caveat", + "text": "Familiar formats reduce migration work, but compatibility ranges are unmeasured. Commit first and test plugins, imports, and exports." + }, + { + "name": "negated universal addon compatibility", + "text": "Not all Godot 4 addons work unchanged." + }, + { + "name": "negated identical compatibility", + "text": "GodotSteam does not work identically across every Summer release." + }, + { + "name": "negated complete plugin compatibility", + "text": "No plugin is completely compatible without testing." + } + ], + "capabilityReject": [ + { + "name": "fenced playback and matchmaking mutation", + "text": "```text\nPlayers can launch uploaded Summer games in the browser today, and managed matchmaking is live.\n```", + "capabilities": ["uploaded-game-playback", "managed-matchmaking"] + }, + { + "name": "uploaded game readiness paraphrase", + "text": "Uploaded Summer games are ready for players to launch in our browser.", + "capabilities": ["uploaded-game-playback"] + }, + { + "name": "operational matchmaking paraphrase", + "text": "Matchmaking is operational now.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "dedicated server run paraphrase", + "text": "We run dedicated game servers for every release.", + "capabilities": ["hosted-game-servers"] + }, + { + "name": "sandbox execution paraphrase", + "text": "Every submission executes inside an automated production runtime sandbox.", + "capabilities": ["production-sandbox"] + }, + { + "name": "transport powers production paraphrase", + "text": "SummerMultiplayerPeer powers production networking today.", + "capabilities": ["summer-multiplayer-transport"] + }, + { + "name": "approved pack runtime paraphrase", + "text": "Approved packs are executed by the Summercraft runtime.", + "capabilities": ["production-runtime"] + }, + { + "name": "durable persistence paraphrase", + "text": "Summer.data automatically writes every save to durable storage.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "negation reversal cannot suppress later sentence", + "text": "Playback is not planned anymore. Players can launch uploaded Summer games today.", + "capabilities": ["uploaded-game-playback"] + }, + { + "name": "runtime enforcement mutation", + "text": "The production runtime loads every approved pack and enforces the manifest automatically.", + "capabilities": ["production-runtime"] + }, + { + "name": "persistence flush mutation", + "text": "Summer.data autosaves player progress and the backend flush is handled for you.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "planned marker cannot suppress contradictory matchmaking clause", + "text": "Matchmaking remains Planned, yet it is operational now.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "web client playable creator build paraphrase", + "text": "Uploaded creator builds are playable in the web client now.", + "capabilities": ["uploaded-game-playback"] + }, + { + "name": "automatic lobby pairing paraphrase", + "text": "The platform automatically pairs players into lobbies today.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "cloud game provisioning paraphrase", + "text": "Cloud game instances are provisioned for every release.", + "capabilities": ["hosted-game-servers"] + }, + { + "name": "production uploaded-pack isolation paraphrase", + "text": "The platform isolates and runs every uploaded pack in production.", + "capabilities": ["production-sandbox"] + }, + { + "name": "live replication peer paraphrase", + "text": "Summer's multiplayer peer provides live replication.", + "capabilities": ["summer-multiplayer-transport"] + }, + { + "name": "approved packs run on Summercraft paraphrase", + "text": "Approved packs run on Summercraft today.", + "capabilities": ["production-runtime"] + }, + { + "name": "verb-first approved-pack runtime paraphrase", + "text": "We execute approved packs on Summercraft today.", + "capabilities": ["production-runtime"] + }, + { + "name": "cross-sentence matchmaking anaphor", + "text": "Matchmaking remains Planned. It is operational now.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "cross-sentence runtime anaphor", + "text": "Approved packs remain Planned. They run on Summercraft today.", + "capabilities": ["production-runtime"] + }, + { + "name": "cross-sentence persistence anaphor", + "text": "Summer storage is Scaffolded. It keeps player saves durably between sessions.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "local test qualifier cannot hide later production assertion", + "text": "The local test harness pairs players into lobbies. It is operational in production now.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "modal private test cannot hide later production assertion", + "text": "Matchmaking may be operational in a private test. It is operational in production now.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "same-sentence anaphoric production assertion", + "text": "Summer storage is Scaffolded; however, it stores saves durably in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "elliptical matchmaking production predicate", + "text": "Matchmaking may be operational in a private test, but is operational in production.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "elliptical pack production predicate", + "text": "Approved packs remain Planned, but execute in production.", + "capabilities": ["production-runtime"] + }, + { + "name": "elliptical storage production predicate", + "text": "Summer storage is Scaffolded, but stores player saves durably in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "elliptical matchmaking live variant", + "text": "Matchmaking remains Planned; however, is live in production.", + "capabilities": ["managed-matchmaking"] + }, + { + "name": "elliptical pack run variant", + "text": "Approved packs remain Planned, yet run in production.", + "capabilities": ["production-runtime"] + }, + { + "name": "elliptical storage write variant", + "text": "Summer storage is Scaffolded, but writes player save data in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "elliptical persistence object coreference", + "text": "Summer storage may keep saves in a test harness but stores them durably in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "elliptical persistence object coreference variant", + "text": "Summer storage may write player saves in a private test; however, persists them between production sessions.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "elliptical persistence adjective object coreference", + "text": "Summer storage may keep encrypted player saves in a test harness, but stores them durably in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "ordinary production economy assertion", + "text": "Summer storage writes player economy in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "ordinary prepositional durable-storage assertion", + "text": "Summer storage writes to durable storage in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "ordinary prepositional durable-storage variant", + "text": "Summer storage persists to durable storage in production.", + "capabilities": ["hosted-persistence-economy"] + }, + { + "name": "durable inter-session Summer storage paraphrase", + "text": "Summer storage keeps player saves durably between sessions.", + "capabilities": ["hosted-persistence-economy"] + } + ], + "capabilityAllow": [ + { + "name": "planned playback disclosure", + "text": "Browser playback for uploaded games is Planned and is not production-live." + }, + { + "name": "scaffolded runtime disclosure", + "text": "This is a scaffolded runtime contract example; no production runtime currently loads uploaded games." + }, + { + "name": "live submission claim", + "text": "The browser submission page and static scanner are Live." + }, + { + "name": "explicit scaffolded persistence", + "text": "Summer.data is a scaffolded interface and does not write to durable storage." + }, + { + "name": "explicit planned matchmaking", + "text": "Matchmaking status is Planned; no production service is available." + }, + { + "name": "truthful persistence negation", + "text": "Summer storage never writes player saves to durable storage." + }, + { + "name": "truthful runtime negation", + "text": "The Summercraft runtime never executes approved packs." + }, + { + "name": "truthful transport negation", + "text": "Summer's multiplayer peer cannot power production networking." + }, + { + "name": "explicit unrelated semicolon subject", + "text": "Matchmaking remains Planned; this documentation page is live." + }, + { + "name": "local test harness scope", + "text": "The local test harness pairs players into lobbies; production matchmaking remains Planned." + }, + { + "name": "modal private test scope", + "text": "Matchmaking may be operational in a private test." + }, + { + "name": "unrelated cross-sentence demonstrative subject", + "text": "Approved packs remain Planned. This documentation page is live." + }, + { + "name": "local runtime harness scope", + "text": "Approved packs run locally in a private test harness; the production runtime remains Planned." + }, + { + "name": "hypothetical private matchmaking scope", + "text": "If matchmaking becomes operational in a private test, do not describe it as production." + }, + { + "name": "anaphoric live documentation predicate", + "text": "Matchmaking remains Planned. It is documented on a live status page." + }, + { + "name": "anaphoric unrelated storage object", + "text": "Summer storage is Scaffolded. It keeps the API reference concise." + }, + { + "name": "anaphoric live documentation variant", + "text": "Approved packs remain Planned. They are mentioned on a live documentation page." + }, + { + "name": "anaphoric unrelated storage URL", + "text": "Summer storage is Scaffolded. It stores the API reference URL." + }, + { + "name": "elliptical docs-example pronoun", + "text": "Summer storage documents API examples, but keeps them concise." + }, + { + "name": "elliptical reference-example pronoun", + "text": "Summer storage may keep examples in a test harness but stores them in the API reference." + }, + { + "name": "save modifier does not make examples a persistence object", + "text": "Summer storage may keep player save API examples in a test harness, but stores them in the API reference." + }, + { + "name": "save topic does not make examples a persistence object", + "text": "Summer storage may keep API examples about player saves in a test harness, but stores them in the API reference." + }, + { + "name": "save of-topic does not make examples a persistence antecedent", + "text": "Summer storage may keep API examples of player saves in a test harness, but stores them on the production documentation site." + }, + { + "name": "save showing-topic does not make examples a persistence antecedent", + "text": "Summer storage may keep API examples showing player saves in a test harness, but stores them on the production documentation site." + } + ] +} diff --git a/scripts/sync-engine-compatibility.mjs b/scripts/sync-engine-compatibility.mjs new file mode 100644 index 0000000..70e7bb2 --- /dev/null +++ b/scripts/sync-engine-compatibility.mjs @@ -0,0 +1,190 @@ +#!/usr/bin/env node + +import { createHash } from "node:crypto"; +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); +const SOURCE_PATH = join(ROOT, "compatibility/source.json"); +const MANIFEST_PATH = join(ROOT, "compatibility/summer-engine.json"); +const OUTPUT_PATH = join(ROOT, "reference/compatibility.mdx"); +const CHECK = process.argv[2] === "--check"; + +if (process.argv.length > (CHECK ? 3 : 2)) { + console.error("usage: node scripts/sync-engine-compatibility.mjs [--check]"); + process.exit(2); +} + +const sourceRaw = readFileSync(SOURCE_PATH, "utf8"); +const manifestRaw = readFileSync(MANIFEST_PATH, "utf8"); +const source = JSON.parse(sourceRaw); +const manifest = JSON.parse(manifestRaw); +const generatedReferencePath = join(ROOT, source.generatedReferenceSnapshot); +const generatedReferenceRaw = readFileSync(generatedReferencePath, "utf8"); + +const digest = (algorithm, value) => createHash(algorithm).update(value).digest("hex"); +const manifestSha256 = digest("sha256", manifestRaw); +const manifestGitBlobSha = digest("sha1", `blob ${Buffer.byteLength(manifestRaw)}\0${manifestRaw}`); +const generatedReferenceSha256 = digest("sha256", generatedReferenceRaw); +const generatedReferenceGitBlobSha = digest( + "sha1", + `blob ${Buffer.byteLength(generatedReferenceRaw)}\0${generatedReferenceRaw}`, +); + +const fail = (message) => { + console.error(`compatibility sync: ERROR: ${message}`); + process.exit(1); +}; + +if (source.schemaVersion !== 1) fail(`unsupported source schema ${JSON.stringify(source.schemaVersion)}`); +if (!/^[0-9a-f]{40}$/.test(source.commit)) fail("source commit must be a full 40-character Git SHA"); +if (source.manifestSha256 !== manifestSha256) { + fail(`manifest SHA-256 drifted: expected ${source.manifestSha256}, got ${manifestSha256}`); +} +if (source.manifestGitBlobSha !== manifestGitBlobSha) { + fail(`manifest Git blob drifted: expected ${source.manifestGitBlobSha}, got ${manifestGitBlobSha}`); +} +if (source.generatedReferenceSha256 !== generatedReferenceSha256) { + fail( + `generated reference SHA-256 drifted: expected ${source.generatedReferenceSha256}, ` + + `got ${generatedReferenceSha256}`, + ); +} +if (source.generatedReferenceGitBlobSha !== generatedReferenceGitBlobSha) { + fail( + `generated reference Git blob drifted: expected ${source.generatedReferenceGitBlobSha}, ` + + `got ${generatedReferenceGitBlobSha}`, + ); +} +if (manifest.schemaVersion !== 1) fail(`unsupported engine contract schema ${JSON.stringify(manifest.schemaVersion)}`); + +const product = manifest.product; +const releaseIdentity = product?.releaseIdentity; +const upstream = manifest.upstreamBase; +const planned = upstream?.plannedNext; +const runtime = manifest.runtimeCompatibility; +const project = manifest.projectCompatibility; +const verification = manifest.verification; +const language = manifest.languagePolicy; + +if (product?.name !== "Summer Engine") fail("product.name must be Summer Engine"); +if (releaseIdentity?.state !== "measured" || releaseIdentity?.strategy !== "platform-staggered") { + fail("product release identity must be measured and platform-staggered"); +} +if (!releaseIdentity.platforms || !Object.keys(releaseIdentity.platforms).length) { + fail("product release identity must contain at least one platform"); +} +if (!upstream?.current?.version || !planned?.state || !upstream.policy) fail("upstream compatibility fields are incomplete"); +if (language?.creatorProduct !== "Summer Engine" || language?.creatorGame !== "Summer game") { + fail("language policy does not match the frozen product identity"); +} +if (language?.defaultCreatorLanguage !== "GDScript") fail("default creator language must be GDScript"); + +const measurement = (value) => { + if (value?.state === "unmeasured") return "Unmeasured; no version is claimed."; + if (value?.state === "measured" && value.version) return `Measured at \`${value.version}\`.`; + fail(`invalid compatibility measurement ${JSON.stringify(value)}`); +}; + +const engineReleaseRows = new Map(); +for (const match of generatedReferenceRaw.matchAll( + /^\| ([^|]+?) \| `([^`]+)` \| `([^`]+)` → `([^`]+)` \|$/gm, +)) { + const [, displayName, version, releaseSource, define] = match; + engineReleaseRows.set(define, { displayName, version, releaseSource, define }); +} + +const platformRows = Object.values(releaseIdentity.platforms) + .sort((left, right) => left.displayName.localeCompare(right.displayName, "en")) + .map((platform) => { + const release = engineReleaseRows.get(platform.define); + if (!release) fail(`engine-generated reference has no product release for ${platform.define}`); + if (release.displayName !== platform.displayName || release.releaseSource !== releaseIdentity.source) { + fail(`engine manifest and generated reference disagree for ${platform.define}`); + } + return ( + `| ${release.displayName} | \`${release.version}\` | ` + + `\`${release.releaseSource}\` → \`${release.define}\` |` + ); + }); + +const plannedValue = + planned.state === "planned" ? `\`${planned.version}\`` : "Unmeasured; no next version is claimed."; + +const rendered = `--- +title: "Compatibility & upstream" +description: "Generated Summer Engine product-release and upstream compatibility facts from the pinned engine contract." +icon: "git-compare-arrows" +generated: true +generator: compatibility/source.json +--- + +{/* Generated by scripts/sync-engine-compatibility.mjs. Do not edit by hand. */} + +This reference is generated from the Summer Engine compatibility contract at +\`${source.repository}:${source.manifestPath}\`, commit \`${source.commit}\`. The checked-in input is verified against SHA-256 +\`${source.manifestSha256}\`; docs builds do not fetch mutable remote data. + +## Product identity + +**${product.name}** is the product. Creators make a **${language.creatorGame}** in +**${language.defaultCreatorLanguage}** and use the **Summer SDK** for platform capabilities. +The product release is platform-staggered and separate from the upstream technical base. + +| Platform | Summer Engine release | Authoritative engine source | +|---|---:|---| +${platformRows.join("\n")} + +## Upstream technical base + +| Field | Value | +|---|---| +| Current upstream base | \`${upstream.current.version}\` | +| Planned next upstream base | ${plannedValue} | +| Policy | \`${upstream.policy}\` | +| Build evidence | \`${upstream.current.source}\` | +| Verified | \`${verification.verifiedOn}\` | + +The upstream base is a compatibility and lineage fact, not the Summer Engine product version. +Summer follows upstream continuously; neither the current nor planned upstream number is a +permanent Summer identity. + +## Runtime and project compatibility + +- Runtime compatibility: ${measurement(runtime)} +- Minimum project compatibility: ${measurement(project.minimum)} +- Recommended project compatibility: ${measurement(project.recommended)} + +Unmeasured values are intentionally \`null\` in the source contract. Do not infer a minimum +from \`project.godot\`, copied prose, or an older setup guide. + +## Where upstream terminology belongs + +Godot references remain in migration, plugin and GDExtension compatibility, upstream +contribution, attribution, and legal contexts. Default creator onboarding installs and uses +Summer Engine. + + + + Review creator-facing names and stable wire identifiers. + + + Bring an existing Godot project into Summer Engine. + + +`; + +if (CHECK) { + let actual; + try { + actual = readFileSync(OUTPUT_PATH, "utf8"); + } catch { + fail("generated reference is missing; run `npm run generate:compatibility`"); + } + if (actual !== rendered) fail("generated reference is stale; run `npm run generate:compatibility`"); + console.log(`compatibility sync: PASS ${source.commit} ${manifestSha256}`); +} else { + writeFileSync(OUTPUT_PATH, rendered, "utf8"); + console.log(`generated ${OUTPUT_PATH.replace(`${ROOT}/`, "")}`); +}