@arcbridge/core 0.1.6 → 0.2.0

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/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { z } from "zod";
3
3
  var ServiceSchema = z.object({
4
4
  name: z.string().min(1),
5
5
  path: z.string().default("."),
6
- type: z.enum(["nextjs", "react", "fastify", "express", "hono", "dotnet"]),
6
+ type: z.enum(["nextjs", "react", "fastify", "express", "hono", "dotnet", "unity"]),
7
7
  tsconfig: z.string().optional(),
8
8
  csproj: z.string().optional()
9
9
  });
@@ -14,7 +14,8 @@ var ArcBridgeConfigSchema = z.object({
14
14
  "nextjs-app-router",
15
15
  "react-vite",
16
16
  "api-service",
17
- "dotnet-webapi"
17
+ "dotnet-webapi",
18
+ "unity-game"
18
19
  ]).default("nextjs-app-router"),
19
20
  services: z.array(ServiceSchema).default([]),
20
21
  platforms: z.array(z.enum(["claude", "copilot", "gemini", "codex"])).default(["claude"]),
@@ -743,12 +744,44 @@ function configTemplate4(input) {
743
744
  };
744
745
  }
745
746
 
747
+ // src/templates/config/unity-game.ts
748
+ function configTemplate5(input) {
749
+ return {
750
+ schema_version: 1,
751
+ project_name: input.name,
752
+ project_type: input.template,
753
+ services: [{ name: "main", path: ".", type: "unity" }],
754
+ platforms: input.platforms,
755
+ quality_priorities: input.quality_priorities,
756
+ indexing: {
757
+ include: ["Assets/**/*.cs"],
758
+ exclude: ["Library", "Temp", "obj", "bin", "Logs", "UserSettings", "Packages"],
759
+ default_mode: "fast",
760
+ csharp_indexer: "auto"
761
+ },
762
+ testing: {
763
+ test_command: "unity -batchmode -projectPath . -runTests -testPlatform EditMode",
764
+ timeout_ms: 12e4
765
+ },
766
+ drift: {
767
+ ignore_paths: []
768
+ },
769
+ metrics: { auto_record: false },
770
+ sync: {
771
+ auto_detect_drift: true,
772
+ drift_severity_threshold: "warning",
773
+ propose_updates_on: "phase-complete"
774
+ }
775
+ };
776
+ }
777
+
746
778
  // src/generators/config-generator.ts
747
779
  var configTemplates = {
748
780
  "nextjs-app-router": configTemplate,
749
781
  "react-vite": configTemplate2,
750
782
  "api-service": configTemplate3,
751
- "dotnet-webapi": configTemplate4
783
+ "dotnet-webapi": configTemplate4,
784
+ "unity-game": configTemplate5
752
785
  };
753
786
  function generateConfig(targetDir, input) {
754
787
  const templateFn = configTemplates[input.template] ?? configTemplate;
@@ -777,7 +810,7 @@ function introductionTemplate(input) {
777
810
 
778
811
  ## Requirements Overview
779
812
 
780
- ${input.name} is a ${input.template === "nextjs-app-router" ? "Next.js application using the App Router" : input.template === "dotnet-webapi" ? "ASP.NET Core Web API" : "web application"}.
813
+ ${input.name} is a ${input.template === "nextjs-app-router" ? "Next.js application using the App Router" : input.template === "dotnet-webapi" ? "ASP.NET Core Web API" : input.template === "unity-game" ? "Unity game built with a code-heavy C# architecture" : "web application"}.
781
814
 
782
815
  ### Key Features
783
816
 
@@ -814,6 +847,10 @@ function techStack(template) {
814
847
  return `- **Framework:** Express / Fastify
815
848
  - **Language:** TypeScript
816
849
  - **Runtime:** Node.js`;
850
+ case "unity-game":
851
+ return `- **Engine:** Unity
852
+ - **Language:** C#
853
+ - **Runtime:** Mono / IL2CPP`;
817
854
  default:
818
855
  return `- **Framework:** Next.js (App Router)
819
856
  - **Language:** TypeScript
@@ -882,6 +919,8 @@ function getEntrypoints(template, srcPrefix, appPrefix) {
882
919
  return [`${srcPrefix}main.tsx`, `${srcPrefix}App.tsx`];
883
920
  case "api-service":
884
921
  return [`${srcPrefix}index.ts`, `${srcPrefix}app.ts`, `${srcPrefix}server.ts`];
922
+ case "unity-game":
923
+ return ["Assets/Scripts/Core/GameManager.cs"];
885
924
  default:
886
925
  return [`${srcPrefix}index.ts`];
887
926
  }
@@ -891,7 +930,7 @@ function getEntrypoints(template, srcPrefix, appPrefix) {
891
930
  function buildingBlocksTemplate(input) {
892
931
  const now = (/* @__PURE__ */ new Date()).toISOString();
893
932
  const layout = detectProjectLayout(input.projectRoot, input.template);
894
- const defaultBlocks = input.template === "dotnet-webapi" ? buildDotnetBlocks(input) : buildJsBlocks(input, layout);
933
+ const defaultBlocks = input.template === "dotnet-webapi" ? buildDotnetBlocks(input) : input.template === "unity-game" ? buildUnityBlocks() : buildJsBlocks(input, layout);
895
934
  function buildJsBlocks(inp, lt) {
896
935
  const src = lt.srcPrefix;
897
936
  const entries = lt.entrypoints;
@@ -1087,6 +1126,98 @@ function buildingBlocksTemplate(input) {
1087
1126
  });
1088
1127
  return blocks;
1089
1128
  }
1129
+ function buildUnityBlocks() {
1130
+ return [
1131
+ {
1132
+ id: "game-core",
1133
+ name: "Game Core",
1134
+ level: 1,
1135
+ code_paths: ["Assets/Scripts/Core/"],
1136
+ interfaces: [],
1137
+ quality_scenarios: ["PERF-01", "PERF-02"],
1138
+ adrs: [],
1139
+ responsibility: "Game loop, GameManager, state machine, scene management",
1140
+ service: "main"
1141
+ },
1142
+ {
1143
+ id: "input-system",
1144
+ name: "Input System",
1145
+ level: 1,
1146
+ code_paths: ["Assets/Scripts/Input/"],
1147
+ interfaces: [],
1148
+ quality_scenarios: ["PERF-06"],
1149
+ adrs: [],
1150
+ responsibility: "Input handling layer, action maps, platform-independent input abstraction",
1151
+ service: "main"
1152
+ },
1153
+ {
1154
+ id: "player-systems",
1155
+ name: "Player Systems",
1156
+ level: 1,
1157
+ code_paths: ["Assets/Scripts/Player/"],
1158
+ interfaces: ["input-system"],
1159
+ quality_scenarios: [],
1160
+ adrs: [],
1161
+ responsibility: "Player controller, camera system, character state and animation",
1162
+ service: "main"
1163
+ },
1164
+ {
1165
+ id: "gameplay-systems",
1166
+ name: "Gameplay Systems",
1167
+ level: 1,
1168
+ code_paths: ["Assets/Scripts/Gameplay/"],
1169
+ interfaces: ["game-core"],
1170
+ quality_scenarios: ["MAINT-02"],
1171
+ adrs: [],
1172
+ responsibility: "Game mechanics, combat, inventory, AI, physics interactions",
1173
+ service: "main"
1174
+ },
1175
+ {
1176
+ id: "ui-framework",
1177
+ name: "UI Framework",
1178
+ level: 1,
1179
+ code_paths: ["Assets/Scripts/UI/"],
1180
+ interfaces: [],
1181
+ quality_scenarios: ["A11Y-01"],
1182
+ adrs: [],
1183
+ responsibility: "HUD, menus, dialogs, settings screens, and UI event handling",
1184
+ service: "main"
1185
+ },
1186
+ {
1187
+ id: "audio-system",
1188
+ name: "Audio System",
1189
+ level: 1,
1190
+ code_paths: ["Assets/Scripts/Audio/"],
1191
+ interfaces: [],
1192
+ quality_scenarios: [],
1193
+ adrs: [],
1194
+ responsibility: "Music playback, sound effects, spatial audio, and audio mixing",
1195
+ service: "main"
1196
+ },
1197
+ {
1198
+ id: "data-layer",
1199
+ name: "Data Layer",
1200
+ level: 1,
1201
+ code_paths: ["Assets/Scripts/Data/"],
1202
+ interfaces: [],
1203
+ quality_scenarios: [],
1204
+ adrs: [],
1205
+ responsibility: "ScriptableObject definitions, save/load system, game configuration, and persistent data",
1206
+ service: "main"
1207
+ },
1208
+ {
1209
+ id: "editor-tools",
1210
+ name: "Editor Tools",
1211
+ level: 1,
1212
+ code_paths: ["Assets/Editor/"],
1213
+ interfaces: [],
1214
+ quality_scenarios: [],
1215
+ adrs: [],
1216
+ responsibility: "Custom inspectors, editor windows, debug overlays, and development tools",
1217
+ service: "main"
1218
+ }
1219
+ ];
1220
+ }
1090
1221
  return {
1091
1222
  frontmatter: {
1092
1223
  section: "building-blocks",
@@ -1121,6 +1252,15 @@ Client \u2192 Kestrel \u2192 Middleware Pipeline \u2192 Controller / Endpoint
1121
1252
  Client \u2192 HTTP Server \u2192 Middleware \u2192 Route Handler
1122
1253
  \u2192 Services
1123
1254
  \u2192 Database / External APIs
1255
+ \`\`\``;
1256
+ case "unity-game":
1257
+ return `\`\`\`
1258
+ Input System \u2192 Player Controller \u2192 Gameplay Systems
1259
+ \u2192 Physics / Collision
1260
+ GameManager \u2192 State Machine \u2192 Active Game Systems
1261
+ \u2192 UI Framework
1262
+ \u2192 Audio System
1263
+ Unity Engine \u2192 Update Loop \u2192 Render Pipeline
1124
1264
  \`\`\``;
1125
1265
  default:
1126
1266
  return `\`\`\`
@@ -1140,7 +1280,7 @@ function runtimeViewsTemplate(input) {
1140
1280
 
1141
1281
  ## Key Runtime Scenarios
1142
1282
 
1143
- ### Request Flow
1283
+ ### ${input.template === "unity-game" ? "Game Loop" : "Request Flow"}
1144
1284
 
1145
1285
  ${runtimeDiagram(input.template)}
1146
1286
 
@@ -1168,7 +1308,13 @@ ${input.template === "dotnet-webapi" ? `| Platform | Description | Notes |
1168
1308
  |----------|-------------|-------|
1169
1309
  | Azure App Service | Managed PaaS for .NET | Recommended for ASP.NET Core |
1170
1310
  | Docker / Kubernetes | Container-based | For self-hosted or multi-cloud |
1171
- | AWS ECS / Fargate | Container orchestration | For AWS environments |` : `| Platform | Description | Notes |
1311
+ | AWS ECS / Fargate | Container orchestration | For AWS environments |` : input.template === "unity-game" ? `| Platform | Description | Notes |
1312
+ |----------|-------------|-------|
1313
+ | Steam | PC distribution | Recommended for indie games |
1314
+ | Apple App Store | iOS distribution | Requires Xcode build |
1315
+ | Google Play | Android distribution | For mobile games |
1316
+ | WebGL | Browser-based | For quick prototypes and web distribution |
1317
+ | Console | PlayStation, Xbox, Switch | Requires platform-specific SDKs |` : `| Platform | Description | Notes |
1172
1318
  |----------|-------------|-------|
1173
1319
  | Vercel | Recommended for Next.js | Zero-config deployment |
1174
1320
  | Docker | Container-based | For self-hosted environments |`}
@@ -1177,7 +1323,7 @@ ${input.template === "dotnet-webapi" ? `| Platform | Description | Notes |
1177
1323
 
1178
1324
  | Variable | Description | Required |
1179
1325
  |----------|-------------|----------|
1180
- | \`${input.template === "dotnet-webapi" ? "ASPNETCORE_ENVIRONMENT" : "NODE_ENV"}\` | Runtime environment | Yes |
1326
+ | \`${input.template === "dotnet-webapi" ? "ASPNETCORE_ENVIRONMENT" : input.template === "unity-game" ? "UNITY_TARGET_PLATFORM" : "NODE_ENV"}\` | ${input.template === "unity-game" ? "Build target platform" : "Runtime environment"} | Yes |
1181
1327
  | *Add your environment variables here* | | |
1182
1328
  `
1183
1329
  };
@@ -1193,6 +1339,8 @@ function firstAdrTemplate(input) {
1193
1339
  return reactViteAdr(input, now);
1194
1340
  case "api-service":
1195
1341
  return apiServiceAdr(input, now);
1342
+ case "unity-game":
1343
+ return unityAdr(input, now);
1196
1344
  default:
1197
1345
  return nextjsAdr(input, now);
1198
1346
  }
@@ -1297,6 +1445,44 @@ Use a Node.js HTTP framework (Express, Fastify, or Hono) as the API service foun
1297
1445
  `
1298
1446
  };
1299
1447
  }
1448
+ function unityAdr(input, date) {
1449
+ return {
1450
+ filename: "001-unity-code-heavy.md",
1451
+ frontmatter: {
1452
+ id: "001-unity-code-heavy",
1453
+ title: "Use Unity with Code-Heavy Architecture",
1454
+ status: "accepted",
1455
+ date,
1456
+ affected_blocks: ["game-core", "player-systems"],
1457
+ affected_files: ["Assets/Scripts/"],
1458
+ quality_scenarios: []
1459
+ },
1460
+ body: `# ADR-001: Use Unity with Code-Heavy Architecture
1461
+
1462
+ ## Context
1463
+
1464
+ ${input.name} needs a game engine with cross-platform support, strong performance, and a productive development workflow. The team prefers a code-driven approach over hand-crafting scenes in the editor.
1465
+
1466
+ ## Decision
1467
+
1468
+ Use Unity as the game engine with a code-heavy C# architecture. Favor programmatic scene composition, ScriptableObject data architecture, and assembly definitions for modular code organization.
1469
+
1470
+ ## Consequences
1471
+
1472
+ - **Positive:** Version control friendly \u2014 most logic lives in .cs files, not serialized scenes
1473
+ - **Positive:** Testable \u2014 gameplay logic can be unit tested without the editor
1474
+ - **Positive:** Reusable systems \u2014 assembly definitions enforce module boundaries
1475
+ - **Positive:** AI-agent friendly \u2014 agents work effectively with C# scripts
1476
+ - **Negative:** More boilerplate than visual scripting or drag-and-drop workflows
1477
+ - **Negative:** Scene references require discipline (use ScriptableObjects or addressables)
1478
+ - **Negative:** Some Unity features (Animator, Timeline) still require editor interaction
1479
+
1480
+ ## Agent Limitations
1481
+
1482
+ AI agents can review C# scripts, suggest architectural improvements, and check code quality \u2014 but they **cannot** evaluate gameplay feel, frame timing, or visual quality. Use [Unity-MCP](https://github.com/IvanMurzak/Unity-MCP) to give agents basic editor access (scene management, asset operations). For runtime quality (actual FPS, GC spikes, input latency), rely on the Unity Profiler and manual playtesting.
1483
+ `
1484
+ };
1485
+ }
1300
1486
  function dotnetAdr(input, date) {
1301
1487
  return {
1302
1488
  filename: "001-aspnet-core-webapi.md",
@@ -1611,11 +1797,139 @@ var API_SCENARIOS = {
1611
1797
  }
1612
1798
  ]
1613
1799
  };
1800
+ var UNITY_GAME_SCENARIOS = {
1801
+ performance: [
1802
+ {
1803
+ id: "PERF-01",
1804
+ name: "Frame rate stability at 60 FPS",
1805
+ category: "performance",
1806
+ priority: "must",
1807
+ scenario: "Game runs on target hardware during typical gameplay",
1808
+ expected: "Maintains 60 FPS (or platform target) with no frame exceeding 16.7ms",
1809
+ linked_code: [],
1810
+ linked_tests: [],
1811
+ linked_blocks: ["game-core"],
1812
+ verification: "semi-automatic",
1813
+ status: "untested"
1814
+ },
1815
+ {
1816
+ id: "PERF-02",
1817
+ name: "Zero per-frame GC allocations in gameplay",
1818
+ category: "performance",
1819
+ priority: "must",
1820
+ scenario: "Gameplay systems run during a typical session",
1821
+ expected: "No GC allocations per frame in hot-path gameplay code (use object pooling)",
1822
+ linked_code: [],
1823
+ linked_tests: [],
1824
+ linked_blocks: ["gameplay-systems"],
1825
+ verification: "semi-automatic",
1826
+ status: "untested"
1827
+ },
1828
+ {
1829
+ id: "PERF-03",
1830
+ name: "Draw calls under budget",
1831
+ category: "performance",
1832
+ priority: "should",
1833
+ scenario: "Peak visual complexity scene is rendered",
1834
+ expected: "Draw calls stay under 200 on target hardware (use batching, atlasing, instancing)",
1835
+ linked_code: [],
1836
+ linked_tests: [],
1837
+ linked_blocks: [],
1838
+ verification: "semi-automatic",
1839
+ status: "untested"
1840
+ },
1841
+ {
1842
+ id: "PERF-04",
1843
+ name: "Scene load time under 3s",
1844
+ category: "performance",
1845
+ priority: "should",
1846
+ scenario: "Player transitions between major scenes",
1847
+ expected: "Scene load completes within 3 seconds on minimum-spec hardware",
1848
+ linked_code: [],
1849
+ linked_tests: [],
1850
+ linked_blocks: ["game-core"],
1851
+ verification: "semi-automatic",
1852
+ status: "untested"
1853
+ },
1854
+ {
1855
+ id: "PERF-05",
1856
+ name: "Memory usage under platform budget",
1857
+ category: "performance",
1858
+ priority: "should",
1859
+ scenario: "Game is loaded and gameplay session is active",
1860
+ expected: "Memory stays under 512MB on mobile, 2GB on desktop",
1861
+ linked_code: [],
1862
+ linked_tests: [],
1863
+ linked_blocks: [],
1864
+ verification: "semi-automatic",
1865
+ status: "untested"
1866
+ },
1867
+ {
1868
+ id: "PERF-06",
1869
+ name: "Input-to-visual response under 100ms",
1870
+ category: "performance",
1871
+ priority: "should",
1872
+ scenario: "Player presses an input during gameplay",
1873
+ expected: "Visual feedback appears within 100ms of input",
1874
+ linked_code: [],
1875
+ linked_tests: [],
1876
+ linked_blocks: ["input-system", "player-systems"],
1877
+ verification: "semi-automatic",
1878
+ status: "untested"
1879
+ }
1880
+ ],
1881
+ security: [
1882
+ {
1883
+ id: "SEC-01",
1884
+ name: "No client-only validation for multiplayer state",
1885
+ category: "security",
1886
+ priority: "should",
1887
+ scenario: "Game state changes are validated (if multiplayer)",
1888
+ expected: "Critical game state changes are server-authoritative; client cannot cheat by modifying local state",
1889
+ linked_code: [],
1890
+ linked_tests: [],
1891
+ linked_blocks: [],
1892
+ verification: "manual",
1893
+ status: "untested"
1894
+ }
1895
+ ],
1896
+ reliability: [
1897
+ {
1898
+ id: "REL-01",
1899
+ name: "No unhandled exceptions crash the game",
1900
+ category: "reliability",
1901
+ priority: "should",
1902
+ scenario: "An unexpected error occurs during gameplay",
1903
+ expected: "Error is caught and logged; game recovers gracefully or shows error UI without crashing",
1904
+ linked_code: [],
1905
+ linked_tests: [],
1906
+ linked_blocks: ["game-core"],
1907
+ verification: "automatic",
1908
+ status: "untested"
1909
+ }
1910
+ ],
1911
+ accessibility: [
1912
+ {
1913
+ id: "A11Y-01",
1914
+ name: "Color-blind friendly UI",
1915
+ category: "accessibility",
1916
+ priority: "should",
1917
+ scenario: "Player with color vision deficiency plays the game",
1918
+ expected: "Critical UI elements distinguish by shape, pattern, or label \u2014 not color alone",
1919
+ linked_code: [],
1920
+ linked_tests: [],
1921
+ linked_blocks: ["ui-framework"],
1922
+ verification: "manual",
1923
+ status: "untested"
1924
+ }
1925
+ ]
1926
+ };
1614
1927
  var TEMPLATE_SCENARIOS = {
1615
1928
  "nextjs-app-router": FRONTEND_SCENARIOS,
1616
1929
  "react-vite": FRONTEND_SCENARIOS,
1617
1930
  "api-service": API_SCENARIOS,
1618
- "dotnet-webapi": DOTNET_SCENARIOS
1931
+ "dotnet-webapi": DOTNET_SCENARIOS,
1932
+ "unity-game": UNITY_GAME_SCENARIOS
1619
1933
  };
1620
1934
  function mergeScenarios(template, category) {
1621
1935
  const shared = SHARED_SCENARIOS[category] ?? [];
@@ -1835,12 +2149,96 @@ function apiConcepts() {
1835
2149
  - Schema versioning approach for event contracts
1836
2150
  `;
1837
2151
  }
2152
+ function unityConcepts() {
2153
+ return `## Scripting Architecture
2154
+
2155
+ *Document the code organization and scripting patterns once established.*
2156
+
2157
+ - MonoBehaviour vs plain C# class usage guidelines
2158
+ - Assembly definition (.asmdef) boundaries and dependencies
2159
+ - Component composition patterns
2160
+ - Singleton vs dependency injection approach
2161
+
2162
+ ## Asset Management
2163
+
2164
+ *Document how assets are organized and loaded.*
2165
+
2166
+ - Folder structure and naming conventions
2167
+ - Resource loading strategy (Resources, Addressables, AssetBundles)
2168
+ - Asset versioning and memory lifecycle
2169
+ - Prefab organization and instantiation patterns
2170
+
2171
+ ## Scene Management
2172
+
2173
+ *Document the scene structure and loading strategy.*
2174
+
2175
+ - Scene organization (main scenes, additive scenes, test scenes)
2176
+ - Scene loading patterns (async loading, transition effects)
2177
+ - DontDestroyOnLoad usage and persistent objects
2178
+ - Scene-to-scene data passing
2179
+
2180
+ ## Physics & Collision
2181
+
2182
+ *Document physics setup and collision detection.*
2183
+
2184
+ - Physics layers and collision matrix configuration
2185
+ - Rigidbody usage guidelines (kinematic vs dynamic)
2186
+ - Collision detection mode choices
2187
+ - Physics performance budget
2188
+
2189
+ ## Input Handling
2190
+
2191
+ *Document player input processing.*
2192
+
2193
+ - Input System package configuration and action maps
2194
+ - Input abstraction layer for platform-independent code
2195
+ - Rebinding and accessibility considerations
2196
+ - Mobile/touch input handling
2197
+
2198
+ ## Audio
2199
+
2200
+ *Document audio implementation.*
2201
+
2202
+ - AudioMixer group structure
2203
+ - Music vs SFX management and pooling
2204
+ - Spatial audio configuration
2205
+ - Volume control and persistence
2206
+
2207
+ ## Visual Effects & Animation
2208
+
2209
+ *Document visual effects and animation approach.*
2210
+
2211
+ - Particle system conventions
2212
+ - Shader usage and material management
2213
+ - Animator controller organization and state naming
2214
+ - Animation event and callback patterns
2215
+
2216
+ ## Object Pooling
2217
+
2218
+ *Document object pooling strategy.*
2219
+
2220
+ - Which objects are pooled (projectiles, effects, enemies)
2221
+ - Pool sizing and growth strategy
2222
+ - Return-to-pool lifecycle management
2223
+
2224
+ ## Save System
2225
+
2226
+ *Document the save/load approach.*
2227
+
2228
+ - Serialization format (JSON, binary, PlayerPrefs)
2229
+ - Save data structure and versioning
2230
+ - Auto-save and checkpoint strategy
2231
+ `;
2232
+ }
1838
2233
  function crosscuttingTemplate(input) {
1839
2234
  const isDotnet = input.template === "dotnet-webapi";
1840
2235
  const isFrontend = input.template === "nextjs-app-router" || input.template === "react-vite";
2236
+ const isUnity = input.template === "unity-game";
1841
2237
  let concepts;
1842
2238
  if (isDotnet) {
1843
2239
  concepts = dotnetConcepts();
2240
+ } else if (isUnity) {
2241
+ concepts = unityConcepts();
1844
2242
  } else if (isFrontend) {
1845
2243
  concepts = frontendConcepts();
1846
2244
  } else {
@@ -2843,12 +3241,197 @@ function phaseTasksTemplate4(_input, phaseId) {
2843
3241
  return tasksByPhase[phaseId] ?? null;
2844
3242
  }
2845
3243
 
3244
+ // src/templates/phases/unity-game.ts
3245
+ function phasePlanTemplate5(_input) {
3246
+ const phases = [
3247
+ {
3248
+ id: "phase-0-setup",
3249
+ name: "Project Setup",
3250
+ phase_number: 0,
3251
+ status: "in-progress",
3252
+ description: "Initialize Unity project structure, configure input system, core game loop, and assembly definitions",
3253
+ gate_requirements: [
3254
+ "Unity project opens and runs without errors",
3255
+ "Assembly definitions (.asmdef) created for each module",
3256
+ "Basic scene loads and game loop runs at target FPS",
3257
+ "Development tooling configured (version control, IDE, logging)"
3258
+ ]
3259
+ },
3260
+ {
3261
+ id: "phase-1-core",
3262
+ name: "Core Systems",
3263
+ phase_number: 1,
3264
+ status: "planned",
3265
+ description: "Player controller, camera system, game state machine, data architecture with ScriptableObjects",
3266
+ gate_requirements: [
3267
+ "Player input responds and controls character/object",
3268
+ "Camera system follows player correctly",
3269
+ "Game state machine handles transitions (menu, playing, paused)",
3270
+ "ScriptableObject data architecture established",
3271
+ "Quality scenarios PERF-01, MAINT-01 verified"
3272
+ ]
3273
+ },
3274
+ {
3275
+ id: "phase-2-gameplay",
3276
+ name: "Gameplay Features",
3277
+ phase_number: 2,
3278
+ status: "planned",
3279
+ description: "Core game mechanics, level design, UI framework, audio integration, save/load system",
3280
+ gate_requirements: [
3281
+ "Core gameplay loop complete and playable",
3282
+ "UI framework in place (HUD, menus, dialogs)",
3283
+ "Audio system integrated (music, SFX)",
3284
+ "Save/load system working",
3285
+ "Performance targets met on target platforms"
3286
+ ]
3287
+ },
3288
+ {
3289
+ id: "phase-3-polish",
3290
+ name: "Polish & Launch",
3291
+ phase_number: 3,
3292
+ status: "planned",
3293
+ description: "Performance profiling, accessibility, platform-specific builds, bug fixes, and release",
3294
+ gate_requirements: [
3295
+ "All quality scenarios passing",
3296
+ "Accessibility audit complete",
3297
+ "Platform-specific builds tested and optimized",
3298
+ "No critical or major bugs outstanding",
3299
+ "Release build successful"
3300
+ ]
3301
+ }
3302
+ ];
3303
+ return { schema_version: 1, phases };
3304
+ }
3305
+ function phaseTasksTemplate5(_input, phaseId) {
3306
+ const tasksByPhase = {
3307
+ "phase-0-setup": {
3308
+ schema_version: 1,
3309
+ phase_id: "phase-0-setup",
3310
+ tasks: [
3311
+ {
3312
+ id: "task-0.1-project-structure",
3313
+ title: "Set up Unity project folder structure and assembly definitions",
3314
+ status: "todo",
3315
+ building_block: "game-core",
3316
+ quality_scenarios: ["MAINT-01"],
3317
+ acceptance_criteria: [
3318
+ "Folder structure: Assets/Scripts/{Core,Input,Player,Gameplay,UI,Audio,Data}, Assets/Editor/",
3319
+ "Assembly definition (.asmdef) for each script folder",
3320
+ "Version control configured (.gitignore for Library/, Temp/, Logs/)"
3321
+ ]
3322
+ },
3323
+ {
3324
+ id: "task-0.2-core-loop",
3325
+ title: "Implement core game loop and GameManager",
3326
+ status: "todo",
3327
+ building_block: "game-core",
3328
+ quality_scenarios: ["PERF-01"],
3329
+ acceptance_criteria: [
3330
+ "GameManager handles game lifecycle (init, run, pause, quit)",
3331
+ "Main scene loads and runs at target frame rate",
3332
+ "Debug logging infrastructure in place"
3333
+ ]
3334
+ },
3335
+ {
3336
+ id: "task-0.3-input-system",
3337
+ title: "Configure Unity Input System",
3338
+ status: "todo",
3339
+ building_block: "input-system",
3340
+ quality_scenarios: [],
3341
+ acceptance_criteria: [
3342
+ "New Input System package installed and configured",
3343
+ "Input action asset with default action maps",
3344
+ "Input abstraction layer for platform-independent handling"
3345
+ ]
3346
+ },
3347
+ {
3348
+ id: "task-0.4-testing",
3349
+ title: "Set up testing infrastructure",
3350
+ status: "todo",
3351
+ quality_scenarios: ["MAINT-02"],
3352
+ acceptance_criteria: [
3353
+ "EditMode test assembly created (NUnit)",
3354
+ "PlayMode test assembly created",
3355
+ "Basic test for GameManager lifecycle"
3356
+ ]
3357
+ }
3358
+ ]
3359
+ },
3360
+ "phase-1-core": {
3361
+ schema_version: 1,
3362
+ phase_id: "phase-1-core",
3363
+ tasks: [
3364
+ {
3365
+ id: "task-1.1-player-controller",
3366
+ title: "Implement player controller and movement",
3367
+ status: "todo",
3368
+ building_block: "player-systems",
3369
+ quality_scenarios: ["PERF-06"],
3370
+ acceptance_criteria: [
3371
+ "Player character spawns and responds to input",
3372
+ "Movement feels responsive (< 100ms input-to-visual)",
3373
+ "Physics/collision configured correctly"
3374
+ ]
3375
+ },
3376
+ {
3377
+ id: "task-1.2-camera-system",
3378
+ title: "Implement camera system",
3379
+ status: "todo",
3380
+ building_block: "player-systems",
3381
+ quality_scenarios: [],
3382
+ acceptance_criteria: [
3383
+ "Camera follows player smoothly",
3384
+ "Camera handles transitions and edge cases",
3385
+ "Camera settings configurable via ScriptableObject"
3386
+ ]
3387
+ },
3388
+ {
3389
+ id: "task-1.3-data-architecture",
3390
+ title: "Set up ScriptableObject data architecture",
3391
+ status: "todo",
3392
+ building_block: "data-layer",
3393
+ quality_scenarios: [],
3394
+ acceptance_criteria: [
3395
+ "ScriptableObject base types for game config, events, and data",
3396
+ "Event channel pattern for decoupled communication",
3397
+ "Game settings accessible from ScriptableObject assets"
3398
+ ]
3399
+ },
3400
+ {
3401
+ id: "task-1.4-state-machine",
3402
+ title: "Implement game state machine",
3403
+ status: "todo",
3404
+ building_block: "game-core",
3405
+ quality_scenarios: [],
3406
+ acceptance_criteria: [
3407
+ "State machine handles: MainMenu, Loading, Playing, Paused, GameOver",
3408
+ "Clean transitions between states",
3409
+ "State-specific systems enabled/disabled correctly"
3410
+ ]
3411
+ },
3412
+ {
3413
+ id: "task-1.5-document-decisions",
3414
+ title: "Document architectural decisions as ADRs",
3415
+ status: "todo",
3416
+ quality_scenarios: [],
3417
+ acceptance_criteria: [
3418
+ "ADR for each significant architecture/pattern choice",
3419
+ "ADRs linked to affected building blocks and code paths"
3420
+ ]
3421
+ }
3422
+ ]
3423
+ }
3424
+ };
3425
+ return tasksByPhase[phaseId] ?? null;
3426
+ }
3427
+
2846
3428
  // src/generators/plan-generator.ts
2847
3429
  var planTemplates = {
2848
3430
  "nextjs-app-router": { plan: phasePlanTemplate, tasks: phaseTasksTemplate },
2849
3431
  "react-vite": { plan: phasePlanTemplate2, tasks: phaseTasksTemplate2 },
2850
3432
  "api-service": { plan: phasePlanTemplate3, tasks: phaseTasksTemplate3 },
2851
- "dotnet-webapi": { plan: phasePlanTemplate4, tasks: phaseTasksTemplate4 }
3433
+ "dotnet-webapi": { plan: phasePlanTemplate4, tasks: phaseTasksTemplate4 },
3434
+ "unity-game": { plan: phasePlanTemplate5, tasks: phaseTasksTemplate5 }
2852
3435
  };
2853
3436
  function generatePlan(targetDir, input) {
2854
3437
  const planDir = join5(targetDir, ".arcbridge", "plan");
@@ -3492,7 +4075,7 @@ You cannot see screenshots, but you CAN reason about UI quality through code:
3492
4075
  }
3493
4076
 
3494
4077
  // src/generators/agent-generator.ts
3495
- var UI_TEMPLATES = /* @__PURE__ */ new Set(["nextjs-app-router", "react-vite"]);
4078
+ var UI_TEMPLATES = /* @__PURE__ */ new Set(["nextjs-app-router", "react-vite", "unity-game"]);
3496
4079
  function writeAgentRole(dir, role) {
3497
4080
  const { system_prompt, ...frontmatter } = role;
3498
4081
  const content = matter2.stringify(system_prompt, frontmatter);
@@ -5957,9 +6540,23 @@ async function indexCSharpTreeSitter(db, options) {
5957
6540
  await ensureCSharpParser();
5958
6541
  const service = options.service ?? "main";
5959
6542
  const projectRoot = options.projectRoot;
6543
+ const ignorePatterns = [
6544
+ "**/bin/**",
6545
+ "**/obj/**",
6546
+ "**/node_modules/**",
6547
+ "**/.git/**",
6548
+ // Unity root-level directories (anchored to avoid matching nested folders
6549
+ // like src/Library/ or src/Packages/ in non-Unity .NET projects)
6550
+ "Library/**",
6551
+ "Temp/**",
6552
+ "Logs/**",
6553
+ "UserSettings/**",
6554
+ "Packages/**",
6555
+ "ProjectSettings/**"
6556
+ ];
5960
6557
  const csFiles = globbySync("**/*.cs", {
5961
6558
  cwd: projectRoot,
5962
- ignore: ["**/bin/**", "**/obj/**", "**/node_modules/**", "**/.git/**"],
6559
+ ignore: ignorePatterns,
5963
6560
  absolute: false
5964
6561
  });
5965
6562
  const existingHashes = getExistingHashes(db, service);
@@ -6154,6 +6751,9 @@ function loadConfig(projectRoot) {
6154
6751
 
6155
6752
  // src/indexer/index.ts
6156
6753
  function detectProjectLanguage(projectRoot) {
6754
+ if (existsSync7(join14(projectRoot, "ProjectSettings")) && existsSync7(join14(projectRoot, "Assets"))) {
6755
+ return "csharp";
6756
+ }
6157
6757
  if (existsSync7(join14(projectRoot, "tsconfig.json"))) return "typescript";
6158
6758
  if (existsSync7(join14(projectRoot, "package.json"))) return "typescript";
6159
6759
  if (findDotnetProject(projectRoot)) return "csharp";
@@ -6296,6 +6896,17 @@ var FRAMEWORK_IGNORES = {
6296
6896
  "Properties/",
6297
6897
  "Migrations/",
6298
6898
  "wwwroot/"
6899
+ ],
6900
+ "unity-game": [
6901
+ "Library/",
6902
+ "Temp/",
6903
+ "Logs/",
6904
+ "UserSettings/",
6905
+ "Packages/",
6906
+ "ProjectSettings/",
6907
+ "Assets/Plugins/",
6908
+ "obj/",
6909
+ "bin/"
6299
6910
  ]
6300
6911
  };
6301
6912
  function detectDrift(db, options) {