diff --git a/.beads/.gitignore b/.beads/.gitignore
index 374adb8..e68d2a2 100644
--- a/.beads/.gitignore
+++ b/.beads/.gitignore
@@ -10,6 +10,7 @@ daemon.lock
daemon.log
daemon.pid
bd.sock
+sync-state.json
# Local version tracking (prevents upgrade notification spam after git ops)
.local_version
@@ -26,7 +27,8 @@ beads.left.meta.json
beads.right.jsonl
beads.right.meta.json
-# Keep JSONL exports and config (source of truth for git)
-!issues.jsonl
-!metadata.json
-!config.json
+# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
+# They would override fork protection in .git/info/exclude, allowing
+# contributors to accidentally commit upstream issue databases.
+# The JSONL files (issues.jsonl, interactions.jsonl) and config files
+# are tracked by git by default since no pattern above ignores them.
diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl
new file mode 100644
index 0000000..e69de29
diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl
index a39f34e..70a2ad9 100644
--- a/.beads/issues.jsonl
+++ b/.beads/issues.jsonl
@@ -12,4 +12,4 @@
{"id":"gpu-support-ilr","title":"Extract OpenCLBuffer implementation","description":"Extract OpenCLBuffer from ART.\n\n## Source\n`/Users/hal.hildebrand/git/ART/art-modules/art-cortical/src/main/java/com/hellblazer/art/cortical/gpu/memory/OpenCLBuffer.java`\n\n## Target\n`resource/src/main/java/com/hellblazer/luciferase/resource/compute/memory/OpenCLBuffer.java`\n\n## Changes Required\n- Update package declaration\n- Update GPUBuffer import\n- CLBufferHandle.translateError() import unchanged (already in resource module)\n\n## Key Features\n- Float buffer abstraction\n- upload(FloatBuffer) / upload(float[])\n- download(FloatBuffer) / download(float[])\n- Protected constructor for subclasses (CLBufferAdapter pattern)\n- Size validation on transfers\n\n## Future Enhancement (Phase 5)\nConsider refactoring to wrap CLBufferHandle internally for RAII benefits\n\nContext: Parent feature gpu-support-5wc","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T17:06:16.180484-08:00","updated_at":"2025-12-28T19:52:42.541562-08:00","closed_at":"2025-12-28T19:52:42.541562-08:00","close_reason":"OpenCLBuffer tests fixed - 10 tests pass with simplified test pattern","dependencies":[{"issue_id":"gpu-support-ilr","depends_on_id":"gpu-support-gij","type":"blocks","created_at":"2025-12-28T17:06:31.264386-08:00","created_by":"daemon"}]}
{"id":"gpu-support-ipz","title":"Phase 1 Unit Tests","description":"Create unit tests for Phase 1 components.\n\n## Tests Required\n1. GPUBufferTest - Interface contract verification (mock implementation)\n2. ComputeKernelTest - Interface contract, exception types\n3. GPUBackendTest - Enum values, availability checks\n4. BackendSelectorTest - Selection logic, CI detection, env vars\n5. GPUErrorClassifierTest - Error classification logic\n\n## Test Patterns\n- Use Mockito for interface testing\n- Test error classification with sample exception messages\n- Test CI environment detection with env var mocking\n\n## Acceptance Criteria\n- [ ] All tests pass\n- [ ] Coverage \u003e 80% for classifier logic\n\nContext: Parent feature gpu-support-6e9","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T17:05:42.229259-08:00","updated_at":"2025-12-28T18:11:02.203471-08:00","closed_at":"2025-12-28T18:11:02.203471-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gpu-support-ipz","depends_on_id":"gpu-support-kdp","type":"blocks","created_at":"2025-12-28T17:05:49.00115-08:00","created_by":"daemon"},{"issue_id":"gpu-support-ipz","depends_on_id":"gpu-support-cbr","type":"blocks","created_at":"2025-12-28T17:05:49.077511-08:00","created_by":"daemon"},{"issue_id":"gpu-support-ipz","depends_on_id":"gpu-support-e63","type":"blocks","created_at":"2025-12-28T17:10:14.155949-08:00","created_by":"daemon"},{"issue_id":"gpu-support-ipz","depends_on_id":"gpu-support-ad2","type":"blocks","created_at":"2025-12-28T17:10:14.229753-08:00","created_by":"daemon"},{"issue_id":"gpu-support-ipz","depends_on_id":"gpu-support-9go","type":"blocks","created_at":"2025-12-28T17:10:14.30489-08:00","created_by":"daemon"}]}
{"id":"gpu-support-kdp","title":"Extract GPUErrorClassifier","description":"Extract GPUErrorClassifier from ART.\n\n## Source\n`/Users/hal.hildebrand/git/ART/art-modules/art-cortical/src/main/java/com/hellblazer/art/cortical/gpu/compute/GPUErrorClassifier.java`\n\n## Target\n`resource/src/main/java/com/hellblazer/luciferase/resource/compute/GPUErrorClassifier.java`\n\n## Changes Required\n- Update package declaration\n- Update ComputeKernel.KernelCompilationException import\n- Update ComputeKernel.KernelExecutionException import\n\n## Key Features to Preserve\n- Programming error detection (fail fast)\n- Recoverable error detection (allow CPU fallback)\n- OpenCL error code extraction from messages\n- Error code to name translation\n\nContext: Parent feature gpu-support-6e9","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-28T17:03:23.717012-08:00","updated_at":"2025-12-28T18:10:23.076314-08:00","closed_at":"2025-12-28T18:10:23.076314-08:00","close_reason":"Closed","dependencies":[{"issue_id":"gpu-support-kdp","depends_on_id":"gpu-support-ad2","type":"blocks","created_at":"2025-12-28T17:05:48.769925-08:00","created_by":"daemon"}]}
-{"id":"gpu-support-trf","title":"Phase 4: ART Migration","description":"Migrate ART to use gpu-support compute infrastructure.\n\n## Tasks\n1. Update ART pom.xml to depend on gpu-support 1.0.5+\n2. Update ART imports from art.cortical.gpu to luciferase.resource.compute\n3. Remove extracted code from ART (compute/, memory/, kernels/ packages)\n4. Run full ART test suite to validate\n\n## Risk Mitigation\n- Keep ART working on separate branch until validated\n- Run performance comparison before/after\n\n## Acceptance Criteria\n- [ ] ART builds successfully with new dependency\n- [ ] All ART GPU tests pass\n- [ ] No duplicate code remains in ART\n- [ ] Performance within 5% of original\n\nContext: Depends on gpu-support-0y1 (Phase 3)","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-28T17:02:02.780414-08:00","updated_at":"2025-12-28T17:02:02.780414-08:00","dependencies":[{"issue_id":"gpu-support-trf","depends_on_id":"gpu-support-0y1","type":"blocks","created_at":"2025-12-28T17:02:43.652183-08:00","created_by":"daemon"}]}
+{"id":"gpu-support-trf","title":"Phase 4: ART Migration","description":"Migrate ART to use gpu-support compute infrastructure.\n\n## Tasks\n1. Update ART pom.xml to depend on gpu-support 1.0.5+\n2. Update ART imports from art.cortical.gpu to luciferase.resource.compute\n3. Remove extracted code from ART (compute/, memory/, kernels/ packages)\n4. Run full ART test suite to validate\n\n## Risk Mitigation\n- Keep ART working on separate branch until validated\n- Run performance comparison before/after\n\n## Acceptance Criteria\n- [ ] ART builds successfully with new dependency\n- [ ] All ART GPU tests pass\n- [ ] No duplicate code remains in ART\n- [ ] Performance within 5% of original\n\nContext: Depends on gpu-support-0y1 (Phase 3)","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-28T17:02:02.780414-08:00","updated_at":"2025-12-31T10:05:25.24913-08:00","closed_at":"2025-12-29T02:01:55.866187-08:00","dependencies":[{"issue_id":"gpu-support-trf","depends_on_id":"gpu-support-0y1","type":"blocks","created_at":"2025-12-28T17:02:43.652183-08:00","created_by":"daemon"}]}
diff --git a/AGENTS.md b/AGENTS.md
index a657a7f..2b56af7 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -192,3 +192,29 @@ if (!compute.isGPUAvailable()) return;
./mvnw test -pl resource # Test compute module
./mvnw test -Dtest=ComputeServiceTest # Specific test
```
+
+## Landing the Plane (Session Completion)
+
+**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
+
+**MANDATORY WORKFLOW:**
+
+1. **File issues for remaining work** - Create issues for anything that needs follow-up
+2. **Run quality gates** (if code changed) - Tests, linters, builds
+3. **Update issue status** - Close finished work, update in-progress items
+4. **PUSH TO REMOTE** - This is MANDATORY:
+ ```bash
+ git pull --rebase
+ bd sync
+ git push
+ git status # MUST show "up to date with origin"
+ ```
+5. **Clean up** - Clear stashes, prune remote branches
+6. **Verify** - All changes committed AND pushed
+7. **Hand off** - Provide context for next session
+
+**CRITICAL RULES:**
+- Work is NOT complete until `git push` succeeds
+- NEVER stop before pushing - that leaves work stranded locally
+- NEVER say "ready to push when you are" - YOU must push
+- If push fails, resolve and retry until it succeeds
diff --git a/pom.xml b/pom.xml
index d4a8938..4dff9a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -195,7 +195,6 @@
This method allows setting raw cl_mem handles directly, useful when + * working with buffers created outside the GPUBuffer abstraction (e.g., + * ByteBuffer uploads via clCreateBuffer). + * + * @param index Argument index + * @param clMem Raw OpenCL memory object handle (cl_mem) + * @throws IllegalStateException if kernel is closed or not compiled + */ + public void setRawBufferArg(int index, long clMem) { + checkNotClosed(); + checkCompiled(); + + try { + checkCLError( + clSetKernelArg1p(kernel, index, clMem), + "Failed to set raw buffer argument " + index + ); + } catch (KernelCompilationException e) { + throw new RuntimeException(e); // Convert to unchecked for setter + } + } + + /** + * Set a float3 vector argument. + * + *
Passes a 3-component float vector to the kernel. Useful for + * scene bounds, positions, directions, etc. + * + * @param index Argument index + * @param x X component + * @param y Y component + * @param z Z component + * @throws IllegalStateException if kernel is closed or not compiled + */ + public void setFloat3Arg(int index, float x, float y, float z) { + checkNotClosed(); + checkCompiled(); + + try (var stack = stackPush()) { + var buffer = stack.mallocFloat(3); + buffer.put(0, x); + buffer.put(1, y); + buffer.put(2, z); + try { + checkCLError( + clSetKernelArg(kernel, index, buffer), + "Failed to set float3 argument " + index + ); + } catch (KernelCompilationException e) { + throw new RuntimeException(e); // Convert to unchecked for setter + } + } + } + @Override public void execute(int globalWorkSize) throws KernelExecutionException { execute(globalWorkSize, 1, 1);