diff --git a/AGENTS.md b/AGENTS.md index c9447359a2..45301ec4a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,12 +18,19 @@ Directory-level responsibilities. Kept deliberately coarse — check the directo - `cli/common/` — Go modules shared by dispatcher and project runner. Tool parameter schemas live in `cli/common/tools/default-tools.json`; skill discovery in `cli/common/skillscan/`. - `cli/release-automation/` — Go logic backing GitHub Actions release/CI workflows. - `tools/UnityCliLoop.DeadCodeScanner/` — the C# dead-code scanner described below. +- `docs/` — reference docs for the rules in this file. `docs/adr/` holds architecture decision records: read the relevant one before reopening a settled design question, and note its stated reversal condition rather than relitigating from scratch. - `dist/` — locally built development binaries (`dist/darwin-arm64/uloop`, etc.); never committed. - `.claude/`, `.agents/` — generated skill copies; never edit directly (see Generated Skill Files). - `.uloop/` — runtime state and command outputs (screenshots, test results, hierarchy dumps). Do not rename public package, assembly, or extension API identifiers as part of cleanup-only changes. +Use the terms in `docs/glossary.md` with the meanings defined there — in code identifiers, docs, +commit messages, and reviews alike. Tool, internal bridge command, server, dispatcher, project +runner, pin, protocol version, skill, and pause point all have exact meanings there. When an +internal identifier conflicts with the glossary, rename the identifier; when a public one does, +keep it and record the mismatch in the glossary instead. + Comments in the code, commit messages, PR titles, and PR descriptions must all be written in English. Every test method must have a short comment that states what behavior the test verifies. @@ -62,6 +69,11 @@ These files are generated copies. Update the source skill definitions instead, t Write GitHub Actions and release automation logic in Go when it needs JSON parsing, workflow polling, state transitions, or non-trivial branching. Shell scripts are acceptable only as thin wrappers or simple command sequences. +Remote actions in workflow files must be pinned to full 40-character commit SHAs — version tags +such as `actions/checkout@v6` are rejected by CI. Before adding or updating any `uses:` ref, read +`docs/github-actions-security.md` (SHA resolution for nested action paths, the `setup-go` cache +ban on pull-request workflows, and the Unity license guard on cache steps). + ## Shared Release Inputs and Triggers All three components release through release-please; `dispatcherVersion` and component @@ -72,6 +84,15 @@ inputs outside the package roots (non-test `cli/common/**` sources, `scripts/ins run in the same PR; CI (`check-release-triggers`) fails otherwise. Rules and rationale: `docs/shared-release-inputs.md`. +## Broken CLI Releases + +When a native CLI release has a tag commit that differs from the `sourceRepositoryDigest` in its +asset attestations, the dispatcher refuses to download it. Roll forward to the next version — +never retag, rerun, or otherwise revive the broken one; a new run can only attest its own head +commit. Diagnosis commands, the narrow conditions under which rerunning *is* valid, and the +deliberately preserved mismatch specimen (`uloop-project-runner-v3.0.0-beta.48`, which must not +be deleted): `docs/release-recovery-runbook.md`. + ## Windows Compatibility Guardrails Most day-to-day development happens on macOS, but this project must keep working on Windows. @@ -87,6 +108,14 @@ apparently unreferenced type must stay, run the scanner and interpret its output as described in `docs/dead-code-scanner.md` (commands, and what `KeptByUnityOrReflection` / `PublicCandidate` do and do not prove). +## Code Complexity + +The repository-wide maximum cyclomatic complexity is 15, enforced by `cyclop` for Go and CA1502 +for C#. The `Code Complexity` workflow reports findings but never fails the build, so a finding +only does its job if someone acts on it: when you touch a reported function, reduce its +complexity before adding behavior. Commands and the two places the threshold is declared: +`docs/code-complexity.md`. + ## Native Go CLI Validation When running `uloop` commands for this project during CLI development, do not use the `uloop` diff --git a/docs/architecture/execute-dynamic-code-rebuild.md b/docs/architecture/execute-dynamic-code-rebuild.md deleted file mode 100644 index 388d4cc6ce..0000000000 --- a/docs/architecture/execute-dynamic-code-rebuild.md +++ /dev/null @@ -1,286 +0,0 @@ -# execute-dynamic-code rebuild - -This document describes the rebuilt `execute-dynamic-code` pipeline after the layering refactor. - -## Layered overview - -```mermaid -flowchart TD - subgraph Entry["Entry layer"] - Tool["ExecuteDynamicCodeTool"] - Server["UnityCliLoopServerController"] - end - - subgraph UseCase["UseCase layer"] - ExecuteUseCase["IExecuteDynamicCodeUseCase / ExecuteDynamicCodeUseCase"] - PrewarmUseCase["IPrewarmDynamicCodeUseCase / PrewarmDynamicCodeUseCase"] - end - - subgraph Infrastructure["Infrastructure layer"] - subgraph RuntimeAccess["Runtime access module"] - RuntimeContract["IDynamicCodeExecutionRuntime"] - RuntimeFacade["DynamicCodeExecutionFacade"] - ExecutorPoolContract["IDynamicCodeExecutorPool"] - ExecutorPool["DynamicCodeExecutorPool"] - Provider["RegistryDynamicCodeExecutorFactory"] - end - - subgraph Invocation["Invocation module"] - ExecutorContract["IDynamicCodeExecutor"] - Executor["DynamicCodeExecutor"] - InvokerContract["ICompiledCommandInvoker"] - Runner["CommandRunner"] - EntryResolver["CompiledCommandEntryPointResolver"] - end - - subgraph CompilationPipeline["Compilation pipeline module"] - CompilerContract["IDynamicCompilationService"] - Compiler["DynamicCodeCompiler"] - end - - subgraph Planning["Planning module"] - PlannerContract["IDynamicCompilationPlanner"] - Planner["DynamicCompilationPlanner"] - Plan["DynamicCompilationPlan"] - SourcePrepSvc["DynamicCodeSourcePreparationService"] - SourcePrep["DynamicCodeSourcePreparer"] - end - - subgraph BackendBuild["Backend build module"] - BuilderContract["ICompiledAssemblyBuilder"] - Builder["CompiledAssemblyBuilder"] - RefSvc["DynamicReferenceSetBuilderService"] - RefBuilder["DynamicReferenceSetBuilder"] - AutoUsing["PreUsingResolver / AutoUsingResolver / AssemblyTypeIndex"] - Diagnostics["CompilerDiagnostics"] - Backend["DynamicCompilationBackend"] - PathSvc["ExternalCompilerPathResolutionService"] - PathResolver["ExternalCompilerPathResolver"] - Roslyn["RoslynCompilerBackend"] - Worker["SharedRoslynCompilerWorkerHost"] - Fallback["AssemblyBuilderFallbackCompilerBackend"] - end - - subgraph SafetyLoad["Safety + load module"] - LoadContract["ICompiledAssemblyLoader"] - LoadSvc["CompiledAssemblyLoadService"] - Loader["CompiledAssemblyLoader"] - Cache["CompilationCacheManager"] - Timing["DynamicCompilationTimingFormatter"] - end - end - - Tool --> ExecuteUseCase - Server --> PrewarmUseCase - - ExecuteUseCase --> RuntimeContract - PrewarmUseCase --> RuntimeContract - RuntimeContract --> RuntimeFacade - - RuntimeFacade --> ExecutorPoolContract - RuntimeFacade --> BuilderContract - ExecutorPoolContract --> ExecutorPool - ExecutorPool --> Provider - Provider --> ExecutorContract - ExecutorContract --> Executor - Executor --> CompilerContract - CompilerContract --> Compiler - Executor --> InvokerContract - InvokerContract --> Runner - Runner --> EntryResolver - - Compiler --> PlannerContract - PlannerContract --> Planner - Planner --> Plan - Planner --> SourcePrepSvc - Compiler --> BuilderContract - BuilderContract --> Builder - Compiler --> LoadContract - LoadContract --> LoadSvc - Compiler --> Cache - Compiler --> Timing - - SourcePrepSvc --> SourcePrep - RefSvc --> RefBuilder - RefBuilder --> AutoUsing - LoadSvc --> Loader - Backend --> PathSvc - Backend --> Roslyn - Backend --> Fallback - PathSvc --> PathResolver - Roslyn --> Worker -``` - -## Composition graph - -```mermaid -flowchart TD - Services["DynamicCodeServices"] - SourcePrepSvc["DynamicCodeSourcePreparationService"] - PathSvc["ExternalCompilerPathResolutionService"] - Planner["IDynamicCompilationPlanner / DynamicCompilationPlanner"] - Builder["ICompiledAssemblyBuilder / CompiledAssemblyBuilder"] - LoadSvc["ICompiledAssemblyLoader / CompiledAssemblyLoadService"] - Backend["DynamicCompilationBackend"] - EntryResolver["CompiledCommandEntryPointResolver"] - Provider["RegistryDynamicCodeExecutorFactory"] - ExecutorPool["IDynamicCodeExecutorPool / DynamicCodeExecutorPool"] - RuntimeFacade["DynamicCodeExecutionFacade"] - ExecuteUseCase["ExecuteDynamicCodeUseCase"] - PrewarmUseCase["PrewarmDynamicCodeUseCase"] - - Services --> SourcePrepSvc - Services --> PathSvc - Services --> Planner - Services --> Builder - Services --> LoadSvc - Services --> Backend - Services --> EntryResolver - Services --> Provider - Services --> ExecutorPool - Services --> RuntimeFacade - Services --> ExecuteUseCase - Services --> PrewarmUseCase - - Provider --> SourcePrepSvc - Provider --> EntryResolver - ExecutorPool --> Provider - RuntimeFacade --> ExecutorPool - RuntimeFacade --> Builder - ExecuteUseCase --> RuntimeFacade - PrewarmUseCase --> RuntimeFacade -``` - -## Reading guide - -1. Start with `Entry layer`. - - `ExecuteDynamicCodeTool` only delegates the tool workflow. - - `UnityCliLoopServerController` only requests warm-up after server start and recovery. -2. Move to `UseCase layer`. - - `ExecuteDynamicCodeUseCase` owns the user-facing workflow for execute-dynamic-code. - - `PrewarmDynamicCodeUseCase` owns the warm-up workflow. -3. Only then read `Infrastructure layer`. - - `Runtime access module` is the only runtime-facing gateway. - - `Planning`, `Backend build`, `Safety + load`, and `Invocation` split the heavy mechanics into named modules. -4. Read `Composition graph` last. - - `DynamicCodeServices` is the only place that is expected to know many concrete classes at once. - - If a concrete-to-concrete edge only appears there, it is a wiring edge rather than a runtime dependency. - -## Layer responsibilities - -- `Entry layer` - - Translate external calls into use-case invocations. - - Avoid business workflow logic. - - Avoid reaching into executor or compiler wiring directly. - -- `UseCase layer` - - Own temporal cohesion. - - Decide the workflow order for the feature. - - Keep user-facing retry rules such as the missing-`return` retry in one place. - - Depend on runtime contracts instead of concrete infrastructure types. - -- `Infrastructure layer` - - Own the mechanics of execution, compilation, loading, caching, path discovery, and worker lifecycle. - - Keep low-level concerns isolated behind contracts and focused service classes. - -## Infrastructure module boundaries - -- `Runtime access module` - - Exposes `IDynamicCodeExecutionRuntime` to the use-case layer. - - Reuses a single executor through `IDynamicCodeExecutorPool`. - - Queries warm-up capability through the build facade instead of reaching into path resolution directly. - -- `Planning module` - - Turns `CompilationRequest` into `DynamicCompilationPlan`. - - Keeps wrapper generation and literal hoisting together. - - Prevents `DynamicCodeCompiler` from knowing preparation details. - -- `Backend build module` - - Takes a plan and produces `CompiledAssemblyBuildResult`. - - Owns reference resolution, auto-using retry, backend selection, temp artifact handling, and build timings. - - Hides Roslyn worker details from the compiler orchestration. - -- `Safety + load module` - - Loads DLL bytes only after build success. - - Keeps `Assembly.Load` isolated behind a focused loader service. - - Prevents backend code from depending on assembly-load mechanics. - -- `Invocation module` - - Executes the compiled wrapper method through `ICompiledCommandInvoker`. - - Keeps reflection-heavy entry-point resolution behind a focused facade. - - Lets `DynamicCodeExecutor` stay a thin bridge between compile and invoke. - -## Class responsibilities - -- `ExecuteDynamicCodeTool` - - Thin entry point for the CLI tool. - - Delegates the full workflow to `IExecuteDynamicCodeUseCase`. - -- `ExecuteDynamicCodeUseCase` - - Converts parameters into the runtime request. - - Performs the missing-`return` retry. - - Shapes `ExecutionResult` into `ExecuteDynamicCodeResponse`. - -- `PrewarmDynamicCodeUseCase` - - Owns the single-flight warm-up flow. - - Reuses the same runtime contract as the real execution path. - -- `IDynamicCodeExecutionRuntime` - - Contract between use cases and runtime infrastructure. - - Keeps use cases from depending on factory and executor wiring directly. - -- `DynamicCodeExecutionFacade` - - Reuses executors through `IDynamicCodeExecutorPool`. - - Checks warm-up capability through `ICompiledAssemblyBuilder`. - - Hides provider, pool, and build-capability wiring from use cases. - -- `DynamicCodeExecutorPool` - - Owns executor reuse and disposal for the runtime access path. - - Keeps that caching concern out of the runtime facade itself. - -- `RegistryDynamicCodeExecutorFactory` - - Builds `DynamicCodeExecutor` and `CommandRunner` from registered compiler services. - - Lives in the composition graph and runtime infrastructure, not in the entry layer. - -- `DynamicCodeExecutor` - - Bridges compilation and execution. - - Merges timing information. - - Converts hoisted literals into execution parameters. - -- `DynamicCodeCompiler` - - Orchestrates cache lookup, source security, planning, build, and assembly load. - - Depends on module facades instead of low-level helpers directly. - -- `DynamicCompilationPlanner` - - Produces the normalized `DynamicCompilationPlan`. - - Keeps request normalization and source preparation together. - -- `CompiledAssemblyBuilder` - - Builds the assembly bytes from a plan. - - Owns the auto-using retry loop and ambiguity rollback. - -- `DynamicCodeSourcePreparationService` / `DynamicCodeSourcePreparer` - - Normalize snippets into wrapper code. - - Handle top-level mode, return completion, and literal hoisting. - -- `DynamicCompilationBackend` - - Chooses between the Roslyn path and the AssemblyBuilder fallback path inside the build module. - -- `RoslynCompilerBackend` / `SharedRoslynCompilerWorkerHost` - - Provide the fast path with the shared external worker. - -- `CompiledAssemblyLoadService` / `CompiledAssemblyLoader` - - Keep metadata validation, assembly loading, and IL validation together. - -- `CommandRunner` / `CompiledCommandEntryPointResolver` - - Execute the compiled wrapper method while hiding reflection-heavy lookup. - - Form the `Invocation` facade seen by `DynamicCodeExecutor`. - -## Design intent - -- Make the architecture readable as `Entry -> UseCase -> Infrastructure`. -- Keep the runtime dependency chain narrower than the composition graph. -- Allow the composition root to know concrete classes, while runtime layers depend on contracts or use cases. -- Keep the `Infrastructure` layer readable as a set of named module facades instead of one large helper cluster. -- Keep the async-only contracts honest. -- Keep performance work in infrastructure without leaking that complexity into the entry layer. diff --git a/docs/architecture/execute-dynamic-code-windows-handoff.md b/docs/architecture/execute-dynamic-code-windows-handoff.md deleted file mode 100644 index eb665ca3cd..0000000000 --- a/docs/architecture/execute-dynamic-code-windows-handoff.md +++ /dev/null @@ -1,182 +0,0 @@ -# execute-dynamic-code Windows handoff - -This note is for resuming the `execute-dynamic-code` rebuild on a Windows machine. - -## Branch - -- Work on `codex/rebuild-execute-dynamic-code` -- Do not switch back to the historical reference branch unless you need to compare behavior - -## What changed already - -The rebuild has already moved to a layered shape: - -- `Entry` - - `ExecuteDynamicCodeTool` - - `UnityCliLoopServerController` -- `UseCase` - - `ExecuteDynamicCodeUseCase` - - `PrewarmDynamicCodeUseCase` -- `Infrastructure` - - `Runtime access` - - `Invocation` - - `Compilation pipeline` - - `Planning` - - `Backend build` - - `Safety + load` - -The key design rule is: - -- Entry knows only use cases -- Use cases know only `IDynamicCodeExecutionRuntime` -- Infrastructure internals are split behind module-level facades - -## Read this first - -Start with these files in order: - -1. `docs/architecture/execute-dynamic-code-rebuild.md` -2. `Packages/src/Editor/FirstPartyTools/ExecuteDynamicCode/ExecuteDynamicCodeTool.cs` -3. `Packages/src/Editor/Application/Api/Tools/UseCases/Tools/ExecuteDynamicCodeUseCase.cs` -4. `Packages/src/Editor/Application/Execution/DynamicCodeExecutionFacade.cs` -5. `Packages/src/Editor/Infrastructure/DynamicCompilation/DynamicCodeCompiler.cs` -6. `Packages/src/Editor/Infrastructure/DynamicCompilation/CompiledAssemblyBuilder.cs` - -## Important module facades - -- Runtime access - - `IDynamicCodeExecutionRuntime` - - `IDynamicCodeExecutorPool` -- Invocation - - `ICompiledCommandInvoker` -- Compilation pipeline - - `IDynamicCompilationService` -- Planning - - `IDynamicCompilationPlanner` -- Backend build - - `ICompiledAssemblyBuilder` -- Safety + load - - `ICompiledAssemblyLoader` - -## Current Windows expectation - -Windows is the biggest remaining unknown. - -Expected behavior from the current code: - -- Shared Roslyn worker is intentionally disabled on `RuntimePlatform.WindowsEditor` -- One-shot Roslyn compile may still work if Unity ships the expected `dotnet.exe` and `DotNetSdkRoslyn` layout -- If Unity's bundled Roslyn files cannot be resolved, the build should fall back to `AssemblyBuilder` - -This means: - -- Functionality may still work on Windows -- Performance may be slower than macOS -- Fast-path failures should now be visible immediately - -## Fast-path failure visibility - -If the ideal Roslyn path is not available, the code now emits both: - -- `VibeLogger.LogError` -- `Debug.LogError` - -Look for messages related to: - -- `dynamic_code_fast_path_unavailable` -- `dynamic_code_shared_worker_fallback` -- `dynamic_code_shared_worker_failure` -- `dynamic_code_one_shot_compiler_start_failure` - -Relevant files: - -- `Packages/src/Editor/Application/Compilation/DynamicCompilationHealthMonitor.cs` -- `Packages/src/Editor/Infrastructure/DynamicCompilation/ExternalCompilerPathResolver.cs` -- `Packages/src/Editor/Infrastructure/DynamicCompilation/RoslynCompilerBackend.cs` -- `Packages/src/Editor/Infrastructure/DynamicCompilation/SharedRoslynCompilerWorkerHost.cs` - -## Windows validation checklist - -Run these in order on Windows: - -1. `uloop compile` -2. `uloop run-tests --test-mode EditMode --filter-type regex --filter-value 'io.github.hatayama.UnityCliLoop.DynamicCodeToolTests'` -3. `uloop execute-dynamic-code --code "return 1 + 2;"` -4. `uloop execute-dynamic-code --code "StringBuilder sb = new StringBuilder(); sb.Append(\"ok\"); return sb.ToString();"` -5. `uloop execute-dynamic-code --code "UnityEngine.GameObject go = new UnityEngine.GameObject(\"bench\"); UnityEngine.Object.DestroyImmediate(go); return \"ok\";"` - -Then inspect the Unity Console for: - -- compile errors -- fallback error logs -- worker failure logs - -## How to interpret results - -- If all commands succeed and no fast-path error logs appear: - - Windows one-shot Roslyn path is probably healthy -- If commands succeed but `dynamic_code_fast_path_unavailable` appears: - - Windows is running through the `AssemblyBuilder` fallback -- If commands fail and `dynamic_code_one_shot_compiler_start_failure` appears: - - Unity's bundled `dotnet.exe` or `csc.dll` assumptions are wrong on Windows -- If commands fail and `dynamic_code_shared_worker_failure` appears: - - The worker path unexpectedly activated or broke before fallback completed - -## Likely next steps on Windows - -If Windows is broken, investigate in this order: - -1. `ExternalCompilerPathResolver` - - Are `NetCoreRuntime/dotnet.exe` and `DotNetSdkRoslyn/*` really present? -2. `RoslynCompilerBackend` - - Does the one-shot `dotnet csc.dll` process launch? -3. `AssemblyBuilderFallbackCompilerBackend` - - If Roslyn fast path is unavailable, does fallback still produce a valid DLL? -4. `SharedRoslynCompilerWorkerHost` - - Do not enable this on Windows until lifecycle, pipes, and file-lock behavior are proven stable - -## Current quality bar before changing more code - -Do not optimize Windows first. First make sure: - -- basic execution works -- diagnostics are visible -- fallback behavior is understandable -- the current tests stay green - -Only after that should Windows-specific performance work start. - -## Paste this into Windows Codex - -Use this prompt as the starting message on Windows: - -```text -Please resume work on branch `codex/rebuild-execute-dynamic-code`. - -First read: -- docs/architecture/execute-dynamic-code-rebuild.md -- docs/architecture/execute-dynamic-code-windows-handoff.md - -Important recent commits: -- 583cde7e Log dynamic compile fast-path failures for Windows handoff -- 893f42f2 Route prewarm capability through build facade -- 0889d2c6 Split dynamic code infrastructure into module facades - -Goal: -- Validate execute-dynamic-code on Windows -- Confirm whether the fast Roslyn path, one-shot Roslyn path, or AssemblyBuilder fallback is being used -- If the ideal path is not active, inspect Unity Console error logs and fix the cause - -Suggested validation commands: -1. uloop compile -2. uloop run-tests --test-mode EditMode --filter-type regex --filter-value 'io.github.hatayama.UnityCliLoop.DynamicCodeToolTests' -3. uloop execute-dynamic-code --code "return 1 + 2;" -4. uloop execute-dynamic-code --code "StringBuilder builder1002 = new StringBuilder(); builder1002.Append(\"ok-1002\"); return builder1002.ToString();" -5. uloop execute-dynamic-code --code "DynamicAssemblyTest test1004 = new DynamicAssemblyTest(); return test1004.HelloWorld();" - -Watch the Unity Console for: -- dynamic_code_fast_path_unavailable -- dynamic_code_shared_worker_fallback -- dynamic_code_shared_worker_failure -- dynamic_code_one_shot_compiler_start_failure -``` diff --git a/docs/architecture/native-cli-simplification-plan.md b/docs/architecture/native-cli-simplification-plan.md deleted file mode 100644 index dbe145b916..0000000000 --- a/docs/architecture/native-cli-simplification-plan.md +++ /dev/null @@ -1,74 +0,0 @@ -# Native CLI Simplification Plan - -## 背景 - -`cli` は小さな Go CLI アプリケーションです。以前の構成は Clean Architecture の語彙に寄せて `presentation`、`application`、`ports`、`adapters` に分かれていましたが、CLI の規模に対して抽象化が強くなっていました。 - -この整理では、Clean Architecture の層名を守ることよりも、CLI として実際に何をしているかが読み取りやすい構成を優先します。ただし SOLID、デメテルの法則、凝集度は維持し、特に機能的凝集を優先します。 - -## 現状の違和感 - -旧 `internal/presentation` は、実質的には CLI の入出力層でした。ここには引数解釈、help、completion、stdout/stderr、tool list、skills、update、Unity RPC 実行の入口がまとまっていました。 - -このまとまり自体は間違いではありませんが、`presentation` という名前だけでは terminal CLI の責務が伝わりづらく、さらに `tools` や `update` など独立した機能も同じ package に混ざっていました。 - -また、`internal/application/tool_dispatcher.go` と `internal/ports/unity_bridge.go` は、抽象化のための抽象化に近い状態でした。Unity 以外の送信先があるわけではないため、最初から port/interface を置くより、実際の痛みが出てから抽象化する方がシンプルです。 - -## 目指す構成 - -ゼロから設計するなら、抽象レイヤー名ではなく機能名で分けます。 - -```text -cli -├── cmd/uloop/ -├── internal/ -│ ├── cli/ # args, help, completion, stdout/stderr, command routing -│ ├── unityipc/ # connection, framing, Unity RPC client -│ ├── project/ # project root, cache path, Unity project discovery -│ ├── skills/ # CLI-only skill sources and skill file-layout knowledge -│ ├── update/ # self update, installer URL, release tag selection -│ ├── tools/ # default-tools.json, tool list/cache DTO and loading -│ └── version/ # semver compare -├── contract.json # CLI version contract exposed by root package -└── dist/ # ignored local build and release output -``` - -この構成では、読み手は「CLI の入力処理」「Unity との IPC」「tool catalog」「update 処理」のように、実際の機能単位でコードを探せます。 - -## 段階的な進め方 - -一気に全部を動かすのではなく、小さい commit に分けて進めます。 - -1. `Core~`、`Dispatcher~`、`Shared~` に分かれていた Go modules を `cli` に統合する。 -2. `internal/presentation` を `internal/cli` に rename する。 -3. `internal/application` と `internal/ports` を削除し、`cli` から `unityipc.Client` を直接呼ぶ。 -4. `adapters/unity` と `adapters/framing` を `internal/unityipc` に寄せる。 -5. `adapters/project` を `internal/project` に寄せる。 -6. `default-tools.json` と tool catalog/cache DTO を `internal/tools` へ移す。 -7. CLI-only skill source path を `internal/skills` 配下へ移し、CLI が直接 file layout を持たないようにする。 -8. update installer URL と release tag 選択を `internal/update` に寄せる。 - -## やらないこと - -この整理では、大きな設計変更や互換性維持用の抽象化は追加しません。 - -- Unity 以外の backend を想定した interface は先に作らない。 -- HTTP/TUI など、存在しない presentation surface を想定した階層は作らない。 -- pure value transform だけの小さな処理を無理に service 化しない。 -- public command の挙動や出力形式は変えない。 -- package 間の情報の受け渡しでは、できるだけ意味のある DTO を使い、生成後に書き換えない前提で扱う。 - -## 検証方針 - -各ステップでは、少なくとも次を確認します。 - -```bash -scripts/check-go-cli.sh -dist/darwin-arm64/uloop compile --wait-for-domain-reload -``` - -skill discovery や CLI-only skill source path を動かした場合は、`ToolSkillSynchronizerTests` の targeted EditMode test も実行します。 - -```bash -dist/darwin-arm64/uloop run-tests --test-mode EditMode --filter-type regex --filter-value ToolSkillSynchronizerTests -``` diff --git a/docs/architecture/unity-cli-loop-onion-refactor-plan.md b/docs/architecture/unity-cli-loop-onion-refactor-plan.md deleted file mode 100644 index 161a7df654..0000000000 --- a/docs/architecture/unity-cli-loop-onion-refactor-plan.md +++ /dev/null @@ -1,244 +0,0 @@ -# UnityCLILoop C# Onion Architecture Refactor Plan - -## Summary - -- Work from `refactor/unity-cli-loop-onion-architecture`, created from `origin/v3-beta`. -- Treat the UnityCLILoop domain as the platform that safely hosts and executes Unity operation tools, not as the individual Unity operations themselves. -- Treat `Compile`, `GetLogs`, and `ExecuteDynamicCode` as first-party tool plugins that use the same contract, registration path, and execution path as third-party tools. -- Treat each tool implementation as an outer plugin in the Onion Architecture. -- Tool implementations depend on `UnityCLILoop.ToolContracts`, which is the inward contract defined by the platform. -- Keep the Figma diagram as the visual reference: https://www.figma.com/board/ThcM67cR9MdNRQpQgeVnvi?utm_source=codex&utm_content=edit_in_figjam&oai_id=&request_id=7ebbf16a-1ed2-4c82-9f17-9cf8201373d7 - -## Implemented Slice - -- Added `UnityCLILoop.ToolContracts` as the public tool contract assembly. -- Moved the public extension API into `ToolContracts`: - - `IUnityCliLoopTool` - - `UnityCliLoopTool` - - `UnityCliLoopToolSchema` - - `UnityCliLoopToolResponse` - - `UnityCliLoopToolAttribute` - - `UnityCliLoopSecuritySetting` - - `UnityCliLoopToolParameterValidationException` -- Renamed the main editor assembly to `UnityCLILoop.Application`. -- Added onion boundary asmdefs for the intended final shape: - - `UnityCLILoop.Domain` - - `UnityCLILoop.Presentation` - - `UnityCLILoop.Infrastructure` - - `UnityCLILoop.CompositionRoot.Editor` - - `UnityCLILoop.FirstPartyTools.Editor` -- Removed manual built-in tool registration from `UnityCliLoopToolRegistry`. -- Registered bundled tools and extension tools through the same `[UnityCliLoopTool]` attribute discovery path. -- Split `Assets/Editor/CustomCommandSamples` into `UnityCLILoop.CustomCommandSamples.Editor`, which references only `UnityCLILoop.ToolContracts`. -- Moved `get-version` out of the extension-facing tool registry and kept it as an internal bridge command for CLI readiness and diagnostics. -- Moved `get-tool-details` out of the extension-facing tool registry and kept it as an internal bridge command for CLI list/sync catalog access. -- Removed `focus-window` from the Unity-side tool registry because it is implemented as a native Go CLI command. -- Removed legacy MCP-era development tools from the runtime registry: - - `ping` - - `debug-sleep` -- Moved `control-play-mode` into `UnityCLILoop.FirstPartyTools.Editor` as the first bundled tool plugin that references only `UnityCLILoop.ToolContracts`. -- Moved `get-logs` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives Unity Console access through a `ToolContracts` host-service contract. -- Moved `clear-console` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives Unity Console mutation access through a `ToolContracts` host-service contract. -- Moved `compile` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives Unity compilation access through a `ToolContracts` host-service contract. -- Moved `execute-dynamic-code` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives dynamic-code execution access through a `ToolContracts` host-service contract. -- Moved `get-hierarchy` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives hierarchy export access through a `ToolContracts` host-service contract. -- Moved `run-tests` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives Unity Test Runner access through a `ToolContracts` host-service contract. -- Moved `find-game-objects` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives GameObject search access through a `ToolContracts` host-service contract. -- Moved `screenshot` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives Unity window and GameView capture access through a `ToolContracts` host-service contract. -- Moved `record-input` and `replay-input` into `UnityCLILoop.FirstPartyTools.Editor` as bundled tool plugins that receive input recording and replay access through `ToolContracts` host-service contracts. -- Moved `simulate-keyboard` and `simulate-mouse-input` into `UnityCLILoop.FirstPartyTools.Editor` as bundled tool plugins that receive input simulation access through `ToolContracts` host-service contracts. -- Moved `simulate-mouse-ui` into `UnityCLILoop.FirstPartyTools.Editor` as a bundled tool plugin that receives EventSystem mouse simulation access through a `ToolContracts` host-service contract. -- Moved `execute-dynamic-code` schema and response DTOs into `UnityCLILoop.ToolContracts` because both the bundled tool and the application-side execution pipeline shape those values. -- Moved concrete tool host-service wiring into `UnityCLILoop.CompositionRoot.Editor`; `UnityCliLoopToolRegistry` now asks an application-side provider for registered host services instead of constructing them directly. -- Moved concrete dynamic-code compilation service factory and runtime-service factory into `UnityCLILoop.Infrastructure`; `UnityCLILoop.CompositionRoot.Editor` still owns registration, while Infrastructure owns the concrete compiler creation. -- Moved Unity Console clear host-service implementation into `UnityCLILoop.Infrastructure`; `clear-console` receives the capability through `ToolContracts` and the composition root wires the concrete adapter. -- Moved project-root identity matching into `UnityCLILoop.Domain` as a platform safety rule; JSON-RPC request validation now delegates to the domain rule and only converts failures into tool parameter errors. -- Moved project-root canonicalization into `UnityCLILoop.Domain` so Application code can validate project identity without depending on project IPC transport types. -- Moved CLI version ordering into `UnityCLILoop.Domain` because dispatcher compatibility checks are pure platform rules with no Unity Editor, file-system, or protocol dependency. -- Moved compilation diagnostic message parsing into `UnityCLILoop.Domain` because it is a pure diagnostic normalization rule with no Unity Editor, file-system, or protocol dependency. -- Moved dynamic-code default namespace and class-name constants into `UnityCLILoop.Domain` because they are platform defaults shared by compilation and execution policies. -- Moved script-changes-while-playing policy values into `UnityCLILoop.Domain` because they are compile safety policy values interpreted by Application services. -- Moved dynamic-code compilation service ports, runtime-service ports, and registries into `UnityCLILoop.Application` because Application owns the execution flow while Infrastructure supplies concrete compiler collaborators. -- Moved dynamic-code compilation DTOs into `UnityCLILoop.Application` because they are the data contract between the application execution flow and the infrastructure compiler implementation. -- Moved concrete dynamic-code compilation collaborators into `UnityCLILoop.Infrastructure`: - - `DynamicCodeCompiler` - - `DynamicCodeSourcePreparationService` - - `DynamicCompilationPlanner` - - `CompiledAssemblyBuilder` - - `CompiledAssemblyLoadService` - - `CompiledAssemblyLoader` - - `CompilationCacheManager` - - Roslyn and AssemblyBuilder compiler backends - - source shaping, auto-using, pre-using, literal hoisting, and reference-set builders -- Removed now-unused `uLoopMCP.Editor.Shared` references from `UnityCLILoop.Infrastructure` and `UnityCLILoop.CompositionRoot.Editor`. -- Removed `uLoopMCP.Editor.Shared` as a production assembly after moving its remaining constants, logging, and domain-reload registry types into `UnityCLILoop.Application`. -- Removed stale references to the deleted shared assembly GUID from dev and editor test asmdefs. -- Added `UnityCliLoopServerApplicationFacade` so Presentation code observes and controls server lifecycle through Application instead of depending on server/controller internals. -- Removed `UnityCliLoopServerApplicationFacade` in C4-6 after Presentation received `UnityCliLoopServerApplicationService` through the bootstrap service graph. -- Added `IUnityCliLoopServerInstance` so Application use cases expose an application-owned server handle instead of returning the project IPC bridge implementation. -- Added server instance factory and lifecycle registries in `UnityCLILoop.Application`; `UnityCLILoop.CompositionRoot.Editor` registers the concrete bridge implementation. -- Moved project IPC implementation into `UnityCLILoop.Infrastructure`: - - `UnityCliLoopBridgeServer` - - `BridgeTransportEndpoint` - - `BridgeTransportListener` - - `DynamicBufferManager` - - `FrameParser` - - `MessageReassembler` -- Added registry tests proving: - - bundled tools are discovered through the attribute path. - - `get-logs` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - `compile` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - `execute-dynamic-code` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - `get-version` is not registered as an extension-facing tool. - - `get-version` still executes as an internal bridge command. - - `get-tool-details` is not registered as an extension-facing tool. - - `get-tool-details` still returns the CLI catalog through the internal bridge path. - - `focus-window` is not registered as a Unity-side tool. - - legacy MCP-era development tools are not registered. - - `hello-world` is registered as an extension tool. - - `control-play-mode` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - `control-play-mode` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `get-logs` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `clear-console` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `compile` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `execute-dynamic-code` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `get-hierarchy` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `run-tests` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `find-game-objects` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `screenshot` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `record-input` and `replay-input` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `simulate-keyboard` and `simulate-mouse-input` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `simulate-mouse-ui` skill discovery still works after moving under `UnityCLILoop.FirstPartyTools.Editor`. - - `get-hierarchy` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - hierarchy host-service contracts compile under `UnityCLILoop.ToolContracts`. - - hierarchy host-service implementation compiles under `UnityCLILoop.Application`. - - `run-tests` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - test execution host-service contracts compile under `UnityCLILoop.ToolContracts`. - - test execution host-service implementation compiles under `UnityCLILoop.Application`. - - `find-game-objects` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - GameObject search host-service contracts compile under `UnityCLILoop.ToolContracts`. - - GameObject search host-service implementation compiles under `UnityCLILoop.Application`. - - `screenshot` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - screenshot host-service contracts compile under `UnityCLILoop.ToolContracts`. - - screenshot host-service implementation compiles under `UnityCLILoop.Application`. - - `record-input` and `replay-input` are registered from `UnityCLILoop.FirstPartyTools.Editor`. - - input recording host-service contracts compile under `UnityCLILoop.ToolContracts`. - - input recording host-service implementations compile under `UnityCLILoop.Application`. - - `simulate-keyboard` and `simulate-mouse-input` are registered from `UnityCLILoop.FirstPartyTools.Editor`. - - input simulation host-service contracts compile under `UnityCLILoop.ToolContracts`. - - input simulation host-service implementations compile under `UnityCLILoop.Application`. - - `simulate-mouse-ui` is registered from `UnityCLILoop.FirstPartyTools.Editor`. - - concrete tool host services compile under `UnityCLILoop.CompositionRoot.Editor`. - - `UnityCliLoopToolRegistry` does not directly construct concrete host services. - - concrete dynamic-code compiler factory compiles under `UnityCLILoop.Infrastructure`. - - Unity Console clear host service compiles under `UnityCLILoop.Infrastructure`. - - project-root identity safety policy compiles under `UnityCLILoop.Domain`. - - CLI version ordering compiles under `UnityCLILoop.Domain`. - - compilation diagnostic message parsing compiles under `UnityCLILoop.Domain`. - - dynamic-code platform defaults compile under `UnityCLILoop.Domain`. - - script-changes-while-playing policy values compile under `UnityCLILoop.Domain`. - - dynamic-code compilation service ports, runtime-service ports, and registries compile under `UnityCLILoop.Application`. - - dynamic-code compilation DTOs compile under `UnityCLILoop.Application`. - - concrete dynamic-code compilation collaborators compile under `UnityCLILoop.Infrastructure`. - - Application source files do not reference concrete dynamic-code compilation infrastructure directly. - - `UnityCLILoop.Infrastructure` and `UnityCLILoop.CompositionRoot.Editor` no longer reference `uLoopMCP.Editor.Shared`. - - support constants, structured logging, and domain-reload registry types compile under `UnityCLILoop.Application`. - - production asmdefs no longer reference `uLoopMCP.Editor.Shared`. - - project asmdefs no longer reference the deleted shared assembly GUID. - - the sample extension asmdef references only `UnityCLILoop.ToolContracts`. - - the sample `hello-world` extension executes through the same typed contract path as bundled tools. - - `UnityCLILoop.FirstPartyTools.Editor` references only `UnityCLILoop.ToolContracts`. - - settings/setup UI code no longer reaches CLI setup internals directly and receives `CliSetupApplicationService` through editor startup. - - settings/setup UI code no longer reaches skill setup internals directly and goes through `SkillSetupApplicationFacade`. - - settings-window UI code no longer reaches tool settings or registry internals directly and goes through `ToolSettingsApplicationFacade`. - - settings-window UI source uses `UnityCliLoopSettingsWindow` naming instead of the legacy MCP settings-window name. - - settings, setup, and server editor UI files now compile under `UnityCLILoop.Presentation`. - - recordings editor UI now compiles under `UnityCLILoop.Presentation` and reaches record/replay services through `RecordingsApplicationFacade`. - - unused legacy MCP communication-log code and its transient settings have been removed. - - shared editor UI constants now use `UnityCliLoopUIConstants` naming instead of the legacy MCP name. - - editor settings storage now uses `UnityCliLoopEditorSettings` naming instead of the legacy MCP name. - - editor domain reload state provider now uses `UnityCliLoopEditorDomainReloadStateProvider` naming instead of the legacy MCP name. - - project path resolution now uses `UnityCliLoopPathResolver` naming instead of the legacy MCP name. - - package version, tool availability, console log filter, shared constants, and server config now use `UnityCliLoop*` naming instead of legacy MCP names. - - project IPC server lifecycle types now use `UnityCliLoop*` naming instead of legacy MCP names. - - presentation USS, UXML, and C# style class names now use `unity-cli-loop-*` prefixes instead of the legacy `mcp-*` prefix. - - public tool source files now live under `Packages/src/Editor/FirstPartyTools` instead of the legacy `Packages/src/Editor/Api/McpTools` folder. - - pure platform values `ToolDisabledException`, `ValidationResult`, and `ServiceResult` now compile under `UnityCLILoop.Domain`. - - dynamic-code compiler factory registration now compiles under `UnityCLILoop.CompositionRoot.Editor`. - - server lifecycle facade, server handle, server factory registry, and server lifecycle registry compile under `UnityCLILoop.Application`. - - project IPC transport implementation compiles under `UnityCLILoop.Infrastructure`. - - Application source files do not reference project IPC implementation classes directly. -- Added asmdef dependency tests proving: - - `Domain` and `ToolContracts` have no project assembly references. - - `Application` references the inward contracts and does not reference outer onion layers. - - `Presentation` and `Infrastructure` are sibling outer layers and do not reference each other. - - `CompositionRoot.Editor` is the assembly allowed to reference all onion assemblies. - -## Key Changes - -- Create `refactor/unity-cli-loop-onion-architecture` from `origin/v3-beta`. -- Restructure asmdef boundaries around: - - `UnityCLILoop.Domain` - - `UnityCLILoop.ToolContracts` - - `UnityCLILoop.Application` - - `UnityCLILoop.Presentation` - - `UnityCLILoop.Infrastructure` - - `UnityCLILoop.CompositionRoot.Editor` - - `UnityCLILoop.FirstPartyTools.Editor` -- Keep `Domain` focused on platform rules. -- Keep `Application` focused on tool hosting, registration, catalog, and execution policy. -- Keep `Presentation` and `Infrastructure` as sibling outer layers that do not reference each other. -- Keep `CompositionRoot.Editor` as the only assembly that references all layers and first-party tools for DI wiring and registration. -- Keep `FirstPartyTools.Editor` as an outer plugin assembly that references only `ToolContracts`. -- Move editor/runtime session state out of static facades and into instance services where the state has a lifecycle: - - CLI setup and skill installation detection - - tool, ULoop, and editor settings repositories - - tool registrar and host-service provider registries - - dynamic-code server-scoped services and startup telemetry - - server controller, server factory, and lifecycle registries - - editor delay scheduling and main-thread continuation scheduling - - input recording, replay, simulation, overlay, and VibeLogger state -- Keep static entrypoints only where Unity callbacks, current public API, or generated skill compatibility still require a static surface; those entrypoints delegate to instance services. - -## Follow-up Opportunities - -- Move additional cohesive platform rules into `UnityCLILoop.Domain` when they have no Unity or file-system dependency. -- Move additional Unity Editor and file-system adapters into `UnityCLILoop.Infrastructure` when Application facades or ports are available. -- Split additional internal bridge commands from public tool registration when more CLI-only commands are identified. -- Move additional startup and DI wiring into `UnityCLILoop.CompositionRoot.Editor` as concrete service composition points are identified. -- Extend asmdef dependency tests after each future physical move, so dependency direction stays enforced by Unity assemblies instead of documentation alone. - -## Public Contracts - -- Replace old public SDK names with UnityCLILoop names: - - `[McpTool]` to `[UnityCliLoopTool]` - - `McpToolAttribute` to `UnityCliLoopToolAttribute` - - `IUnityTool` to `IUnityCliLoopTool` - - `AbstractUnityTool` to `UnityCliLoopTool` - - `BaseToolSchema` to `UnityCliLoopToolSchema` - - `BaseToolResponse` to `UnityCliLoopToolResponse` - - `CustomToolManager` to `UnityCliLoopToolRegistrar` -- Remove `MCP` naming from public SDK and contract types. -- Keep MCP naming only inside infrastructure protocol implementation if it is still needed there. - -## Test Plan - -- Add or update asmdef dependency tests to verify: - - `Domain` does not reference project asmdefs. - - `ToolContracts` does not reference implementation asmdefs. - - `Application` references only `Domain` and `ToolContracts`. - - `Presentation` and `Infrastructure` do not reference each other. - - `FirstPartyTools.Editor` references only `ToolContracts`. - - `CompositionRoot.Editor` is the only assembly that can reference all layers and first-party tools. -- Add contract tests for `[UnityCliLoopTool]` and `UnityCliLoopTool` registration and execution. -- Add first-party parity coverage showing `GetLogs` and a Hello World style tool use the same catalog and execution path. -- Add source-level guard coverage so migrated static facades do not regain direct mutable static fields. -- Run `uloop compile` after C# changes and confirm there are no errors or warnings. -- Run focused EditMode and PlayMode suites around onion boundaries, static facade state, server startup protection, input replay, and input simulation. - -## Assumptions - -- Full source compatibility for existing third-party tools is not required. -- Tool implementations are external plugins from the perspective of the core Onion. -- Tool implementations should reference only `UnityCLILoop.ToolContracts`. -- First-party tools are grouped in `UnityCLILoop.FirstPartyTools.Editor` for now rather than split into per-tool asmdefs. diff --git a/docs/code-complexity.md b/docs/code-complexity.md index 40e6ba36cc..80b66b816c 100644 --- a/docs/code-complexity.md +++ b/docs/code-complexity.md @@ -30,13 +30,18 @@ CODE_COMPLEXITY_FAIL_ON_EXCEEDED=true scripts/check-code-complexity.sh Run the C# checker directly: ```sh -dotnet run --project tools/UnityCliLoop.CodeComplexity -- --root . --max-complexity 25 +dotnet run --project tools/UnityCliLoop.CodeComplexity -- --root . --max-complexity 15 ``` ## Operating Policy -Start with a maximum cyclomatic complexity of 25. This matches the default threshold for CA1502 and avoids turning existing hotspots into immediate PR blockers. +The repository-wide maximum cyclomatic complexity is 15. It is declared in two places that must +stay in step: `MAX_COMPLEXITY` in `scripts/check-code-complexity.sh` and `cyclop.max-complexity` +in `cli/.golangci-complexity.yml`. The `Code Complexity` workflow runs on every pull request that +touches `cli/**/*.go` or `Packages/src/**/*.cs`, reports findings, and uploads per-module JSON +artifacts — it never fails the build. When touching a reported function, prefer reducing complexity before adding behavior. Use tests first, then refactor with small steps such as guard clauses, Extract Method, or data-driven dispatch. -Do not lower the repository-wide threshold until the current warning list is small enough that the stricter threshold creates actionable review feedback. +Because the check is advisory, the threshold only does its job if someone reads the report. Treat +a new finding in code you are already editing as review feedback, not as noise to defer. diff --git a/docs/execute-dynamic-code-examples.md b/docs/execute-dynamic-code-examples.md deleted file mode 100644 index 5843481230..0000000000 --- a/docs/execute-dynamic-code-examples.md +++ /dev/null @@ -1,194 +0,0 @@ -# execute-dynamic-code Examples - -`uloop execute-dynamic-code` をターミナルから試すためのサンプル集。 - -## Quick Start - -まずは短いコードで疎通を確認する。 - -```sh -uloop execute-dynamic-code --code 'return "hello";' -``` - -実行速度を体感したい時は `time` を付けて複数回打つ。 - -```sh -time uloop execute-dynamic-code --code 'return "first";' -time uloop execute-dynamic-code --code 'return "second";' -time uloop execute-dynamic-code --code 'return "third";' -``` - -## Short Examples - -単純な計算。 - -```sh -uloop execute-dynamic-code --code 'return 1 + 2 + 3;' -``` - -配列を組み立てて返す。 - -```sh -uloop execute-dynamic-code --code 'string[] names = { "A", "B", "C" }; return string.Join(", ", names);' -``` - -Unity バージョンを返す。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine; return Application.unityVersion;' -``` - -現在の Scene 名を返す。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine.SceneManagement; return SceneManager.GetActiveScene().name;' -``` - -GameObject を作って名前を返す。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine; GameObject go = new GameObject("SampleCube"); go.AddComponent(); return go.name;' -``` - -パラメータ付きで掛け算する。 - -```sh -uloop execute-dynamic-code --code 'int a = (int)parameters[0]; int b = (int)parameters[1]; return a * b;' --parameters '[6,7]' -``` - -## Medium Examples - -Camera 情報を列挙する。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine; Camera[] cameras = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None); System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (Camera cam in cameras) { sb.AppendLine(cam.name + " depth=" + cam.depth); } return sb.ToString();' -``` - -Renderer の数を集計する。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine; Renderer[] renderers = UnityEngine.Object.FindObjectsByType(FindObjectsSortMode.None); int enabledCount = 0; foreach (Renderer r in renderers) { if (r.enabled) { enabledCount++; } } return "renderers=" + renderers.Length + ", enabled=" + enabledCount;' -``` - -ルート GameObject 名を並べる。 - -```sh -uloop execute-dynamic-code --code 'using UnityEngine; using UnityEngine.SceneManagement; GameObject[] roots = SceneManager.GetActiveScene().GetRootGameObjects(); System.Collections.Generic.List names = new System.Collections.Generic.List(); foreach (GameObject root in roots) { names.Add(root.name); } return string.Join(", ", names);' -``` - -## Long Examples - -長いコードは変数に入れてから渡すと扱いやすい。 - -Scene 全体をざっと調べる例。 - -```sh -CODE=$(cat <<'EOF' -using UnityEngine; -using UnityEngine.SceneManagement; -using System.Text; - -Scene scene = SceneManager.GetActiveScene(); -GameObject[] roots = scene.GetRootGameObjects(); -StringBuilder sb = new StringBuilder(); - -sb.AppendLine("Scene: " + scene.name); -sb.AppendLine("Root count: " + roots.Length); - -foreach (GameObject root in roots) -{ - sb.AppendLine("- " + root.name); - - Transform[] children = root.GetComponentsInChildren(true); - sb.AppendLine(" transforms=" + children.Length); - - Renderer[] renderers = root.GetComponentsInChildren(true); - sb.AppendLine(" renderers=" + renderers.Length); -} - -return sb.ToString(); -EOF -) -uloop execute-dynamic-code --code "$CODE" -``` - -特定オブジェクトを探して移動する例。 - -```sh -CODE=$(cat <<'EOF' -using UnityEngine; - -GameObject target = GameObject.Find("Main Camera"); -if (target == null) -{ - return "Main Camera not found"; -} - -Vector3 before = target.transform.position; -target.transform.position = before + new Vector3(0f, 1f, 0f); -Vector3 after = target.transform.position; - -return "moved: " + before + " -> " + after; -EOF -) -uloop execute-dynamic-code --code "$CODE" -``` - -Hierarchy をフラットに列挙する例。 - -```sh -CODE=$(cat <<'EOF' -using UnityEngine; -using UnityEngine.SceneManagement; -using System.Collections.Generic; - -List lines = new List(); -GameObject[] roots = SceneManager.GetActiveScene().GetRootGameObjects(); - -foreach (GameObject root in roots) -{ - Transform[] all = root.GetComponentsInChildren(true); - foreach (Transform t in all) - { - lines.Add(t.name + " | activeSelf=" + t.gameObject.activeSelf); - } -} - -return string.Join("\n", lines); -EOF -) -uloop execute-dynamic-code --code "$CODE" -``` - -コンポーネントを追加して設定する例。 - -```sh -CODE=$(cat <<'EOF' -using UnityEngine; - -GameObject host = GameObject.Find("DynamicHost"); -if (host == null) -{ - host = new GameObject("DynamicHost"); -} - -Rigidbody rb = host.GetComponent(); -if (rb == null) -{ - rb = host.AddComponent(); -} - -rb.useGravity = false; -rb.mass = 2.5f; - -return host.name + " mass=" + rb.mass + " useGravity=" + rb.useGravity; -EOF -) -uloop execute-dynamic-code --code "$CODE" -``` - -## Tips - -- `launch -r` 直後は `prewarm` がまだ終わっていないことがある -- 速度比較をしたい時は、同じコマンドを `time` 付きで 2 回以上打つ -- 長いコードは `CODE=$(cat <<'EOF' ... EOF)` 形式が扱いやすい diff --git a/docs/execute-dynamic-code-run-log.md b/docs/execute-dynamic-code-run-log.md deleted file mode 100644 index e3eea4b7b5..0000000000 --- a/docs/execute-dynamic-code-run-log.md +++ /dev/null @@ -1,50 +0,0 @@ -# execute-dynamic-code Run Log - -2026-04-16 にターミナルから実行した `uloop execute-dynamic-code` のコード一覧。 - -## Single Snippet Benchmark - -最初の計測では、次のコードを 5 回連続で実行した。 - -```csharp -using UnityEngine; return Mathf.PI; -``` - -## Distinct Snippet Benchmark - -次の 5 本のコードを 1 回ずつ実行する計測を行い、その後まったく同じ 5 本で再計測した。 - -### 1. PI - -```csharp -using UnityEngine; return Mathf.PI; -``` - -### 2. Vector Magnitude - -```csharp -using UnityEngine; Vector3 v = new Vector3(3f, 4f, 0f); return v.magnitude; -``` - -### 3. Unity Version - -```csharp -using UnityEngine; return Application.unityVersion; -``` - -### 4. Play Mode State - -```csharp -using UnityEditor; return EditorApplication.isPlaying; -``` - -### 5. Active Scene Name - -```csharp -using UnityEditor.SceneManagement; return EditorSceneManager.GetActiveScene().name; -``` - -## Notes - -- `Distinct Snippet Benchmark` の 5 本は 2 回連続で同じコードを使用した。 -- `Unity Version` の戻り値は計測タイミングによって `6000.2.10f1` と `6000.3.13f1` の 2 パターンを確認した。 diff --git a/docs/github-actions-security.md b/docs/github-actions-security.md index 20d2122996..a73d18d3b5 100644 --- a/docs/github-actions-security.md +++ b/docs/github-actions-security.md @@ -8,7 +8,7 @@ When updating a pinned action: 1. Resolve the intended upstream tag to a commit SHA. 2. Replace the workflow `uses:` ref with the full 40-character SHA. -3. Run `go test ./internal/architecture -run 'TestWorkflowActions|TestPullRequestWorkflow' -count=1` from `cli`. +3. Run `go test ./internal/architecture -run 'TestWorkflowActions|TestPullRequestWorkflow' -count=1` from `cli/release-automation`. For nested action paths such as `github/codeql-action/upload-sarif`, resolve the tag against the action repository, not the nested action path. diff --git a/docs/glossary.md b/docs/glossary.md index 52b6a89e88..e66b9264a8 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -44,15 +44,17 @@ internal bridge command. ### Server -The TCP IPC endpoint hosted inside the Unity Editor by the package -(`UnityCliLoopBridgeServer`). It accepts short-lived sessions from the CLI, dispatches -JSON-RPC requests to tools and internal bridge commands, and reports editor readiness. +The local IPC endpoint hosted inside the Unity Editor by the package +(`UnityCliLoopBridgeServer`) — a Unix domain socket on macOS/Linux, a named pipe on +Windows, never TCP (`BridgeTransportEndpoint`). It accepts short-lived sessions from the +CLI, dispatches JSON-RPC requests to tools and internal bridge commands, and reports +editor readiness. ### CLI The `uloop` command-line interface as a whole — the user-facing entry point that talks to -the server over TCP. Physically it consists of two Go binaries: the dispatcher and the -project runner. +the server over local IPC. Physically it consists of two Go binaries: the dispatcher and +the project runner. ### Dispatcher