@inneranimalmedia/agentsam-sdk 2.6.5 → 2.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTSAM.md +29 -0
- package/apps/README.md +5 -0
- package/apps/cad-creator/README.md +4 -4
- package/apps/cad-creator/shared/cad/package.json +1 -1
- package/apps/client-cms-editor/AGENTS.md +12 -7
- package/apps/client-cms-editor/README.md +76 -48
- package/apps/client-cms-editor/agentsam.app.json +26 -9
- package/apps/client-cms-editor/backend/package.json +20 -3
- package/apps/client-cms-editor/backend/src/api/client.ts +134 -101
- package/apps/client-cms-editor/backend/src/index.ts +1 -1
- package/apps/client-cms-editor/backend/src/model.ts +11 -115
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +1 -1
- package/apps/client-cms-editor/backend/tsconfig.json +6 -1
- package/apps/client-cms-editor/bin/agentsam-cms.js +262 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +2 -228
- package/apps/client-cms-editor/frontend/package.json +16 -7
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +9 -41
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +19 -174
- package/apps/client-cms-editor/frontend/src/adapters/heuristic.ts +29 -0
- package/apps/client-cms-editor/frontend/src/adapters/http.ts +628 -0
- package/apps/client-cms-editor/frontend/src/adapters/memory.ts +510 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditor.tsx +213 -0
- package/apps/client-cms-editor/frontend/src/editor/CmsEditorProvider.tsx +20 -0
- package/apps/client-cms-editor/frontend/src/editor/canvas/PreviewCanvas.tsx +53 -0
- package/apps/client-cms-editor/frontend/src/{CmsEditor.tsx → editor/legacy/CmsEditorPrototype.tsx} +52 -23
- package/apps/client-cms-editor/frontend/src/editor/useCmsEditorController.ts +218 -0
- package/apps/client-cms-editor/frontend/src/index.ts +19 -5
- package/apps/client-cms-editor/frontend/src/lib/agent-host.ts +24 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +82 -8
- package/apps/client-cms-editor/frontend/src/mount.tsx +92 -30
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +1 -1
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +8 -8
- package/apps/client-cms-editor/frontend/src/styles/studio.css +55 -3
- package/apps/client-cms-editor/frontend/tsconfig.json +12 -1
- package/apps/client-cms-editor/frontend/vite.config.ts +12 -0
- package/apps/client-cms-editor/package-lock.json +973 -134
- package/apps/client-cms-editor/package.json +118 -6
- package/apps/client-cms-editor/reference/harvest/HARVEST_RECEIPT.json +201 -0
- package/apps/client-cms-editor/reference/harvest/PROVENANCE_HISTORY.txt +10 -0
- package/apps/client-cms-editor/reference/harvest/README.md +8 -0
- package/apps/client-cms-editor/reference/harvest/plans/ARCHIVE-INTAKE.md +135 -0
- package/apps/client-cms-editor/reference/harvest/plans/CHATGPT-IDENTITY-HARVEST.md +83 -0
- package/apps/client-cms-editor/reference/harvest/plans/CMS-EDITOR-HARVEST.md +166 -0
- package/apps/client-cms-editor/reference/harvest/plans/HARVEST-INDEX.md +196 -0
- package/apps/client-cms-editor/reference/harvest/plans/INNERANIMALS-CONTENT-001.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/NO-IMPLICIT-SIDE-EFFECTS.md +87 -0
- package/apps/client-cms-editor/reference/harvest/plans/STOREFRONT-SURFACE-MAP.md +140 -0
- package/apps/client-cms-editor/reference/harvest/plans/THEME-INNERANIMALS-HARVEST.md +137 -0
- package/apps/client-cms-editor/reference/harvest/plans/TOOLING-LAB.md +63 -0
- package/apps/client-cms-editor/reference/harvest/plans/harvest-manifest.json +97 -0
- package/apps/client-cms-editor/reference/harvest/plans/local-cms-harvest-schema.sql +328 -0
- package/apps/client-cms-editor/shared/cms/package.json +17 -7
- package/apps/client-cms-editor/shared/cms/src/adapter.ts +204 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +7 -5
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +32 -0
- package/apps/client-cms-editor/shared/cms/src/host.ts +82 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +4 -0
- package/apps/client-cms-editor/shared/cms/src/map.ts +115 -0
- package/apps/client-cms-editor/shared/cms/src/starter-pack.ts +158 -0
- package/contracts/source-types.v1.json +353 -0
- package/docs/CMS_CONTEXTUAL_COMPOSER.md +1 -1
- package/docs/PRODUCT_LIFECYCLE.md +566 -0
- package/docs/THEME_REFINERY.md +2 -2
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +40 -20
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +1 -1
- package/docs/plans/LOCAL_STUDIO_DESKTOP_RELEASE_2026-09-29.md +150 -0
- package/migrations/d1/0017_identity_native_oauth.sql +21 -0
- package/native/agentsam-machine/Cargo.lock +426 -0
- package/native/agentsam-machine/Cargo.toml +9 -0
- package/native/agentsam-machine/cli/Cargo.toml +14 -0
- package/native/agentsam-machine/cli/src/main.rs +77 -0
- package/native/agentsam-machine/core/Cargo.toml +15 -0
- package/native/agentsam-machine/core/src/assets.rs +790 -0
- package/native/agentsam-machine/core/src/bound.rs +298 -0
- package/native/agentsam-machine/core/src/enrich.rs +706 -0
- package/native/agentsam-machine/core/src/frontend.rs +442 -0
- package/native/agentsam-machine/core/src/lib.rs +1086 -0
- package/native/agentsam-machine/core/src/liquid.rs +528 -0
- package/native/agentsam-machine/core/src/source_types.rs +78 -0
- package/package.json +51 -21
- package/packages/agentsam-brand/README.md +1 -1
- package/packages/agentsam-brand/package.json +4 -4
- package/packages/agentsam-brand/src/index.js +1 -1
- package/packages/agentsam-contracts/package.json +13 -3
- package/packages/agentsam-contracts/src/tools.ts +22 -0
- package/packages/agentsam-errors/package.json +13 -3
- package/packages/agentsam-knowledge/package.json +18 -4
- package/packages/agentsam-knowledge/src/autorag/index.js +10 -3
- package/packages/agentsam-knowledge/src/backends/index.js +33 -1
- package/packages/agentsam-knowledge/test/autorag.test.mjs +60 -1
- package/packages/agentsam-nav/package.json +24 -6
- package/packages/agentsam-queue-control/README.md +1 -1
- package/packages/agentsam-queue-control/package.json +7 -2
- package/packages/agentsam-rapid-rust/src/main.rs +1 -1
- package/packages/agentsam-repository/package.json +13 -3
- package/packages/agentsam-repository/src/source-types.js +8 -0
- package/packages/agentsam-vault/package.json +14 -4
- package/packages/agentsam-workbench/package.json +15 -4
- package/packages/agentsam-workbench/src/agent/ToolPermissionRequest.tsx +94 -0
- package/packages/agentsam-workbench/src/agent/index.ts +2 -0
- package/packages/agentsam-workbench/src/agent/tool-permission.css +134 -0
- package/packages/connectors/cloudflare/package.json +13 -3
- package/packages/connectors/cloudflare/src/api-client.js +3 -2
- package/packages/connectors/cloudflare/src/families/vectorize.js +127 -0
- package/packages/connectors/cloudflare/src/index.js +1 -0
- package/packages/heuristic-theme/README.md +2 -2
- package/packages/heuristic-theme/package.json +8 -3
- package/packages/heuristic-theme/src/registry.js +2 -2
- package/packages/heuristic-theme/src/theme.js +1 -1
- package/packages/heuristic-theme/test/theme.test.mjs +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +27 -7
- package/packages/identity/README.md +2 -2
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +18 -15
- package/packages/identity/migrations/apply-portable.js +109 -0
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +1 -1
- package/packages/identity/migrations/sqlite/005_identity_company_native.sql +52 -0
- package/packages/identity/package.json +27 -6
- package/packages/identity/schema/agentsam.identity/manifest.json +101 -0
- package/packages/identity/scripts/local-identity-bridge.mjs +13 -7
- package/packages/identity/scripts/preview-auth-portal.mjs +6 -6
- package/packages/identity/src/adapters/cloudflare-d1/index.js +8 -401
- package/packages/identity/src/adapters/iam-compat/index.js +540 -0
- package/packages/identity/src/adapters/portable-d1/index.js +18 -0
- package/packages/identity/src/adapters/portable-store.js +479 -0
- package/packages/identity/src/adapters/sqlite/index.js +13 -312
- package/packages/identity/src/contracts/auth-config.js +0 -1
- package/packages/identity/src/contracts/identity-store.js +56 -5
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/contracts/sign-in-options.js +104 -0
- package/packages/identity/src/core/constants.js +1 -1
- package/packages/identity/src/core/session-policy.js +31 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -6
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +5 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +5 -5
- package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
- package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +6 -37
- package/packages/identity/src/index.js +28 -1
- package/packages/identity/src/migrations/README.md +23 -23
- package/packages/identity/src/oauth/README.md +1 -1
- package/packages/identity/src/oauth/credentials.js +10 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +195 -27
- package/packages/identity/src/oauth/iam-platform.js +21 -9
- package/packages/identity/src/oauth/native-handoff.js +136 -0
- package/packages/identity/src/providers/chatgpt/headers.js +65 -0
- package/packages/identity/src/providers/chatgpt/index.js +86 -0
- package/packages/identity/src/providers/chatgpt/mapper.js +43 -0
- package/packages/identity/src/providers/chatgpt/paths.js +45 -0
- package/packages/identity/src/providers/github/oauth.js +1 -2
- package/packages/identity/src/providers/github/profile.js +16 -2
- package/packages/identity/src/providers/index.js +11 -3
- package/packages/identity/src/server/identity-service.js +2 -1
- package/packages/identity/src/server/worker-router.js +71 -18
- package/packages/identity/tests/chatgpt-provider.test.mjs +75 -0
- package/packages/identity/tests/google-desktop-identity-login.test.mjs +210 -0
- package/packages/identity/tests/identity-init-scaffold.test.mjs +15 -4
- package/packages/identity/tests/lane1-identity-store-parity.test.mjs +527 -0
- package/packages/identity/tests/lane1-packed-consumer.test.mjs +175 -0
- package/packages/identity/tests/native-oauth-handoff.test.mjs +292 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +4 -4
- package/packages/identity/tests/preview-auth-portal.test.mjs +4 -2
- package/packages/identity/tests/session-routes-policy.test.mjs +13 -1
- package/packages/identity/tests/worker-runtime-boundary.test.mjs +11 -0
- package/packages/providers/completeful/package.json +7 -2
- package/packages/theme-church-site/package.json +17 -6
- package/packages/theme-church-site/src/harvest.json +4 -2
- package/packages/theme-church-site/src/index.js +7 -3
- package/packages/theme-church-site/test/theme.test.mjs +4 -2
- package/packages/theme-companions-site/package.json +17 -6
- package/packages/theme-companions-site/src/harvest.json +4 -2
- package/packages/theme-companions-site/src/index.js +7 -3
- package/packages/theme-companions-site/test/theme.test.mjs +4 -2
- package/packages/theme-floors-site/package.json +17 -6
- package/packages/theme-floors-site/src/harvest.json +4 -2
- package/packages/theme-floors-site/src/index.js +7 -3
- package/packages/theme-floors-site/test/theme.test.mjs +4 -2
- package/packages/theme-fuelnfree-site/package.json +17 -6
- package/packages/theme-fuelnfree-site/src/harvest.json +4 -2
- package/packages/theme-fuelnfree-site/src/index.js +7 -3
- package/packages/theme-fuelnfree-site/test/theme.test.mjs +4 -2
- package/packages/theme-handyman-site/package.json +17 -6
- package/packages/theme-handyman-site/src/harvest.json +4 -2
- package/packages/theme-handyman-site/src/index.js +7 -3
- package/packages/theme-handyman-site/test/theme.test.mjs +4 -2
- package/packages/theme-insurance-site/package.json +17 -6
- package/packages/theme-insurance-site/src/harvest.json +4 -2
- package/packages/theme-insurance-site/src/index.js +7 -3
- package/packages/theme-insurance-site/test/theme.test.mjs +4 -2
- package/packages/theme-scenes/README.md +1 -1
- package/packages/theme-scenes/package.json +4 -3
- package/packages/theme-scenes/src/registry.js +187 -0
- package/packages/theme-shinshu-site/package.json +17 -6
- package/packages/theme-shinshu-site/src/harvest.json +4 -2
- package/packages/theme-shinshu-site/src/index.js +7 -3
- package/packages/theme-shinshu-site/test/theme.test.mjs +4 -2
- package/packages/work-graph/package.json +14 -4
- package/protocol/FILEMETA_V1.md +2 -2
- package/protocol/capabilities/manifest.json +1 -1
- package/protocol/database/agentsam.schema-pack.v1.schema.json +72 -0
- package/protocol/presets/catalog.json +2 -2
- package/protocol/theme-refinery/lineage-registry.json +105 -0
- package/protocol/theme-refinery/product-metadata.schema.json +21 -1
- package/skills/grok-auth/SKILL.md +110 -0
- package/skills/grok-auth/agentsam.skill.json +25 -0
- package/skills/grok-auth/references/grok-identity.md +64 -0
- package/skills/grok-auth/references/per-user-data.md +49 -0
- package/skills/grok-auth/references/prewired-and-env.md +54 -0
- package/skills/grok-auth/references/session-ui.md +133 -0
- package/skills/grok-auth/references/sign-in-methods.md +55 -0
- package/skills/grok-auth/references/wiring.md +71 -0
- package/skills/grok-building-games/SKILL.md +213 -0
- package/skills/grok-building-games/agentsam.skill.json +25 -0
- package/skills/grok-building-games/references/3d-libs.md +64 -0
- package/skills/grok-building-games/references/ai-pathfinding.md +122 -0
- package/skills/grok-building-games/references/audio.md +129 -0
- package/skills/grok-building-games/references/babylon.md +202 -0
- package/skills/grok-building-games/references/collision-physics.md +122 -0
- package/skills/grok-building-games/references/ecs-architecture.md +111 -0
- package/skills/grok-building-games/references/game-feel-juice.md +110 -0
- package/skills/grok-building-games/references/genres/board-card-chess.md +89 -0
- package/skills/grok-building-games/references/genres/endless-runner.md +83 -0
- package/skills/grok-building-games/references/genres/fps.md +105 -0
- package/skills/grok-building-games/references/genres/platformer-2d.md +97 -0
- package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +131 -0
- package/skills/grok-building-games/references/genres/racing-kart.md +106 -0
- package/skills/grok-building-games/references/genres/topdown-twin-stick.md +97 -0
- package/skills/grok-building-games/references/genres/tower-defense.md +84 -0
- package/skills/grok-building-games/references/genres/voxel-minecraft.md +89 -0
- package/skills/grok-building-games/references/input.md +139 -0
- package/skills/grok-building-games/references/phaser.md +277 -0
- package/skills/grok-building-games/references/procedural-generation.md +141 -0
- package/skills/grok-building-games/references/save-persistence.md +108 -0
- package/skills/grok-building-games/references/threejs-foundational.md +148 -0
- package/skills/grok-controls/SKILL.md +274 -0
- package/skills/grok-controls/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/SKILL.md +122 -0
- package/skills/grok-design-ui/agentsam.skill.json +25 -0
- package/skills/grok-design-ui/references/animations.md +379 -0
- package/skills/grok-design-ui/references/performance.md +88 -0
- package/skills/grok-design-ui/references/refined-ui.md +384 -0
- package/skills/grok-design-ui/references/surfaces.md +247 -0
- package/skills/grok-design-ui/references/typography.md +123 -0
- package/skills/grok-game-animation-frames/SKILL.md +84 -0
- package/skills/grok-game-animation-frames/agentsam.skill.json +25 -0
- package/skills/grok-game-asset-core/SKILL.md +69 -0
- package/skills/grok-game-asset-core/agentsam.skill.json +25 -0
- package/skills/grok-game-character-consistency/SKILL.md +69 -0
- package/skills/grok-game-character-consistency/agentsam.skill.json +25 -0
- package/skills/grok-game-tilesets/SKILL.md +65 -0
- package/skills/grok-game-tilesets/agentsam.skill.json +25 -0
- package/skills/grok-game-ui-icons/SKILL.md +56 -0
- package/skills/grok-game-ui-icons/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/LICENSE +21 -0
- package/skills/grok-generate2dmap/SKILL.md +120 -0
- package/skills/grok-generate2dmap/SOURCE.md +6 -0
- package/skills/grok-generate2dmap/agentsam.skill.json +25 -0
- package/skills/grok-generate2dmap/references/deliverables.md +101 -0
- package/skills/grok-generate2dmap/references/layered-map-contract.md +209 -0
- package/skills/grok-generate2dmap/references/map-strategies.md +341 -0
- package/skills/grok-generate2dmap/references/object-production-gate.md +24 -0
- package/skills/grok-generate2dmap/references/pipeline.md +149 -0
- package/skills/grok-generate2dmap/references/prop-pack-contract.md +174 -0
- package/skills/grok-generate2dmap/references/side-scroll-stages.md +29 -0
- package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +157 -0
- package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +369 -0
- package/skills/grok-generate2dsprite/LICENSE +21 -0
- package/skills/grok-generate2dsprite/SKILL.md +313 -0
- package/skills/grok-generate2dsprite/SOURCE.md +6 -0
- package/skills/grok-generate2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-generate2dsprite/references/modes.md +124 -0
- package/skills/grok-generate2dsprite/references/prompt-rules.md +315 -0
- package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +1031 -0
- package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +109 -0
- package/skills/grok-imagine/SKILL.md +201 -0
- package/skills/grok-imagine/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/SKILL.md +111 -0
- package/skills/grok-multiplayer-p2p/agentsam.skill.json +25 -0
- package/skills/grok-multiplayer-p2p/references/react-binding.md +144 -0
- package/skills/grok-multiplayer-p2p/references/signaling-relay.md +269 -0
- package/skills/grok-neon/SKILL.md +157 -0
- package/skills/grok-neon/agentsam.skill.json +25 -0
- package/skills/grok-og/SKILL.md +102 -0
- package/skills/grok-og/agentsam.skill.json +25 -0
- package/skills/grok-og/references/brand-pass.md +53 -0
- package/skills/grok-og/references/custom-card.md +107 -0
- package/skills/grok-og/references/favicon-and-icons.md +48 -0
- package/skills/grok-og/references/og-type-contract.md +18 -0
- package/skills/grok-og/references/placeholder-card.md +21 -0
- package/skills/grok-og/references/x-banner.md +41 -0
- package/skills/grok-threejs/SKILL.md +67 -0
- package/skills/grok-threejs/agentsam.skill.json +25 -0
- package/skills/grok-threejs/references/llms-full.txt +2780 -0
- package/skills/grok-video2dsprite/LICENSE +21 -0
- package/skills/grok-video2dsprite/SKILL.md +236 -0
- package/skills/grok-video2dsprite/SOURCE.md +6 -0
- package/skills/grok-video2dsprite/agentsam.skill.json +25 -0
- package/skills/grok-video2dsprite/references/pipeline.md +90 -0
- package/skills/grok-video2dsprite/references/prompt-rules.md +63 -0
- package/skills/grok-video2dsprite/scripts/video2dsprite.py +490 -0
- package/skills/grok-xai-api/SKILL.md +152 -0
- package/skills/grok-xai-api/agentsam.skill.json +25 -0
- package/src/cli/command-catalog.js +46 -4
- package/src/cli/dispatch.js +1 -0
- package/src/cli.js +10 -0
- package/src/cloudflare/runtime-status.js +2 -1
- package/src/commands/autorag.js +67 -13
- package/src/commands/cheat-sheet.js +29 -4
- package/src/commands/codebaseindex.js +45 -2
- package/src/commands/knowledge.js +59 -2
- package/src/commands/machine-binary.js +103 -0
- package/src/commands/machine.js +137 -0
- package/src/commands/security.js +67 -4
- package/src/commands/setup.js +33 -16
- package/src/commands/status.js +8 -1
- package/src/features/resolve.js +1 -0
- package/src/knowledge/engine.js +21 -2
- package/src/knowledge/runtime-discovery.js +127 -0
- package/src/lib/identity-scaffold.js +53 -13
- package/src/lib/setup/recipes.js +1 -1
- package/src/models/discovery.js +40 -22
- package/src/models/inventory-core.d.ts +105 -0
- package/src/models/inventory-core.js +54 -6
- package/src/security/logs.js +3 -0
- package/src/ui/cli/help.js +41 -0
- package/test/apps-scaffold-contract.test.mjs +3 -2
- package/test/cli/api-key-env-whoami.test.mjs +2 -2
- package/test/cli/catalog-authority.test.mjs +64 -0
- package/test/cli/machine-command.test.mjs +34 -0
- package/test/fixtures/project-authority/customer-app/.agentsam/app.json +5 -0
- package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +1 -0
- package/test/fixtures/project-authority/customer-app/wrangler.toml +17 -0
- package/test/integration/autorag-project-authority.integration.test.mjs +51 -0
- package/test/integration/autorag-runtime-discovery.test.mjs +107 -0
- package/test/integration/cms-app-scaffold.test.mjs +37 -31
- package/test/integration/cms-site-tenancy-contract.test.mjs +28 -17
- package/test/integration/codebaseindex-ingest.test.mjs +41 -0
- package/test/integration/database-hosted-honesty.test.mjs +49 -0
- package/test/integration/desktop-keychain-boundary.test.mjs +45 -0
- package/test/integration/hosted-work-host-authority.test.mjs +47 -0
- package/test/integration/inventory-eligibility.test.mjs +59 -0
- package/test/integration/local-provider-bridge.test.mjs +65 -0
- package/test/integration/local-studio-settings-production.test.mjs +40 -0
- package/test/integration/lockfile-sync.test.mjs +26 -0
- package/test/integration/provider-env-cli.test.mjs +13 -3
- package/test/integration/runtime-status.integration.test.mjs +16 -1
- package/test/integration/theme-package-registry.test.mjs +31 -0
- package/test/repository-snapshot-view.test.mjs +2 -2
- package/test/security.test.mjs +14 -0
- package/test/terminal-machine-identity.test.mjs +2 -2
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +0 -145
- package/packages/agentsam-nav/dist/Nav.d.ts +0 -43
- package/packages/agentsam-nav/dist/NavCollapsible.d.ts +0 -10
- package/packages/agentsam-nav/dist/NavContent.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavFooter.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavGroup.d.ts +0 -3
- package/packages/agentsam-nav/dist/NavHeader.d.ts +0 -2
- package/packages/agentsam-nav/dist/NavMenu.d.ts +0 -22
- package/packages/agentsam-nav/dist/NavProvider.d.ts +0 -35
- package/packages/agentsam-nav/dist/NavTrigger.d.ts +0 -2
- package/packages/agentsam-nav/dist/Surfaces.d.ts +0 -41
- package/packages/agentsam-nav/dist/browser.d.ts +0 -11
- package/packages/agentsam-nav/dist/browser.global.js +0 -132
- package/packages/agentsam-nav/dist/browser.js +0 -613
- package/packages/agentsam-nav/dist/contracts.d.ts +0 -76
- package/packages/agentsam-nav/dist/index.d.ts +0 -11
- package/packages/agentsam-nav/dist/index.js +0 -614
- package/packages/agentsam-nav/dist/legacy.css +0 -83
- package/packages/agentsam-nav/dist/shell.css +0 -113
- package/packages/agentsam-nav/dist/theme.css +0 -113
- package/packages/agentsam-nav/dist/utils.d.ts +0 -1
- package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +0 -670
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Save & Persistence for Browser Games (localStorage vs IndexedDB, versioned saves, serialization, autosave)
|
|
2
|
+
|
|
3
|
+
Consolidated from MDN storage docs and the `idb` library (see Sources). Focus: what an AI builder needs so saves **survive updates, don't corrupt, and don't block the frame** — the usual bugs are lost progress on a schema change, quota errors, and jank from synchronous writes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Pick the right storage
|
|
8
|
+
|
|
9
|
+
**`localStorage`** — simple key/value, **synchronous, string-only, ~5MB** per origin.
|
|
10
|
+
- Good for: small settings, high scores, current-level, a single small save blob, key bindings, volume.
|
|
11
|
+
- **Synchronous = it blocks the main thread.** Fine for occasional small writes; **do NOT write large/frequent blobs to it every frame** (causes hitches). Values must be strings → `JSON.stringify`/`parse`.
|
|
12
|
+
- `sessionStorage` = same API but cleared when the tab closes (use for transient state only).
|
|
13
|
+
|
|
14
|
+
**IndexedDB** — **asynchronous**, transactional, large (hundreds of MB to GB, quota-based), stores **structured data** (objects, arrays, `Blob`, `ArrayBuffer`, typed arrays via the structured clone algorithm — no manual JSON needed).
|
|
15
|
+
- Good for: big/complex saves, multiple save slots, replays, generated assets/level caches, offline data.
|
|
16
|
+
- The raw API is verbose/callbacky — **use the `idb` wrapper** (Jake Archibald) for a clean promise-based API. Don't hand-roll raw IndexedDB.
|
|
17
|
+
|
|
18
|
+
**Rule of thumb:** settings/scores/small single save → `localStorage`; anything large, multi-slot, binary, or frequently written → **IndexedDB (via `idb`)**. Cookies are the wrong tool for game saves (tiny, sent on every request).
|
|
19
|
+
|
|
20
|
+
**Cache API / service worker** is for caching the *game itself* (assets, offline PWA), not for player save data.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. ALWAYS version your saves (the #1 lost-progress bug)
|
|
25
|
+
|
|
26
|
+
Your save schema *will* change between game versions. If you `JSON.parse` an old save into new code with no version handling, you get crashes or silent corruption and angry players who lost progress.
|
|
27
|
+
|
|
28
|
+
**Rule: every save carries a `version` number, and you write migration steps between versions.**
|
|
29
|
+
```js
|
|
30
|
+
const SAVE_VERSION = 3;
|
|
31
|
+
function migrate(save) {
|
|
32
|
+
let s = { ...save };
|
|
33
|
+
if (s.version === 1) { s.coins = s.gold ?? 0; delete s.gold; s.version = 2; }
|
|
34
|
+
if (s.version === 2) { s.settings = { ...defaults.settings, ...s.settings }; s.version = 3; }
|
|
35
|
+
return s; // now at SAVE_VERSION
|
|
36
|
+
}
|
|
37
|
+
function loadSave(raw) {
|
|
38
|
+
let save = raw ?? structuredClone(defaultSave);
|
|
39
|
+
if (save.version !== SAVE_VERSION) save = migrate(save);
|
|
40
|
+
return save;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
- Migrations run **in sequence** (v1→v2→v3) so any old save upgrades.
|
|
44
|
+
- IndexedDB has its own **schema versioning** via the `open(name, version)` + `onupgradeneeded`/`idb`'s `upgrade` callback — use it to create/alter object stores. That's separate from your *data* version above; you often want both.
|
|
45
|
+
- **New fields:** merge over defaults (`{ ...defaults, ...loaded }`) so older saves gain new keys with sane values instead of `undefined`.
|
|
46
|
+
- Keep a **backup of the previous save** before overwriting, so a failed migration/corruption is recoverable.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 3. Serialization: what to save
|
|
51
|
+
|
|
52
|
+
- **Save state, not behavior.** Serialize plain data (positions, inventory, flags, RNG seed + counters). Never try to serialize class instances/functions/DOM/engine objects directly.
|
|
53
|
+
- **Save the seed + progress**, not the whole generated world, for procgen games — regenerate deterministically on load (see procgen skill). Massively smaller and robust.
|
|
54
|
+
- Use `structuredClone` / IndexedDB for objects with `Map`/`Set`/`Date`/typed arrays; **plain `JSON` drops those** (Map→`{}`, Date→string, `undefined`/functions omitted, `NaN`/`Infinity`→`null`). If using JSON, convert them explicitly.
|
|
55
|
+
- **Wrap every load in try/catch.** Corrupt/partial JSON must fall back to defaults, not white-screen the game.
|
|
56
|
+
- Consider a **checksum** or at least shape-validation of loaded data before trusting it. For competitive/leaderboard games remember client saves are trivially editable — validate server-side, don't trust local high scores.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 4. Autosave (do it safely)
|
|
61
|
+
|
|
62
|
+
- **Autosave on meaningful events** (level complete, checkpoint, item gained) and on a throttled timer — not every frame.
|
|
63
|
+
- **Debounce/throttle writes** (e.g. at most once every few seconds) to avoid thrashing storage and causing jank; coalesce rapid changes.
|
|
64
|
+
- **Save on `visibilitychange` (hidden) and `pagehide`/`beforeunload`** — mobile browsers kill backgrounded tabs without firing `beforeunload` reliably, so `visibilitychange → hidden` is the most reliable "player is leaving" signal. Do a final synchronous-ish flush there (localStorage) or a queued IndexedDB write.
|
|
65
|
+
- **Write atomically:** for IndexedDB use a transaction; for localStorage, build the full string then set it once (a half-written multi-key save = corruption). Keep the previous save until the new one is confirmed.
|
|
66
|
+
- Give visible feedback ("Saved") and expose manual save/load + multiple slots where appropriate.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 5. Quota, availability & privacy gotchas
|
|
71
|
+
- **Storage can throw or be disabled:** private/incognito mode, quota exceeded (`QuotaExceededError`), or blocked third-party storage. **Feature-detect and wrap in try/catch**; degrade gracefully (in-memory only) rather than crashing.
|
|
72
|
+
- **Eviction:** browsers can clear storage under pressure ("best-effort" default). For important saves, request **`navigator.storage.persist()`** to reduce eviction risk, and check `navigator.storage.estimate()` for usage/quota.
|
|
73
|
+
- Storage is **per-origin**; a domain change loses saves. iOS Safari has historically been aggressive about clearing storage from rarely-visited sites — don't treat browser storage as permanent; offer export/import (download/upload a save file) for anything precious, and cloud save for accounts.
|
|
74
|
+
- **`localStorage` blocks the main thread** — keep values small; move big/async work to IndexedDB.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 6. Bug-prevention checklist
|
|
79
|
+
- **No version field** → old saves crash new builds / silent data loss; version + sequential migrations.
|
|
80
|
+
- **Parsing without try/catch** → corrupt save white-screens the game; fall back to defaults.
|
|
81
|
+
- **Merging loaded save without defaults** → new fields are `undefined`; spread over defaults.
|
|
82
|
+
- **JSON round-trip of Map/Set/Date/typed arrays** → data silently lost; use structuredClone/IndexedDB or convert explicitly.
|
|
83
|
+
- **Frequent/large `localStorage.setItem`** → main-thread hitches; throttle + use IndexedDB for big data.
|
|
84
|
+
- **No save on tab hide** → mobile players lose progress; save on `visibilitychange`/`pagehide`.
|
|
85
|
+
- **Non-atomic multi-key writes** → partial/corrupt saves; write one blob / use a transaction, keep a backup.
|
|
86
|
+
- **Assuming storage always works** → crashes in private mode / over quota; feature-detect + try/catch + graceful degrade.
|
|
87
|
+
- **Trusting local high scores** → trivially cheatable; validate server-side for leaderboards.
|
|
88
|
+
- **Saving the whole procgen world** → bloated saves; save seed + progress and regenerate.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Defaults to apply
|
|
93
|
+
- **Ship a tiny save module by default:** `save(state)` / `load()` with a **`version` field + sequential `migrate()`**, **try/catch → defaults**, and **merge-over-defaults**. This single pattern prevents the most damaging bug (progress lost on update).
|
|
94
|
+
- **Storage routing rule baked in:** settings/scores/small save → `localStorage`; large/multi-slot/binary/frequent → **IndexedDB via `idb`**.
|
|
95
|
+
- **Autosave defaults:** save on checkpoints + throttled timer + **`visibilitychange`/`pagehide`**, written atomically with a retained backup.
|
|
96
|
+
- **Persist the seed, not the world** for procgen; offer **export/import** for precious saves and request `storage.persist()`. Never trust local scores for leaderboards.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Sources
|
|
101
|
+
- MDN — Web Storage API (`localStorage`/`sessionStorage`): https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
|
|
102
|
+
- MDN — IndexedDB API + Using IndexedDB (versioning/`onupgradeneeded`): https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API , https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
|
|
103
|
+
- MDN — Structured clone algorithm (what serializes): https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm ; `structuredClone()`: https://developer.mozilla.org/en-US/docs/Web/API/structuredClone
|
|
104
|
+
- MDN — Storage quotas & eviction / `navigator.storage`: https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria , https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persist
|
|
105
|
+
- MDN — `Document.visibilitychange` / Page Visibility API: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
|
106
|
+
- `idb` (promise-based IndexedDB wrapper, Jake Archibald): https://github.com/jakearchibald/idb
|
|
107
|
+
- web.dev — "Storage for the web" (choosing storage): https://web.dev/articles/storage-for-the-web
|
|
108
|
+
- localForage (localStorage-like API over IndexedDB): https://github.com/localForage/localForage
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Browser Game Best Practices — Three.js / Babylon.js / Phaser (controls, camera, orientation, loop, assets, perf)
|
|
2
|
+
|
|
3
|
+
Consolidated from official docs, well-regarded tutorials, and engine forums (see Sources at bottom). Focus: what an AI builder needs to get **browser games that feel right and don't have the usual bugs.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Game loop & timing (the #1 correctness issue)
|
|
8
|
+
|
|
9
|
+
**Rules:**
|
|
10
|
+
- Drive the loop with **`renderer.setAnimationLoop(fn)`** in Three.js (internally uses `requestAnimationFrame`, plays nicely with WebXR) or the engine's built-in loop (Phaser `update(time, delta)`, Babylon `scene.onBeforeRenderObservable` / `engine.runRenderLoop`). Avoid `setTimeout`/`setInterval` and `Date.now()`.
|
|
11
|
+
- **Scale ALL movement/animation by delta time** (seconds since last frame) so speed is frame-rate independent (30fps laptop vs 144Hz monitor). e.g. `mesh.position.x += speed * delta`.
|
|
12
|
+
- **Cap delta** to avoid huge jumps after a backgrounded tab: `delta = Math.min(delta, 0.1)`.
|
|
13
|
+
- **Compute delta exactly once per frame** and reuse it everywhere.
|
|
14
|
+
- Three.js gotcha: `THREE.Clock.getDelta()` mutates state — calling it more than once per frame returns ~0 on later calls (very common bug). Newer `THREE.Timer` (Clock deprecated ~r183) has an explicit `.update()` so delta can be read multiple times safely.
|
|
15
|
+
- **For physics/gameplay stability use a fixed timestep + accumulator** ("Fix Your Timestep"): run `fixedUpdate(FIXED_STEP)` (e.g. 1/60) in a `while (accumulator >= FIXED_STEP)` loop, render at display rate, optionally interpolate. Variable delta is fine for purely visual demos.
|
|
16
|
+
- **Modularize**: give objects a `.update(delta)`/`.tick(delta)` method and iterate an "updatables" list; keep the top-level loop lean.
|
|
17
|
+
- **On-demand rendering**: if nothing is animating, stop the loop / render only on change to save battery (Three.js `setAnimationLoop(null)`; R3F `frameloop="demand"`).
|
|
18
|
+
|
|
19
|
+
**Reference pattern (Three.js, Timer + capped delta + fixed step):**
|
|
20
|
+
```js
|
|
21
|
+
const timer = new THREE.Timer();
|
|
22
|
+
let accumulator = 0; const FIXED = 1/60;
|
|
23
|
+
function animate() {
|
|
24
|
+
timer.update();
|
|
25
|
+
let delta = Math.min(timer.getDelta(), 0.25);
|
|
26
|
+
accumulator += delta;
|
|
27
|
+
while (accumulator >= FIXED) { fixedUpdate(FIXED); accumulator -= FIXED; } // physics/AI
|
|
28
|
+
updateVisuals(delta);
|
|
29
|
+
renderer.render(scene, camera);
|
|
30
|
+
}
|
|
31
|
+
renderer.setAnimationLoop(animate);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. First-person / WASD + mouse-look controls (Three.js)
|
|
37
|
+
|
|
38
|
+
The canonical reference is the official `misc_controls_pointerlock` example (https://threejs.org/examples/misc_controls_pointerlock.html).
|
|
39
|
+
|
|
40
|
+
**Key facts & rules:**
|
|
41
|
+
- **`PointerLockControls` only handles the Pointer Lock API + mouse-look (yaw/pitch). It does NOT include WASD movement — you implement keyboard + translation yourself.**
|
|
42
|
+
- Add **`controls.getObject()`** (the yaw container) to the scene, not the camera directly; the camera is a child for pitch.
|
|
43
|
+
- Track keys with **boolean state flags** set in `keydown`/`keyup` (support both `KeyW`/`ArrowUp`, etc.). Do NOT move on the keydown event itself.
|
|
44
|
+
- Move with **velocity + delta time** (acceleration + friction/damping), not a fixed distance per press — feels far better.
|
|
45
|
+
- Use **`controls.moveForward()` / `controls.moveRight()`** — they respect current yaw (local XZ plane). Do NOT modify `camera.rotation`/`camera.position` directly for horizontal movement.
|
|
46
|
+
- Pointer lock **requires a user gesture**: always show a "Click to play" blocker overlay; call `controls.lock()` on click; handle `'lock'`/`'unlock'` events and `pointerlockerror`; provide escape-to-unlock and a crosshair.
|
|
47
|
+
- **Avoid the deprecated `FirstPersonControls`** (behaves like fly controls).
|
|
48
|
+
- For real collisions/slopes/stairs, integrate a physics character controller: **Rapier.js `KinematicCharacterController`** (currently favored), or cannon-es (`PointerLockControlsCannon`), Ammo.js. Sync the body to `controls.getObject()`.
|
|
49
|
+
- Encapsulate as a `FirstPersonController` class with `update(delta)`, `lock()`, `dispose()`, and tunable `speed`/`jumpHeight`. Add sprint (Shift), crouch, head-bob for feel.
|
|
50
|
+
- R3F: use drei `<PointerLockControls />` + `useKeyboardControls` + `useFrame`.
|
|
51
|
+
|
|
52
|
+
**Other camera rigs:**
|
|
53
|
+
- **Orbit / product inspection:** Three.js `OrbitControls`; Babylon `ArcRotateCamera` (set `lower/upperRadiusLimit`, `lower/upperBetaLimit`, `inertia`, `panningSensibility`).
|
|
54
|
+
- **Third-person follow:** lerp camera toward a target offset behind the player each frame; `camera.lookAt(player)`; Babylon has `FollowCamera`.
|
|
55
|
+
- Keep the far plane / `camera.maxZ` (Babylon) as small as practical — improves culling, overdraw, and depth precision.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. 3D orientation & coordinate conventions (a top source of "why is my model sideways/backwards" bugs)
|
|
60
|
+
|
|
61
|
+
- **Three.js is right-handed, +Y up:** +X right, +Y up, +Z toward the viewer. Default camera sits at +Z looking toward −Z. (Differs from Unreal's Z-up, etc.) Changing global up (`Object3D.DefaultUp`) is discouraged — it affects helpers/grids.
|
|
62
|
+
- **Forward-axis gotcha:**
|
|
63
|
+
- Most `Object3D` (Mesh/Group): **local forward is +Z** `(0,0,1)`. Model/rotate so the "front" aligns with +Z.
|
|
64
|
+
- **Camera** (and some lights): forward is **local −Z** `(0,0,-1)`. This is the classic "camera looks backwards" gotcha.
|
|
65
|
+
- Many primitives (`ConeGeometry`, `CylinderGeometry`) point along **+Y** by default → rotate before use, e.g. `geo.rotateX(Math.PI/2)` to make +Y → +Z (align an arrow/cone's tip with forward).
|
|
66
|
+
- **`object.lookAt(target)`** rotates in **world space** so the forward axis points at the target (uses `.up`, quaternions internally; does not move the object). For nested targets, first `target.getWorldPosition(v)`. To face a *direction* vector: `obj.lookAt(obj.position.clone().add(dir))`.
|
|
67
|
+
- Imported glTF/GLB models may need an initial rotation to match +Z-forward. glTF/Blender export is right-handed Y-up, consistent with Three.js.
|
|
68
|
+
- Debug with `AxesHelper` and `ArrowHelper` to visualize orientation quickly.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 4. Performance (Three.js-centric, principles apply broadly)
|
|
73
|
+
|
|
74
|
+
**The #1 killer is draw calls** (`renderer.info.render.calls`). Target **<100/frame** for smooth 60fps on most hardware; 500+ stutters; mobile is stricter.
|
|
75
|
+
|
|
76
|
+
- **Share materials** aggressively (reuse one material instance across meshes).
|
|
77
|
+
- **Instancing (`InstancedMesh`)** for many *identical* objects (trees, crowds, bullets) → one draw call; update via `setMatrixAt` + `instanceMatrix.needsUpdate`. Note: default frustum culling applies to the whole instanced mesh.
|
|
78
|
+
- **`BatchedMesh`** (r156+) for *varied* geometries sharing one material, with per-object visibility + `perObjectFrustumCulled`.
|
|
79
|
+
- **Merge geometries** (`BufferGeometryUtils.mergeGeometries`) for fully static scenery sharing a material (loses per-object culling — one bounding volume).
|
|
80
|
+
- **Frustum culling** is automatic (`mesh.frustumCulled`); after modifying geometry call `computeBoundingBox()`/`computeBoundingSphere()`. Reduce `camera.far` where possible.
|
|
81
|
+
- **Dispose GPU resources manually** — Three.js does NOT GC them. On removing objects/switching levels: `geometry.dispose()`, `material.dispose()`, and dispose all textures. Watch `renderer.info.memory`. Use **object pooling** for particles/enemies instead of create/destroy churn.
|
|
82
|
+
- **Avoid allocations in the hot loop** (no `new Vector3()`/`new Matrix4()` per frame; reuse temporaries; Babylon has `TmpVectors` and `xxxToRef()`).
|
|
83
|
+
- **LOD** (`THREE.LOD`) — swap lower-poly at distance. Compress geometry (Draco) and textures (**KTX2/Basis**); prefer texture atlases.
|
|
84
|
+
- Limit lights; bake lighting/AO where possible; keep shadow maps small (and `RENDER_ONCE` refresh for static lights).
|
|
85
|
+
- Add **Stats.js**/FPS counter during dev; profile with Spector.js / engine inspector; profile on target devices.
|
|
86
|
+
|
|
87
|
+
**Babylon.js specifics:** prefer WebGPU w/ fallback + `powerPreference:"high-performance"`; `scene.performancePriority` (Intermediate/Aggressive); `scene.autoClear=false` when meshes cover viewport; `scene.skipPointerMovePicking=true` if no hover-picking; **thin instances** for static crowds; `mesh.freezeWorldMatrix()`, `material.freeze()`, `scene.freezeActiveMeshes()` for static content; `engine.setHardwareScalingLevel(2)` on low-end/mobile; `SceneOptimizer` to auto-degrade quality to hit a target FPS; keep `camera.maxZ` low. Camera "Behaviors" (Framing/Bouncing/AutoRotation) give polish for free.
|
|
88
|
+
|
|
89
|
+
**Phaser specifics:** heavy **object pooling** (Groups with `maxSize`, recycle via `active/visible=false`), process only active objects, texture atlases (Texture Packer), destroy tweens/emitters on `SHUTDOWN`, smaller canvas + CSS upscaling, lazy-load per-level assets.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 5. Engine / stack choice
|
|
94
|
+
|
|
95
|
+
- **2D games → Phaser** (Phaser 3/4): scenes, Arcade/Matter physics, Scale Manager, huge ecosystem, great mobile support. Best default for 2D.
|
|
96
|
+
- **3D games → Three.js** (most control, largest community) or **Babylon.js** (batteries-included: inspector, physics, WebGPU, camera behaviors, SceneOptimizer). **PlayCanvas** if you want a full editor/engine.
|
|
97
|
+
- Physics: 2D → Arcade (simple) / Matter (rigid bodies); 3D → **Rapier.js** (fast, WASM, popular) / cannon-es / Ammo.js.
|
|
98
|
+
- Tooling: **Vite + TypeScript**; PWA (manifest + service worker) for installable/offline mobile.
|
|
99
|
+
|
|
100
|
+
**Phaser architecture (from best-practice write-ups):** one file per Scene extending `Phaser.Scene`; a scene stack of Boot → Preload (progress bar) → Menu → Game → parallel UI/HUD (`scene.launch`) → Pause/GameOver. Lifecycle: `init(data)` → `preload()` → `create(data)` → `update(time,delta)`; clean up on `SHUTDOWN`. Constants file for all string keys. Decouple scenes via an EventEmitter "EventsCenter" or `registry`, not direct references. Prefabs (custom GameObject subclasses) + FSM/ECS for complex logic instead of a giant `update()`.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 6. Assets: generate vs. code vs. link
|
|
105
|
+
|
|
106
|
+
- **Generate real images** for sprites/textures/backgrounds/UI where the builder can (matches Lovable/v0 philosophy: no placeholder images in the final product). For pixel art request specific specs ("clean 32×32 side-view run cycle, 8 frames, sprite sheet, transparent background").
|
|
107
|
+
- **Don't hand-draw complex SVG/geometry** for illustrations or maps — use real assets or a library (echoes v0/Claude anti-slop rules).
|
|
108
|
+
- **Optimize for the browser:** compressed textures (KTX2/Basis/WebP), power-of-two, atlases, keep total download small (aim <20–50MB). Draco/Meshopt for glTF.
|
|
109
|
+
- **Placeholder > bad attempt** (Claude): if a good asset can't be produced, use a clean placeholder rather than an ugly hand-rolled one.
|
|
110
|
+
- Set **`crossOrigin='anonymous'`** on images drawn to `<canvas>`/textures to avoid CORS taint (v0 rule).
|
|
111
|
+
- 3D model pipeline: glTF/GLB (Y-up, right-handed) with Draco/Meshopt/KTX2; verify forward-axis orientation on import.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 7. Mobile / responsive / touch
|
|
116
|
+
|
|
117
|
+
- Distinguish the **canvas drawing buffer** (`canvas.width/height`) from **CSS display size**; account for `devicePixelRatio` to avoid blurry/tiny output. Rendering at a smaller internal resolution + CSS upscale is a valid perf win; `image-rendering: pixelated` for pixel art.
|
|
118
|
+
- Choose a **base design resolution** + aspect ratio; **letterbox (FIT)** to avoid stretching. Phaser: `scale: { mode: Phaser.Scale.FIT, autoCenter: CENTER_BOTH, width, height }` and handle the `resize` event; listen for `orientationchange`.
|
|
119
|
+
- Viewport meta: `width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no`; CSS `touch-action: none` and `preventDefault()` on touch to stop scroll/zoom.
|
|
120
|
+
- **Touch controls:** virtual joystick (e.g. **nipplejs**, `mode:'static'` or `'dynamic'`), split screen (left = move, right = actions/aim), normalize input to −1..1 and apply with delta time, visual feedback on active. **Minimum touch/hit target 44px** (Claude/Apple HIG). Unify keyboard + touch + Gamepad API into one input state.
|
|
121
|
+
- Test on real iOS Safari (audio unlock on gesture, WebGL context loss, touch coalescing) and low-end Android.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 8. Common browser-game bugs to prevent (checklist)
|
|
126
|
+
- Movement tied to frame rate (no delta) → runs too fast/slow on different displays.
|
|
127
|
+
- `Clock.getDelta()` called multiple times per frame → things freeze/jitter.
|
|
128
|
+
- Model faces wrong way → forgot +Z-forward convention / camera −Z; fix geometry rotation or `lookAt`.
|
|
129
|
+
- Pointer lock never engages → missing user-gesture click / blocker overlay.
|
|
130
|
+
- Memory leak / crash after level reload → geometries/materials/textures not disposed.
|
|
131
|
+
- Frame drops → too many draw calls (needs instancing/batching/atlases), per-frame allocations, uncompressed textures.
|
|
132
|
+
- Blurry or misaligned on mobile/retina → not handling devicePixelRatio / canvas resize.
|
|
133
|
+
- CORS-tainted canvas → missing `crossOrigin='anonymous'`.
|
|
134
|
+
- Physics tunneling/instability → variable timestep instead of fixed step.
|
|
135
|
+
- Audio doesn't play on mobile → not unlocked on first user gesture.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Sources
|
|
140
|
+
- Three.js official: PointerLock example (https://threejs.org/examples/misc_controls_pointerlock.html), docs for `Timer`, `Object3D.lookAt`, `InstancedMesh`, `BatchedMesh` (https://threejs.org/docs/).
|
|
141
|
+
- "Discover three.js" — animation loop / Loop class (https://discoverthreejs.com/book/first-steps/animation-loop/).
|
|
142
|
+
- Three.js Discourse (Clock→Timer r183, setAnimationLoop vs RAF, coordinate-system threads) — https://discourse.threejs.org/.
|
|
143
|
+
- Three.js perf write-ups: utsubo.com "100 tips" (https://www.utsubo.com/blog/threejs-best-practices-100-tips), threejsroadmap.com draw calls.
|
|
144
|
+
- StackOverflow / Medium tutorials on PointerLock WASD and Rapier character controllers (https://medium.com/javascript-alliance/creating-a-first-person-character-controller-in-three-js-5d96534edfd8).
|
|
145
|
+
- Babylon.js: official optimization guide (https://doc.babylonjs.com/features/featuresDeepDive/scene/optimize_your_scene), SceneOptimizer, camera input docs; 2025 forum best-practices thread (https://forum.babylonjs.com/t/best-practices-for-optimizing-babylon-js-scenes-not-just-on-lower-end-devices/58688); Babylon 9.0 notes.
|
|
146
|
+
- Phaser: docs.phaser.io (Scenes, Arcade Physics), Phaser Discourse best-practices threads, franzeus.medium.com "How I optimized my Phaser 3 action game in 2025".
|
|
147
|
+
- Mobile/touch: nipplejs (https://github.com/yoannmoinet/nipplejs), joshmorony.com Phaser scaling guide.
|
|
148
|
+
- Fix Your Timestep (Gaffer On Games) — classic fixed-timestep reference.
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: controls
|
|
3
|
+
description: >
|
|
4
|
+
Player-facing input signs for browser games: WASD, vehicles, flight, FPS
|
|
5
|
+
mouse-look, and the #1 failure mode (inverted A/D). Mandatory control
|
|
6
|
+
self-tests and a tiny test interface so you can verify A turns left before
|
|
7
|
+
shipping. Load for ANY game with movement, steering, flying, driving, tanks,
|
|
8
|
+
boats, mechs, drones, planes, karts, third-person follow cams — not only
|
|
9
|
+
racing. Triggers on "controls", "WASD", "inverted", "steer", "flight",
|
|
10
|
+
"airplane", "kart", "vehicle", "yaw", "roll", "pitch", "mouse look", "A/D".
|
|
11
|
+
metadata:
|
|
12
|
+
short-description: "Control signs, inverted A/D fix, vehicle/flight maps, mandatory self-test"
|
|
13
|
+
user-invocable: false
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Controls (player-visible signs — do not ship inverted)
|
|
17
|
+
|
|
18
|
+
**Read this end-to-end before writing movement/steer/flight code** for any game
|
|
19
|
+
that uses WASD, arrows, a chase camera, or a flying craft. Do **not** skip this
|
|
20
|
+
and only open `racing-kart` or `fps` — those genre files assume you already
|
|
21
|
+
know these signs. Inverted A/D is the most common ship-blocker in vehicle and
|
|
22
|
+
flight demos.
|
|
23
|
+
|
|
24
|
+
Pair with **`building-games`** (loop, camera, 3D orientation) and
|
|
25
|
+
**`building-games/references/input.md`** (keydown state, gamepad, touch). This
|
|
26
|
+
skill owns **what left/right/up mean to the player** and **how you prove it**.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 0. Hard rules (fail the build if broken)
|
|
31
|
+
|
|
32
|
+
1. **Player-visible left/right is law.** From a **chase / behind** camera while
|
|
33
|
+
the craft moves **forward**:
|
|
34
|
+
- **A / ←** → nose (or bank) turns **left on screen**
|
|
35
|
+
- **D / →** → nose (or bank) turns **right on screen**
|
|
36
|
+
2. **Never reuse FPS strafe as vehicle steer.** FPS “D → +right vector” is
|
|
37
|
+
**position** on the ground plane. Vehicle A/D is **yaw (or roll) rate**, not
|
|
38
|
+
a strafe offset. Mixing them is the #1 cause of inverted A/D.
|
|
39
|
+
3. **You must run a control self-test (§5) before saying done.** Screenshot-only
|
|
40
|
+
QA is not enough. If A turns right, **flip the steer/roll sign**, retest,
|
|
41
|
+
then ship — do not invent a new coordinate story.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 1. Shared 3D basis (use this everywhere)
|
|
46
|
+
|
|
47
|
+
three.js: right-handed, **+Y up**, meshes face **+Z**, cameras look **−Z**.
|
|
48
|
+
|
|
49
|
+
**Yaw-only heading on XZ** (ground vehicles, walkers, most arcade craft):
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
// yaw = 0 faces world −Z; +yaw is CCW about +Y (nose moves toward −X)
|
|
53
|
+
forward = (-sin(yaw), 0, -cos(yaw))
|
|
54
|
+
right = ( cos(yaw), 0, -sin(yaw)) // = normalize(cross(forward, worldUp))
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
With a chase cam **behind** the craft (camera near `position - forward * dist`):
|
|
58
|
+
|
|
59
|
+
| Player sees | World (this basis) | Input |
|
|
60
|
+
|-------------|--------------------|--------|
|
|
61
|
+
| Nose left | **+yaw** | **A / ←** must produce **+yaw** (or equivalent bank-left for planes) |
|
|
62
|
+
| Nose right | **−yaw** | **D / →** must produce **−yaw** |
|
|
63
|
+
|
|
64
|
+
If your basis differs, keep **one** consistent pair — but the **player-visible**
|
|
65
|
+
row above is mandatory.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 2. Genre maps
|
|
70
|
+
|
|
71
|
+
### 2a. FPS / on-foot (strafe, not steer)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
W = +forward, S = −forward, D = +right, A = −right // position, not yaw
|
|
75
|
+
mouse: yaw -= movementX * sens; pitch -= movementY * sens; clamp pitch
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Body yaw for look; **movement uses yaw only** (do not apply pitch to walk).
|
|
79
|
+
|
|
80
|
+
### 2b. Ground / water vehicle (kart, bike, jetski, boat, tank, rover, snowmobile)
|
|
81
|
+
|
|
82
|
+
Arcade body with `heading`/`yaw` and forward `speed`:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
// Input (held keys → actions once per frame)
|
|
86
|
+
let steer = 0; // -1..+1, player-visible
|
|
87
|
+
if (keys.has('KeyA') || keys.has('ArrowLeft')) steer += 1; // LEFT
|
|
88
|
+
if (keys.has('KeyD') || keys.has('ArrowRight')) steer -= 1; // RIGHT
|
|
89
|
+
// Optional: steer = clamp(steer + gamepadX, -1, 1) with same sign convention
|
|
90
|
+
|
|
91
|
+
// Integrate (speedFactor ~ 0..1 from |speed|)
|
|
92
|
+
const reverse = speed >= 0 ? 1 : -1; // wheel-left still feels left in reverse
|
|
93
|
+
yaw += steer * turnRate * speedFactor * reverse * dt;
|
|
94
|
+
|
|
95
|
+
// Move along heading
|
|
96
|
+
const fx = -Math.sin(yaw), fz = -Math.cos(yaw);
|
|
97
|
+
position.x += fx * speed * dt;
|
|
98
|
+
position.z += fz * speed * dt;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Canonical bug (do not copy):**
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
// WRONG — this is what ships inverted A/D in the wild
|
|
105
|
+
if (KeyA) steer -= 1;
|
|
106
|
+
if (KeyD) steer += 1;
|
|
107
|
+
yaw += steer * turnRate * dt; // A → −yaw → nose RIGHT on chase cam
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If you already wrote `KeyA → steer--`, either **swap the key mapping** or
|
|
111
|
+
**negate once at integrate** (`yaw += -steer * …`) — then run §5. Do not flip
|
|
112
|
+
twice (keys + integrate + bank mesh).
|
|
113
|
+
|
|
114
|
+
### 2c. Fixed-wing flight (airplane, glider, RC plane)
|
|
115
|
+
|
|
116
|
+
| Input | Action | Player expectation |
|
|
117
|
+
|-------|--------|--------------------|
|
|
118
|
+
| **A / ←** | **Roll left** (aileron) | Left wing down / bank left |
|
|
119
|
+
| **D / →** | **Roll right** | Right wing down / bank right |
|
|
120
|
+
| **W / ↑** | Pitch (pick one scheme and label HUD) | Usually nose down *or* pull-up — be consistent |
|
|
121
|
+
| **S / ↓** | Opposite pitch | |
|
|
122
|
+
| **Q / E** | Yaw / rudder (optional) | Q left, E right |
|
|
123
|
+
|
|
124
|
+
- **A/D are not strafe** and not “ground steer with FPS signs.”
|
|
125
|
+
- Apply roll in the craft’s **local forward axis** with a sign that matches
|
|
126
|
+
**bank left on A**. If the mesh banks the wrong way, flip **one** sign on the
|
|
127
|
+
roll apply (or on the A/D → roll mapping), not the whole basis.
|
|
128
|
+
- Coordinated turn: positive bank should produce a turn that matches the bank
|
|
129
|
+
direction under the chase/external cam.
|
|
130
|
+
|
|
131
|
+
### 2d. Heli / drone / 6DOF
|
|
132
|
+
|
|
133
|
+
Document the scheme on a start overlay. Minimum:
|
|
134
|
+
|
|
135
|
+
- Throttle/altitude on discrete keys must **not** stick “always up” after one
|
|
136
|
+
press (use held state or explicit up/down).
|
|
137
|
+
- Strafe/yaw: **A left, D right** in the craft’s horizontal frame (player-visible).
|
|
138
|
+
|
|
139
|
+
### 2e. 2D side-scroller / platformer
|
|
140
|
+
|
|
141
|
+
**D / →** moves **right on screen**; **A / ←** moves **left**. Gravity only
|
|
142
|
+
inverted if the genre is explicitly upside-down.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 3. Camera must agree
|
|
147
|
+
|
|
148
|
+
- Chase cam: `desired = craftPos + up*height + forward*(-followDist)`; lerp;
|
|
149
|
+
`lookAt(craft)`.
|
|
150
|
+
- Compute `forward` **once** for both movement and camera — do not rebuild with
|
|
151
|
+
opposite yaw sign in the camera path.
|
|
152
|
+
- Debug order: (1) keys register → (2) signs correct (§5) → (3) camera agrees.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 4. Input plumbing (brief)
|
|
157
|
+
|
|
158
|
+
- Track keys with a `Set` on `keydown`/`keyup` using **`event.code`**; clear on
|
|
159
|
+
`blur` / `visibilitychange`. Move in the game loop with **dt**, not in the
|
|
160
|
+
key handler.
|
|
161
|
+
- Unify keyboard + touch + gamepad into **actions** (`throttle`, `steer`,
|
|
162
|
+
`pitch`, `roll`, …). See `building-games/references/input.md`.
|
|
163
|
+
- Touch: left stick = move/steer, right = actions; ≥44px targets.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 5. Mandatory control self-test (before “done”)
|
|
168
|
+
|
|
169
|
+
Screenshot-only is **not** enough for any craft with A/D.
|
|
170
|
+
|
|
171
|
+
### 5a. Player-visible checklist (every vehicle / flight build)
|
|
172
|
+
|
|
173
|
+
While **moving forward** (speed > small epsilon), chase cam behind:
|
|
174
|
+
|
|
175
|
+
| Hold | Must observe within ~0.5s |
|
|
176
|
+
|------|---------------------------|
|
|
177
|
+
| **A** | Nose or bank moves **left** on screen |
|
|
178
|
+
| **D** | Nose or bank moves **right** on screen |
|
|
179
|
+
| **W** (ground) | Speed increases / moves along facing |
|
|
180
|
+
| **S** (ground) | Brakes or reverse (as designed) |
|
|
181
|
+
|
|
182
|
+
If A fails: flip steer/roll sign **once**, retest both A and D.
|
|
183
|
+
|
|
184
|
+
### 5b. Minimal test interface (implement this)
|
|
185
|
+
|
|
186
|
+
Expose a tiny hook so you (and automated QA) can prove signs without guessing
|
|
187
|
+
private closures:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
// e.g. src/game/controlsTest.ts — dev/QA only is fine
|
|
191
|
+
export type ControlsProbe = {
|
|
192
|
+
getYaw: () => number; // radians; or getHeading()
|
|
193
|
+
getSpeed: () => number;
|
|
194
|
+
/** Inject held actions instead of real keys; both stay applied until you
|
|
195
|
+
* change them, so §5c can hold a key across frames and clear at the end. */
|
|
196
|
+
setSteer?: (v: number) => void; // -1..1, same sign as production
|
|
197
|
+
setKeys?: (codes: string[]) => void; // held until the next call; `[]` clears
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
declare global {
|
|
201
|
+
interface Window {
|
|
202
|
+
__controlsTest?: ControlsProbe;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Wire `window.__controlsTest` from the game loop when `import.meta.env.DEV` or a
|
|
208
|
+
`?qa=1` flag is set.
|
|
209
|
+
|
|
210
|
+
### 5c. Automated smoke (run it)
|
|
211
|
+
|
|
212
|
+
Drive the §5b probe with the preinstalled **`agent-browser`** CLI — that is the
|
|
213
|
+
first move, not a hand-written script. **A thrown `eval` exits non-zero; a
|
|
214
|
+
merely falsy one does not**, so assert by throwing. Run it as one `batch` — one
|
|
215
|
+
CLI call, not one per verb — taking JSON on stdin; `--bail` stops at the first
|
|
216
|
+
failing step and exits non-zero.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
agent-browser batch --bail <<'JSON' # find's label is case-sensitive: copy it from `snapshot -i`
|
|
220
|
+
[["open","http://127.0.0.1:8080/"],
|
|
221
|
+
["find","text","Start","click"],
|
|
222
|
+
["eval","if (!window.__controlsTest?.setKeys) throw Error('no §5b probe: add setKeys')"],
|
|
223
|
+
["eval","__controlsTest.setKeys(['KeyW'])"],
|
|
224
|
+
["wait","600"],
|
|
225
|
+
["eval","if (__controlsTest.getSpeed() <= 0.1) throw Error('W: no move')"],
|
|
226
|
+
["eval","(async () => { const t = __controlsTest, y0 = t.getYaw(); t.setKeys(['KeyW','KeyA']); await new Promise(r => setTimeout(r, 300)); t.setKeys(['KeyW']); const d = t.getYaw() - y0, w = Math.atan2(Math.sin(d), Math.cos(d)); if (w < -0.05) throw Error('A turns RIGHT — inverted, got ' + w.toFixed(2)); if (w <= 0.05) throw Error('A barely turned (' + w.toFixed(2) + ') — hold longer or check the sim is running'); return 'A ok' })()"],
|
|
227
|
+
["eval","__controlsTest.setKeys([])"],
|
|
228
|
+
["screenshot","/workspace/screenshots/controls.png"],
|
|
229
|
+
["close"]]
|
|
230
|
+
JSON
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Hold keys through the probe, not with `keydown`** — `agent-browser keydown`
|
|
234
|
+
does not reach §4's `Set`, so a correct game reads as broken. No `setKeys` on
|
|
235
|
+
your probe? Add it (§5b), or dispatch the key event yourself — the browser-QA
|
|
236
|
+
reference's **Keys** note has the mechanism and the form.
|
|
237
|
+
|
|
238
|
+
The hold sits **inside** one `eval`: spread across commands it lasts however
|
|
239
|
+
long they take, and the ±π wrap in `Math.atan2(Math.sin(d), Math.cos(d))`
|
|
240
|
+
reads a craft that turned more than π as one turning the other way. The IIFE is
|
|
241
|
+
what keeps the step re-runnable — a bare `const d = …` fails the second time
|
|
242
|
+
with "already declared" — and `async` is what lets the hold run in page time.
|
|
243
|
+
Repeat for **D** with `'KeyD'` and both comparisons mirrored (`w > 0.05` is
|
|
244
|
+
inverted, `w >= -0.05` is barely), single-quoted so the JSON needs no escapes;
|
|
245
|
+
for planes assert **roll**: A ⇒ bank left.
|
|
246
|
+
|
|
247
|
+
**`A turns RIGHT`** is the sign error: flip **one** sign and re-run.
|
|
248
|
+
**`A barely turned`** is not — the craft moved the right way, just less than
|
|
249
|
+
0.05 rad in 300 ms, which a boat or a heavy rover will do; raise the hold, or
|
|
250
|
+
check the sim is running, and flip nothing. Any other non-zero exit — no probe,
|
|
251
|
+
a wedged daemon — means the check never ran: read the message first. Read the
|
|
252
|
+
browser-QA reference `AGENTS.md` links before your first flow — verbs, argument
|
|
253
|
+
shapes and the fallback are there.
|
|
254
|
+
|
|
255
|
+
### 5d. What not to do
|
|
256
|
+
|
|
257
|
+
- Do **not** only test “D increases some internal variable.”
|
|
258
|
+
- Do **not** use FPS “D → +X when facing −Z” as the vehicle pass condition.
|
|
259
|
+
- Do **not** flip mesh bank, camera, and steer all at once when fixing — change
|
|
260
|
+
**one** sign, retest.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 6. Finish criteria (controls)
|
|
265
|
+
|
|
266
|
+
- [ ] Opened **this** skill before writing movement/steer/flight.
|
|
267
|
+
- [ ] Genre map chosen (§2) and start-screen / HUD labels match it.
|
|
268
|
+
- [ ] Chase-cam A/D player-visible test **passed** (§5a).
|
|
269
|
+
- [ ] `window.__controlsTest` (or equivalent) available in dev/QA and used once.
|
|
270
|
+
- [ ] No inverted bank mesh relative to roll/steer input.
|
|
271
|
+
- [ ] Keys are held-state + dt-scaled; no sticky thrust from a single Space tap
|
|
272
|
+
unless intentional and labeled.
|
|
273
|
+
|
|
274
|
+
If any box is unchecked, the game is **not** done.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "agentsam.skill.v1",
|
|
3
|
+
"id": "grok-controls",
|
|
4
|
+
"name": "Grok \u00b7 controls",
|
|
5
|
+
"description": "Control signs, inverted A/D fix, vehicle/flight maps, mandatory self-test",
|
|
6
|
+
"icon": "skill",
|
|
7
|
+
"slash": {
|
|
8
|
+
"suggested": "/grok-controls"
|
|
9
|
+
},
|
|
10
|
+
"instructions": {
|
|
11
|
+
"source": "local_file",
|
|
12
|
+
"ref": "SKILL.md"
|
|
13
|
+
},
|
|
14
|
+
"execution": {
|
|
15
|
+
"mode": "turn",
|
|
16
|
+
"tools": [],
|
|
17
|
+
"operations": [],
|
|
18
|
+
"capabilities": []
|
|
19
|
+
},
|
|
20
|
+
"provenance": {
|
|
21
|
+
"source": "apps/local-studio/.grok/skills",
|
|
22
|
+
"vendor": "grok",
|
|
23
|
+
"status": "imported"
|
|
24
|
+
}
|
|
25
|
+
}
|