Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .githooks/post-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env sh
set -eu

REPO_ROOT=$(git rev-parse --show-toplevel)

if [ -d "$REPO_ROOT/.projectmem" ] && command -v pjm >/dev/null 2>&1; then
(cd "$REPO_ROOT" && pjm _auto-capture commit >/dev/null 2>&1 &)
fi
8 changes: 8 additions & 0 deletions .githooks/post-merge
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env sh
set -eu

REPO_ROOT=$(git rev-parse --show-toplevel)

if [ -d "$REPO_ROOT/.projectmem" ] && command -v pjm >/dev/null 2>&1; then
(cd "$REPO_ROOT" && pjm _auto-capture merge >/dev/null 2>&1 &)
fi
8 changes: 8 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env sh
set -eu

REPO_ROOT=$(git rev-parse --show-toplevel)

if [ -d "$REPO_ROOT/.projectmem" ] && command -v pjm >/dev/null 2>&1; then
(cd "$REPO_ROOT" && pjm precheck --level warn) || true
fi
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,19 @@ LINT_REPORT.txt
temp_verify/
*.tmp
AUDIT_FINDINGS.md*

# ProjectMem runtime state is local and may contain private work history.
# Keep only the reviewed project configuration, map, and plan in Git.
.projectmem/AI_INSTRUCTIONS.md
.projectmem/events.jsonl
.projectmem/issues/
.projectmem/summary.md
.projectmem/watch.pid
.projectmem/watch.log
.projectmem/structure.json

# Claude Code project registration is generated locally and includes the Nexus auth token.
.mcp.json
.mcp.json.bak-*
CLAUDE.md
AGENTS.md.soma-backup-*
47 changes: 47 additions & 0 deletions .projectmem/PROJECT_MAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Project Map - NexusUnity

Status: curated project map. Update this map when package boundaries or primary entry points change.

## Project purpose
Open source Unity Editor automation server for local AI tools and developer workflows.

## Stack
- Unity Package Manager package: `com.forkhorizon.nexus.unity` for Unity `6000.0+`.
- C# Editor implementation under `Editor/`, with runtime support under `Runtime/`.
- Python 3 MCP bridge under `Editor/nexus_unity_bridge.py` and `Editor/nexus_bridge/`.
- Tests: Unity EditMode tests under `Tests~/Editor/` and Python bridge tests under `Editor/tests/`.
- Validation: `scripts/prepush-validate.sh`, GitHub Actions, and the .NET `tools~/NexusQualityGate` tool.

## Entry points
- `package.json` — UPM package identity, dependencies, and public version.
- `Editor/MCPServer.cs` — local JSON-RPC server lifecycle and editor state.
- `Editor/MCPServerMethods.cs` — raw JSON-RPC dispatch; partial method files implement tool groups.
- `Editor/nexus_unity_bridge.py` — Python MCP bridge process entry point.
- `Editor/nexus_bridge/routing.py` — MCP manager routing and macros.

## Structure
- `Editor/` — Unity Editor server, raw tools, integration UI, and Python bridge.
- `MCPServer.cs` — server state/lifecycle; `MCPServer.Networking.cs` owns HTTP/WebSocket handling.
- `MCPServerMethods.cs` — tool dispatch; `MCPServerMethods.*.cs` group the raw tool implementations.
- `NexusMcpConfigGenerator.cs` — generated MCP client configuration and bridge health checks.
- `nexus_unity_bridge.py` — MCP protocol entry point.
- `nexus_bridge/` — bridge transport, schemas, and manager routing.
- `tests/` — Python bridge unit tests.
- `Runtime/` — runtime assembly support used by Editor-facing features.
- `Tests~/Editor/` — Unity EditMode/API/security/integration configuration tests.
- `scripts/` — package validation and optional agent-tooling smoke script.
- `tools~/NexusQualityGate/` — standalone .NET documentation and source-quality gate.
- `.github/workflows/validate.yml` — protected-branch CI validation and Unity package smoke.
- `README.md`, `DOCUMENTATION.MD`, `API_REFERENCE.MD`, `RELEASE.md`, `CHANGELOG.md` — public package and release documentation.

## Relationships
- `Editor/MCPServer.Networking.cs` validates a local request before `Editor/MCPServerMethods.cs` dispatches the raw JSON-RPC method on the Unity main thread.
- `Editor/nexus_unity_bridge.py` loads `Editor/nexus_bridge/routing.py`, which maps MCP manager tools to the raw Unity JSON-RPC API.
- `Editor/nexus_bridge/schemas.py` defines the public bridge contracts exercised by `Editor/tests/`.
- `Editor/NexusMcpConfigGenerator.cs` deploys the bridge and writes client configuration containing the current auth token.
- `scripts/prepush-validate.sh` runs bridge tests and `tools~/NexusQualityGate`; GitHub CI additionally imports the package into a clean Unity project.

## Suggested first reads
- For API or server behavior: `API_REFERENCE.MD`, `Editor/MCPServer.cs`, and the relevant `Editor/MCPServerMethods.*.cs` file.
- For MCP bridge work: `Editor/nexus_unity_bridge.py`, `Editor/nexus_bridge/routing.py`, and `Editor/nexus_bridge/schemas.py`.
- For package publication: `RELEASE.md`, `CHANGELOG.md`, and `.github/workflows/validate.yml`.
3 changes: 3 additions & 0 deletions .projectmem/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
summary_size_limit_kb = 20
recent_days = 30
project_description = "Nexus Unity is an open-source Unity Editor automation package with a C# JSON-RPC server and a Python MCP bridge."
22 changes: 22 additions & 0 deletions .projectmem/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# NexusUnity — plan

> Editable **intent** file: ideas + plans — what we *mean to do*.
> This is NOT the event log. `events.jsonl` -> `summary.md` records what
> *happened*; this file records what we *intend*. The AI reads it at
> session start and edits it directly (like `PROJECT_MAP.md`): add ideas
> and plans, check items off, move done work down to Shipped. Plans are
> never logged as events.

## Ideas
_Loose thoughts, not yet committed to._

## Active plans
_What we're working toward now. Use `- [ ]` / `- [x]` checklists._

## Next
_Queued, but not started._

## Someday / maybe

## Shipped
_Move completed plans here so the top stays about the future._
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,14 @@ PYTHONDONTWRITEBYTECODE=1 scripts/prepush-validate.sh --static-only
For Unity-facing behavior, also use the running test harness through MCP tools such as `unity_wait`, `unity_lint_project`, and `unity_editor_controller`.

Clean generated Python caches before validation if needed; `__pycache__` or `*.pyc` files are not part of package changes.

<!-- SOMA_MEMORY_TOOLS_START -->
## Memory Tools

Default mode: light. Do not spend tokens on memory tools for small, obvious, single-file tasks.

- projectmem: use for bugs, regressions, multi-step changes, repeated attempts, or architecture decisions. For small self-contained edits, skip full memory startup and use targeted history checks only when useful.
- `.projectmem/config.toml`, `PROJECT_MAP.md`, and `plan.md` are shared project configuration. The append-only event log, issue files, generated summary/structure, watcher state, and generated `CLAUDE.md` bridge are local and ignored.
- This package uses the tracked `.githooks` directory. When `pjm` is installed, its `pre-commit`, `post-commit`, and `post-merge` wrappers provide warnings and local auto-capture; do not run `pjm hooks install`, which assumes `.git/hooks` exists.
- Verify that the projectmem MCP server is bound to this package before using write tools. If it is bound elsewhere, use the local `pjm` CLI from this package root instead.
<!-- SOMA_MEMORY_TOOLS_END -->
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable public changes to Nexus Unity are documented here.

## [Unreleased]

### Fixed
- Auto Setup now reports a clear refresh-and-retry message if a client is unavailable after the integration list is regenerated, instead of throwing an exception.

## [1.5.0] - 2026-07-12

### Changed
Expand Down
14 changes: 13 additions & 1 deletion Editor/MCPServerWindow.Integrations.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
Expand Down Expand Up @@ -107,7 +108,13 @@ private void AutoSetupIntegration(NexusMcpClientInfo client)
return;
}

var refreshed = NexusMcpConfigGenerator.BuildAllForCurrentProject().First(item => item.Kind == client.Kind);
var refreshed = FindIntegrationByKind(NexusMcpConfigGenerator.BuildAllForCurrentProject(), client.Kind);
if (refreshed == null)
{
SetIntegrationMessage(client.DisplayName + " is no longer available. Refresh integrations and try again.");
return;
}

refreshed.BridgePath = bridgePath.Replace("\\", "/");

if (refreshed.CustomAutoSetup != null)
Expand All @@ -134,6 +141,11 @@ private void AutoSetupIntegration(NexusMcpClientInfo client)
SetIntegrationMessage(message);
}

internal static NexusMcpClientInfo FindIntegrationByKind(IEnumerable<NexusMcpClientInfo> clients, NexusMcpClientKind kind)
{
return clients.FirstOrDefault(item => item.Kind == kind);
}

private void CopyIntegrationConfig(NexusMcpClientInfo client)
{
EditorGUIUtility.systemCopyBuffer = client.ConfigText;
Expand Down
7 changes: 7 additions & 0 deletions Tests~/Editor/EditorWindowUiToolkitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ public void ServerWindowBuildsResponsiveUiToolkitSurface()
}
}

[Test]
public void IntegrationLookupReturnsNullWhenTheClientIsNoLongerAvailable()
{
Assert.IsNull(MCPServerWindow.FindIntegrationByKind(
Enumerable.Empty<NexusMcpClientInfo>(), NexusMcpClientKind.Codex));
}

[Test]
public void VerificationWindowBuildsNamedControls()
{
Expand Down
Loading