push from SNAPKITTYWEST/ortho32-sdk-java
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitignore +12 -0
- CHANGELOG.md +25 -0
- LICENSE +110 -0
- NOTICE +141 -0
- README.md +197 -0
- SOVEREIGN_METHOD.md +139 -0
- build.gradle.kts +112 -0
- examples/agent-client/src/main/java/org/ortho32/examples/AgentClientExample.java +63 -0
- examples/device-list/src/main/java/org/ortho32/examples/DeviceListExample.java +63 -0
- examples/proof-verify/src/main/java/org/ortho32/examples/ProofVerifyExample.java +90 -0
- examples/tensor-run/src/main/java/org/ortho32/examples/TensorRunExample.java +67 -0
- examples/trace-replay/src/main/java/org/ortho32/examples/TraceReplayExample.java +86 -0
- gradle/wrapper/gradle-wrapper.properties +7 -0
- integration-tests/build.gradle.kts +10 -0
- integration-tests/src/test/java/org/ortho32/tests/CrossVerifyTest.java +67 -0
- integration-tests/src/test/java/org/ortho32/tests/DeterminismTest.java +59 -0
- integration-tests/src/test/java/org/ortho32/tests/JavaRoutingTests.java +187 -0
- integration-tests/src/test/java/org/ortho32/tests/SessionLifecycleTest.java +65 -0
- integration-tests/src/test/java/org/ortho32/tests/SimulatorTransportTest.java +49 -0
- integration-tests/src/test/java/org/ortho32/tests/TensorJobTest.java +64 -0
- integration-tests/src/test/java/org/ortho32/tests/TraceComparatorTest.java +62 -0
- integration-tests/src/test/java/org/ortho32/tests/TransportAgnosticTest.java +60 -0
- integration-tests/src/test/java/org/ortho32/tests/VerificationStatusTest.java +30 -0
- ortho-agent/build.gradle.kts +7 -0
- ortho-agent/src/main/java/org/ortho32/agent/AgentCapability.java +33 -0
- ortho-agent/src/main/java/org/ortho32/agent/AgentClient.java +26 -0
- ortho-agent/src/main/java/org/ortho32/agent/AgentIntent.java +40 -0
- ortho-agent/src/main/java/org/ortho32/agent/AgentResult.java +36 -0
- ortho-agent/src/main/java/org/ortho32/agent/AgentTask.java +32 -0
- ortho-compute/build.gradle.kts +12 -0
- ortho-compute/src/main/java/org/ortho32/compute/ComputeBackend.java +7 -0
- ortho-compute/src/main/java/org/ortho32/compute/ComputeJob.java +42 -0
- ortho-compute/src/main/java/org/ortho32/compute/ComputeResult.java +31 -0
- ortho-core/build.gradle.kts +15 -0
- ortho-core/src/main/java/org/ortho32/OrthoContext.java +24 -0
- ortho-core/src/main/java/org/ortho32/OrthoResult.java +31 -0
- ortho-core/src/main/java/org/ortho32/OrthoRuntime.java +59 -0
- ortho-core/src/main/java/org/ortho32/OrthoSession.java +86 -0
- ortho-core/src/main/java/org/ortho32/OrthoVersion.java +20 -0
- ortho-device/build.gradle.kts +11 -0
- ortho-device/src/main/java/org/ortho32/device/DeviceClient.java +57 -0
- ortho-device/src/main/java/org/ortho32/device/OrthoDevice.java +21 -0
- ortho-device/src/main/java/org/ortho32/device/OrthoDeviceCapabilities.java +14 -0
- ortho-device/src/main/java/org/ortho32/device/OrthoDeviceId.java +21 -0
- ortho-device/src/main/java/org/ortho32/device/OrthoDeviceInfo.java +23 -0
- ortho-device/src/main/java/org/ortho32/device/OrthoDeviceState.java +7 -0
- ortho-fabric/build.gradle.kts +7 -0
- ortho-fabric/src/main/java/org/ortho32/fabric/FabricAddress.java +26 -0
- ortho-fabric/src/main/java/org/ortho32/fabric/FabricCommand.java +40 -0
- ortho-fabric/src/main/java/org/ortho32/fabric/FabricCompletion.java +38 -0
.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.gradle/
|
| 2 |
+
build/
|
| 3 |
+
**/build/
|
| 4 |
+
*.class
|
| 5 |
+
*.jar
|
| 6 |
+
!gradle/wrapper/gradle-wrapper.jar
|
| 7 |
+
.idea/
|
| 8 |
+
*.iml
|
| 9 |
+
*.iws
|
| 10 |
+
*.ipr
|
| 11 |
+
out/
|
| 12 |
+
.DS_Store
|
CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Changelog
|
| 2 |
+
|
| 3 |
+
All notable changes to the ORTHO-32 Java SDK will be documented here.
|
| 4 |
+
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and Semantic Versioning.
|
| 5 |
+
|
| 6 |
+
## [0.1.0] - 2026-08-14
|
| 7 |
+
|
| 8 |
+
### Added
|
| 9 |
+
- Initial SDK release with simulator transport, all public modules
|
| 10 |
+
- Public packages: `org.ortho32`, `device`, `fabric`, `compute`, `tensor`, `trace`, `verify`, `security`, `agent`, `system`, `transport`, `exceptions`
|
| 11 |
+
- Core types: `OrthoRuntime`, `OrthoSession` (AutoCloseable), `OrthoContext`, `OrthoVersion`, `OrthoResult`, `OrthoDevice` family
|
| 12 |
+
- Fabric types: `FabricCommand`, `FabricCompletion`, `FabricAddress/Opcode/Epoch/Slot` — logical API, no BAR access
|
| 13 |
+
- Tensor types: `Tensor`, `TensorShape/Buffer/Job/Operation/Result`, `TensorLatency` (TMUL=4, TLOAD=5, TSTORE=5, Scratchpad=2) — cycles are architectural integers
|
| 14 |
+
- Trace types: `ExecutionTrace`, `CycleRecord`, `TraceHash` (SHA-256 canonical), `TraceComparator` — H=0 determinism
|
| 15 |
+
- Verification types: 12 theorems, `TheoremId/Result`, `VerificationStatus` (VERIFIED != TESTED != ASSUMED), `CrossVerificationResult` with MISMATCH blocking
|
| 16 |
+
- Security types: `Capability`, `Permission`, `SecurityContext`, `Attestation`
|
| 17 |
+
- Agent types: `AgentIntent`, `AgentTask`, `AgentResult` via typed intents
|
| 18 |
+
- Transport: `OrthoTransport` (internal), `SimulatorTransport` (deterministic, no hardware), `NativeHostTransport`, `PCIe/USB/Ethernet` stubs — transport-agnostic API
|
| 19 |
+
- Schemas: `fabric-command`, `fabric-completion`, `execution-trace`, `theorem-result`, `attestation`
|
| 20 |
+
- Examples: `device-list`, `tensor-run`, `trace-replay`, `proof-verify`, `agent-client`
|
| 21 |
+
- Integration tests: `SimulatorTransportTest`, `TensorJobTest`, `DeterminismTest`, `TraceComparatorTest`, `VerificationStatusTest`, `CrossVerifyTest`, `SessionLifecycleTest`, `TransportAgnosticTest` — all runnable offline
|
| 22 |
+
- Build: Gradle Kotlin DSL, Java 21 toolchain, reproducible builds, sources & Javadoc JARs, Maven publication, dependency locking, checksums
|
| 23 |
+
- Compatibility tuple: `SDK-Version + Fabric-Protocol-Version + Device-ABI-Version`
|
| 24 |
+
|
| 25 |
+
[0.1.0]: https://github.com/ortho32/ortho32-sdk-java/releases/tag/v0.1.0
|
LICENSE
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
TRI-LICENSE STRUCTURE
|
| 2 |
+
=====================
|
| 3 |
+
|
| 4 |
+
This project is available under THREE licensing options:
|
| 5 |
+
|
| 6 |
+
1. Business Source License 1.1 (BSL-1.1)
|
| 7 |
+
- Source-available with commercial restrictions
|
| 8 |
+
- No managed service offerings at enterprise scale
|
| 9 |
+
- Converts to AGPL-3.0 after transition period (Change Date: 2028-08-15)
|
| 10 |
+
|
| 11 |
+
2. GNU Affero General Public License v3.0 (AGPL-3.0)
|
| 12 |
+
- Strong network copyleft
|
| 13 |
+
- SaaS/network distribution triggers source disclosure
|
| 14 |
+
- All modifications must be AGPL-3.0
|
| 15 |
+
|
| 16 |
+
3. Mozilla Public License 2.0 (MPL-2.0) + Commercial Dual License
|
| 17 |
+
- Weak copyleft (file-level)
|
| 18 |
+
- Can combine with proprietary code
|
| 19 |
+
- Modified files must remain MPL-2.0
|
| 20 |
+
- Commercial license available for copyleft bypass
|
| 21 |
+
|
| 22 |
+
================================================================================
|
| 23 |
+
|
| 24 |
+
WHICH LICENSE APPLIES?
|
| 25 |
+
|
| 26 |
+
License selection is determined by use case. Use the policy engine:
|
| 27 |
+
|
| 28 |
+
https://github.com/SNAPKITTYWEST/license-policy-engine
|
| 29 |
+
|
| 30 |
+
swipl -q -t halt -f license_policy.pl -- select <your_use_case>
|
| 31 |
+
|
| 32 |
+
Use cases:
|
| 33 |
+
- saas_wrapper → AGPL-3.0
|
| 34 |
+
- enterprise_restricted → BSL-1.1
|
| 35 |
+
- file_level_mod → MPL-2.0
|
| 36 |
+
- copyleft_bypass → Commercial
|
| 37 |
+
- open_source_redistribution → AGPL-3.0
|
| 38 |
+
|
| 39 |
+
================================================================================
|
| 40 |
+
|
| 41 |
+
ORTHO-32 ECOSYSTEM
|
| 42 |
+
|
| 43 |
+
This repository is part of the ORTHO-32 deterministic processor ecosystem.
|
| 44 |
+
All ORTHO-32 connected repositories share this tri-license structure.
|
| 45 |
+
|
| 46 |
+
Ecosystem repos:
|
| 47 |
+
- ORTHO32 (ISA, RTL, Lean 4 proofs)
|
| 48 |
+
- ortho32-host (C#/.NET runtime spine)
|
| 49 |
+
- ortho32-desktop (Swift UI)
|
| 50 |
+
- ortho32-api (Python/FastAPI)
|
| 51 |
+
- ortho32-ai-gateway (MUMPS)
|
| 52 |
+
- ortho32-mcp (AWK MCP server)
|
| 53 |
+
- ortho32-sdk-java (JVM SDK)
|
| 54 |
+
- ortho32-isolation (Formal isolation proofs)
|
| 55 |
+
|
| 56 |
+
================================================================================
|
| 57 |
+
|
| 58 |
+
COPYRIGHT HOLDER
|
| 59 |
+
|
| 60 |
+
Copyright (C) 2026 Bel Esprit D'Accord Irrevocable Trust
|
| 61 |
+
SnapKitty Collective Limited (FLP)
|
| 62 |
+
|
| 63 |
+
Contact: jessicalw34@gmail.com
|
| 64 |
+
Web: https://github.com/SNAPKITTYWEST
|
| 65 |
+
|
| 66 |
+
================================================================================
|
| 67 |
+
|
| 68 |
+
================================================================================
|
| 69 |
+
|
| 70 |
+
PATENT RETALIATION
|
| 71 |
+
|
| 72 |
+
No patent license is granted by this license. If you initiate patent
|
| 73 |
+
litigation against the copyright holder, any co-author, or any
|
| 74 |
+
downstream user of this software — including cross-claims or
|
| 75 |
+
counterclaims in a lawsuit — your license under this software
|
| 76 |
+
terminates automatically and immediately without notice.
|
| 77 |
+
|
| 78 |
+
================================================================================
|
| 79 |
+
|
| 80 |
+
LITIGATION WARNING — WILLFUL INFRINGEMENT
|
| 81 |
+
|
| 82 |
+
Any use of this software beyond the permissions granted above
|
| 83 |
+
constitutes infringement. Willful infringement entitles the
|
| 84 |
+
copyright holder to seek:
|
| 85 |
+
|
| 86 |
+
- Statutory damages for willful infringement
|
| 87 |
+
- Recovery of attorneys fees and litigation costs
|
| 88 |
+
- Injunctive relief to prevent continued infringement
|
| 89 |
+
- Disgorgement of profits derived from infringing use
|
| 90 |
+
|
| 91 |
+
Jurisdiction: United States of America
|
| 92 |
+
Governing Law: Federal copyright law (17 U.S.C.) and applicable state law
|
| 93 |
+
|
| 94 |
+
================================================================================
|
| 95 |
+
|
| 96 |
+
STRONG COPYLEFT — NETWORK DEPLOYMENT
|
| 97 |
+
|
| 98 |
+
Network deployment of this software (SaaS, API, hosted service,
|
| 99 |
+
managed service) is NOT eligible for the MPL-2.0 option.
|
| 100 |
+
Network deployment MANDATES AGPL-3.0:
|
| 101 |
+
|
| 102 |
+
- All source code of the deployed application must be disclosed
|
| 103 |
+
- All modifications must be released under AGPL-3.0
|
| 104 |
+
- All combined works must be released under AGPL-3.0
|
| 105 |
+
- There is no opt-out. The copyleft follows the network.
|
| 106 |
+
|
| 107 |
+
================================================================================
|
| 108 |
+
|
| 109 |
+
Copyright (C) 2026 Bel Esprit D'Accord Irrevocable Trust (EIN 42-697643)
|
| 110 |
+
All rights reserved except as expressly granted above.
|
NOTICE
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
NOTICE — SnapKitty Sovereign IP Estate
|
| 2 |
+
=======================================
|
| 3 |
+
|
| 4 |
+
This repository is part of the SnapKitty Sovereign IP Estate, held by:
|
| 5 |
+
|
| 6 |
+
Bel Esprit D'Accord Irrevocable Trust (EIN 42-697643)
|
| 7 |
+
SnapKitty Collective Limited (FLP)
|
| 8 |
+
|
| 9 |
+
Operators: Ahmad Ali Parr · Jessica Westerhoff
|
| 10 |
+
Contact: ahmedparr93@gmail.com | jessicalw34@gmail.com
|
| 11 |
+
Web: https://github.com/SNAPKITTYWEST
|
| 12 |
+
|
| 13 |
+
All repositories under github.com/SNAPKITTYWEST and
|
| 14 |
+
github.com/BEL-ESPRIT-D-ACCORD-TRUST-HOLDINGS constitute a single
|
| 15 |
+
unified IP estate. Licensing of one component does not grant rights
|
| 16 |
+
to any other component.
|
| 17 |
+
|
| 18 |
+
================================================================================
|
| 19 |
+
|
| 20 |
+
PATENT NOTICE
|
| 21 |
+
|
| 22 |
+
No patent license is granted by this license. If you initiate patent
|
| 23 |
+
litigation against the copyright holder, any co-author, or any
|
| 24 |
+
downstream user of this software — including cross-claims or
|
| 25 |
+
counterclaims — your license under this software terminates
|
| 26 |
+
automatically and immediately without notice.
|
| 27 |
+
|
| 28 |
+
================================================================================
|
| 29 |
+
|
| 30 |
+
LITIGATION WARNING
|
| 31 |
+
|
| 32 |
+
Willful infringement of this license entitles the copyright holder to
|
| 33 |
+
seek the maximum available remedies under applicable law, including:
|
| 34 |
+
|
| 35 |
+
- Statutory damages for willful infringement
|
| 36 |
+
- Recovery of attorneys fees and litigation costs
|
| 37 |
+
- Injunctive relief to prevent continued infringement
|
| 38 |
+
- Disgorgement of profits derived from infringing use
|
| 39 |
+
|
| 40 |
+
Jurisdiction: State of [jurisdiction TBD by counsel]
|
| 41 |
+
Governing Law: Laws of the United States of America
|
| 42 |
+
|
| 43 |
+
Any use of this software beyond the permissions granted in the LICENSE
|
| 44 |
+
file constitutes infringement and triggers these remedies.
|
| 45 |
+
|
| 46 |
+
================================================================================
|
| 47 |
+
|
| 48 |
+
STRONG COPYLEFT NETWORK NOTICE
|
| 49 |
+
|
| 50 |
+
Any deployment of this software over a network — including SaaS,
|
| 51 |
+
API services, hosted tools, or managed services — triggers the
|
| 52 |
+
AGPL-3.0 license option. Network deployment is NOT eligible for
|
| 53 |
+
the MPL-2.0 option. The policy engine enforces this:
|
| 54 |
+
|
| 55 |
+
saas_wrapper → AGPL-3.0 (mandatory)
|
| 56 |
+
network_deployment → AGPL-3.0 (mandatory)
|
| 57 |
+
api_service → AGPL-3.0 (mandatory)
|
| 58 |
+
enterprise_restricted → BSL-1.1
|
| 59 |
+
file_level_mod → MPL-2.0 (non-network only)
|
| 60 |
+
research_evaluation → BSL-1.1 (free)
|
| 61 |
+
|
| 62 |
+
If you deploy this software over a network, you MUST release all
|
| 63 |
+
modified and combined source code under AGPL-3.0. There is no
|
| 64 |
+
exception. There is no opt-out. The copyleft follows the network.
|
| 65 |
+
|
| 66 |
+
================================================================================
|
| 67 |
+
|
| 68 |
+
ATTRIBUTION REQUIREMENTS
|
| 69 |
+
|
| 70 |
+
Any permitted use must display the following in documentation,
|
| 71 |
+
UI, and all derivative works:
|
| 72 |
+
|
| 73 |
+
"Built with SnapKitty sovereign software.
|
| 74 |
+
Copyright (C) 2026 Bel Esprit D'Accord Irrevocable Trust.
|
| 75 |
+
https://github.com/SNAPKITTYWEST"
|
| 76 |
+
|
| 77 |
+
Removing, obscuring, or misrepresenting this attribution
|
| 78 |
+
constitutes willful infringement.
|
| 79 |
+
|
| 80 |
+
================================================================================
|
| 81 |
+
|
| 82 |
+
Copyright (C) 2026 Bel Esprit D'Accord Irrevocable Trust (EIN 42-697643)
|
| 83 |
+
All rights reserved except as expressly granted in the LICENSE file.
|
| 84 |
+
|
| 85 |
+
================================================================================
|
| 86 |
+
|
| 87 |
+
PUBLISHED PRIOR ART — ZENODO DOI RECORD
|
| 88 |
+
|
| 89 |
+
The following peer-reviewed, DOI-stamped publications establish prior art
|
| 90 |
+
for all IP in this repository and across the SnapKitty sovereign stack.
|
| 91 |
+
Both works are immutable, publicly timestamped, and citable in any
|
| 92 |
+
legal, academic, or patent proceeding.
|
| 93 |
+
|
| 94 |
+
Publication 1:
|
| 95 |
+
Title: The Sovereign Stack: From Attention Exhaustion to
|
| 96 |
+
Computational Jurisdiction — A Unified Theory of
|
| 97 |
+
Deterministic Agent Architecture
|
| 98 |
+
Authors: Ahmad Ali Parr, Jessica Westerhoff
|
| 99 |
+
DOI: 10.5281/zenodo.21816366
|
| 100 |
+
Date: 2026-08-06
|
| 101 |
+
URL: https://zenodo.org/records/21816366
|
| 102 |
+
Covers: Sovereign Tick Runtime, Jordan-algebraic routing,
|
| 103 |
+
NAND completeness kernel, Phase Mirror Dissonance,
|
| 104 |
+
Softmax simplex critique, HyperKitty constraint DSL,
|
| 105 |
+
Resonance block capture, proof-gated deterministic
|
| 106 |
+
execution, cryptographic provenance methodology.
|
| 107 |
+
|
| 108 |
+
Publication 2:
|
| 109 |
+
Title: Erdos-789-lean/Idris-2 — Erdos-Straus Distinct-Sum-Sizes
|
| 110 |
+
Problem: An Elementary Quadratic Lower Bound for the
|
| 111 |
+
Greedy Sequence
|
| 112 |
+
Authors: Ahmad Ali Parr
|
| 113 |
+
DOI: 10.5281/zenodo.21869107
|
| 114 |
+
Date: 2026-08-10
|
| 115 |
+
URL: https://zenodo.org/records/21869107
|
| 116 |
+
Covers: Elementary combinatorial proof of g_k >= (k^2+1)/2,
|
| 117 |
+
O(sqrt(n)) extremal bound, Straus 1966 upper bound
|
| 118 |
+
recovery, Lean 4 + Idris 2 dual formalization,
|
| 119 |
+
gap-counting framework for DSS construction.
|
| 120 |
+
|
| 121 |
+
Any claim of independent invention of the mathematical results,
|
| 122 |
+
architectural patterns, or formal verification structures described
|
| 123 |
+
in these publications must predate the DOI timestamps above.
|
| 124 |
+
No such prior claim exists.
|
| 125 |
+
|
| 126 |
+
================================================================================
|
| 127 |
+
|
| 128 |
+
Publication 3:
|
| 129 |
+
Title: SNAPKITTYWEST: Sovereign Compute Architecture with
|
| 130 |
+
Linear Types, WORM Seals, Goldilocks Field Arithmetic,
|
| 131 |
+
and Settlement Witnesses
|
| 132 |
+
Authors: Snapkitty Collective, Jessica Westerhoff
|
| 133 |
+
DOI: 10.5281/zenodo.21132094
|
| 134 |
+
Date: 2026-07-02
|
| 135 |
+
URL: https://zenodo.org/records/21132094
|
| 136 |
+
Covers: sovereign-multiplicity, Goldilocks field arithmetic
|
| 137 |
+
(p=2^64-2^32+1), WORM seals, linear type hierarchy
|
| 138 |
+
(lin/aff/un/cap/seal), PIRTM compiler infrastructure,
|
| 139 |
+
agent governance, topological quantum computing,
|
| 140 |
+
snapaddr canonical addressing, root-fontana
|
| 141 |
+
constitutional compiler. Git history anchor: 2026-05-07.
|
README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ORTHO-32 Java SDK
|
| 2 |
+
|
| 3 |
+
Official JVM developer surface for ORTHO-32 — a deterministic, tensor-augmented ORTHO architecture.
|
| 4 |
+
|
| 5 |
+
> Java Application → ORTHO Java SDK → ORTHO Protocol / Native Bridge → ORTHO Host Service → Transport → ORTHO Fabric → Hardware
|
| 6 |
+
|
| 7 |
+
Applications program against stable, typed Java APIs (`OrthoDevice`, `FabricCommand`, `TensorJob`, `ExecutionTrace`, `TheoremResult`) and never touch PCIe BARs, DMA windows, or raw MMIO. The SDK hides transport internals; the same code runs against a simulator, FPGA, ASIC, PCIe, USB, or Ethernet device.
|
| 8 |
+
|
| 9 |
+
## What is ORTHO-32?
|
| 10 |
+
|
| 11 |
+
ORTHO-32 is a 32-bit ORTHO ISA with deterministic arbitration, a 4-cycle TMUL tensor unit, cycle-accurate tracing (H=0 determinism), and 12 mechanically-checked theorems (Lean4 + HOL Light). Fabric commands are logically addressed, epoch-ordered, and completed with architectural-cycle timestamps — not wall-clock time.
|
| 12 |
+
|
| 13 |
+
## What this SDK provides
|
| 14 |
+
|
| 15 |
+
- **Stable Java APIs** over ORTHO system contracts: `org.ortho32`, `org.ortho32.device`, `fabric`, `compute`, `tensor`, `trace`, `verify`, `security`, `agent`, `system`, `transport`, `exceptions`
|
| 16 |
+
- **Immutable value objects, records, `CompletableFuture` async, `Flow.Publisher` streaming, typed exceptions, `AutoCloseable` resources**
|
| 17 |
+
- **SimulatorTransport** — deterministic fake fabric for offline development, CI, and tests (no hardware required)
|
| 18 |
+
- **JSON Schemas** for `FabricCommand`, `FabricCompletion`, `ExecutionTrace`, `TheoremResult`, `Attestation`
|
| 19 |
+
- **Examples & integration tests** validated against `SimulatorTransport`
|
| 20 |
+
|
| 21 |
+
## Quick-start (5 lines)
|
| 22 |
+
|
| 23 |
+
Add the SDK to your Gradle project and run with the simulator (Java 21):
|
| 24 |
+
|
| 25 |
+
```kotlin
|
| 26 |
+
dependencies { implementation("dev.ortho32:ortho32-sdk:0.1.0") }
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
```java
|
| 30 |
+
try (OrthoRuntime runtime = OrthoRuntime.open();
|
| 31 |
+
OrthoSession session = runtime.openSession()) {
|
| 32 |
+
|
| 33 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 34 |
+
|
| 35 |
+
TensorJob job = TensorJob.builder()
|
| 36 |
+
.device(device)
|
| 37 |
+
.operation(TensorOperation.TMUL)
|
| 38 |
+
.inputA(matrixA)
|
| 39 |
+
.inputB(matrixB)
|
| 40 |
+
.build();
|
| 41 |
+
|
| 42 |
+
TensorResult result = session.tensor().submit(job).join();
|
| 43 |
+
|
| 44 |
+
System.out.println("cycles: " + result.cycles());
|
| 45 |
+
System.out.println("trace: " + result.traceHash());
|
| 46 |
+
}
|
| 47 |
+
```
|
| 48 |
+
No drivers, no hardware — `OrthoRuntime.open()` defaults to `SimulatorTransport` when no device is present. Swap to PCIe/USB/Ethernet by changing transport, not application code.
|
| 49 |
+
|
| 50 |
+
## Module overview
|
| 51 |
+
|
| 52 |
+
| Module | Artifact | Purpose |
|
| 53 |
+
|---|---|---|
|
| 54 |
+
| `ortho-core` | `org.ortho32` | `OrthoRuntime`, `OrthoSession`, `OrthoContext`, `OrthoVersion`, `OrthoResult` |
|
| 55 |
+
| `ortho-device` | `org.ortho32.device` | `OrthoDevice`, `OrthoDeviceId/Info/Capabilities/State` |
|
| 56 |
+
| `ortho-fabric` | `org.ortho32.fabric` | `FabricCommand`, `FabricCompletion`, `FabricAddress/Opcode/Epoch/Slot` |
|
| 57 |
+
| `ortho-compute` | `org.ortho32.compute` | Scalar compute submission |
|
| 58 |
+
| `ortho-tensor` | `org.ortho32.tensor` | `Tensor`, `TensorShape/Buffer/Job/Operation/Result`, `TensorLatency` |
|
| 59 |
+
| `ortho-trace` | `org.ortho32.trace` | `ExecutionTrace`, `CycleRecord`, `TraceHash`, `TraceComparator` |
|
| 60 |
+
| `ortho-verify` | `org.ortho32.verify` | `TheoremId`, `TheoremResult`, `VerificationStatus/Report`, `CrossVerificationResult` |
|
| 61 |
+
| `ortho-security` | `org.ortho32.security` | `Capability`, `Permission`, `SecurityContext`, `Attestation` |
|
| 62 |
+
| `ortho-agent` | `org.ortho32.agent` | `AgentIntent`, `AgentTask`, `AgentResult`, `AgentCapability` |
|
| 63 |
+
| `ortho-transport` | `org.ortho32.transport` | `OrthoTransport` (internal), `SimulatorTransport`, `NativeHostTransport`, `PCIe/USB/Ethernet` |
|
| 64 |
+
| `ortho-system` | `org.ortho32.system` | System utilities, versioning |
|
| 65 |
+
|
| 66 |
+
Per-module JARs + aggregate `ortho32-sdk.jar`, sources JAR, Javadoc JAR, Maven publication metadata, reproducible builds, checksums, dependency locking.
|
| 67 |
+
|
| 68 |
+
## Transport options
|
| 69 |
+
|
| 70 |
+
All transports expose the same `OrthoSession` API. Application code is transport-agnostic.
|
| 71 |
+
|
| 72 |
+
| Transport | Class | Use |
|
| 73 |
+
|---|---|---|
|
| 74 |
+
| **Simulator** | `SimulatorTransport` | Deterministic fake fabric, offline tests, CI. Required. No hardware. |
|
| 75 |
+
| **PCIe** | `PCIeTransport` | Native host service over PCIe BAR |
|
| 76 |
+
| **USB** | `USBTransport` | USB-attached ORTHO device |
|
| 77 |
+
| **Ethernet** | `EthernetTransport` | Remote ORTHO fabric over UDP/TCP |
|
| 78 |
+
| **Native** | `NativeHostTransport` | JNI bridge to ORTHO Host Service |
|
| 79 |
+
|
| 80 |
+
```java
|
| 81 |
+
// Explicit simulator (tests/examples)
|
| 82 |
+
OrthoRuntime runtime = OrthoRuntime.open(new SimulatorTransport());
|
| 83 |
+
// Production - auto-detect or inject via service loader
|
| 84 |
+
OrthoRuntime runtime = OrthoRuntime.open();
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
> Rule: `FabricCommand` is the logical API. Applications never write PCIe BAR registers.
|
| 88 |
+
|
| 89 |
+
## Versioning
|
| 90 |
+
|
| 91 |
+
Semantic versioning for public Java APIs. Compatibility is a tuple:
|
| 92 |
+
|
| 93 |
+
```
|
| 94 |
+
SDK-Version + Fabric-Protocol-Version + Device-ABI-Version
|
| 95 |
+
```
|
| 96 |
+
|
| 97 |
+
Access via `OrthoVersion`:
|
| 98 |
+
|
| 99 |
+
```java
|
| 100 |
+
OrthoVersion v = OrthoRuntime.open().version();
|
| 101 |
+
System.out.println(v.sdkVersion()); // e.g. 0.1.0
|
| 102 |
+
System.out.println(v.fabricProtocolVersion()); // e.g. 1
|
| 103 |
+
System.out.println(v.deviceABIVersion()); // e.g. 2
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
- **SDK version** — bumped on API change; follows SemVer
|
| 107 |
+
- **Fabric protocol version** — bumped on wire-format change
|
| 108 |
+
- **Device ABI version** — bumped on scratchpad / register map change
|
| 109 |
+
- `OrthoRuntime` checks compatibility on `openSession()` and fails fast on mismatch
|
| 110 |
+
|
| 111 |
+
See `CHANGELOG.md` for history.
|
| 112 |
+
|
| 113 |
+
## Build instructions
|
| 114 |
+
|
| 115 |
+
Requirements: Java 21 toolchain, Gradle 8.x
|
| 116 |
+
|
| 117 |
+
```bash
|
| 118 |
+
git clone https://github.com/ortho32/ortho32-sdk-java.git
|
| 119 |
+
cd ortho32-sdk-java
|
| 120 |
+
./gradlew build # all modules, tests with SimulatorTransport
|
| 121 |
+
./gradlew :integration-tests:test --info # integration tests only (no hardware)
|
| 122 |
+
./gradlew publishToMavenLocal # artifacts to ~/.m2
|
| 123 |
+
./gradlew javadoc # aggregated Javadoc
|
| 124 |
+
```
|
| 125 |
+
|
| 126 |
+
Reproducible builds, dependency locking (`gradle.lockfile`), checksums. Gradle Kotlin DSL.
|
| 127 |
+
|
| 128 |
+
## Examples
|
| 129 |
+
|
| 130 |
+
All examples run without hardware via `SimulatorTransport`.
|
| 131 |
+
|
| 132 |
+
| Example | Path | Description |
|
| 133 |
+
|---|---|---|
|
| 134 |
+
| device-list | `examples/device-list` | Enumerate and print available devices |
|
| 135 |
+
| tensor-run | `examples/tensor-run` | Build `TensorJob`, submit `TMUL`, print cycles & `traceHash` |
|
| 136 |
+
| trace-replay | `examples/trace-replay` | Capture trace, compute hash, replay, compare (H=0) |
|
| 137 |
+
| proof-verify | `examples/proof-verify` | Verify 12 theorems via `VerifyClient`, table with Lean/HOL columns |
|
| 138 |
+
| agent-client | `examples/agent-client` | Dispatch `AgentTask` via `AgentClient`, print result |
|
| 139 |
+
|
| 140 |
+
Run:
|
| 141 |
+
|
| 142 |
+
```bash
|
| 143 |
+
./gradlew :examples:device-list:run
|
| 144 |
+
./gradlew :examples:tensor-run:run
|
| 145 |
+
./gradlew :examples:trace-replay:run
|
| 146 |
+
./gradlew :examples:proof-verify:run
|
| 147 |
+
./gradlew :examples:agent-client:run
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
## API style
|
| 151 |
+
|
| 152 |
+
- Immutable value objects; `record` where appropriate
|
| 153 |
+
- No raw native pointers in public API
|
| 154 |
+
- No `Map<String,Object>` when schema exists
|
| 155 |
+
- Async via `CompletableFuture`, streaming via `Flow.Publisher`
|
| 156 |
+
- Typed exceptions (`OrthoException` hierarchy)
|
| 157 |
+
- `AutoCloseable` sessions and transports
|
| 158 |
+
|
| 159 |
+
## Contributing
|
| 160 |
+
|
| 161 |
+
1. Fork, create feature branch
|
| 162 |
+
2. `./gradlew build` — must pass with `SimulatorTransport` (no hardware)
|
| 163 |
+
3. Add schema + Javadoc for new public types
|
| 164 |
+
4. Update `CHANGELOG.md`
|
| 165 |
+
5. PR with determinism proof (`TraceHash` equality) where applicable
|
| 166 |
+
|
| 167 |
+
License: MIT. See `LICENSE`.
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
---
|
| 171 |
+
|
| 172 |
+
## Sovereign Boundary
|
| 173 |
+
|
| 174 |
+
This repository operates under the **SnapKitty Method**: public by default, sovereign by construction.
|
| 175 |
+
|
| 176 |
+
```
|
| 177 |
+
CODE → PUBLIC (this repository)
|
| 178 |
+
PROOF → PUBLIC (Lean 4 / formal verification artifacts)
|
| 179 |
+
SPEC → PUBLIC (interfaces, schemas, invariants)
|
| 180 |
+
HISTORY → PUBLIC (cryptographic provenance, WORM-sealed)
|
| 181 |
+
|
| 182 |
+
AUTHORITY → SOVEREIGN (Bel Esprit D'Accord Irrevocable Trust)
|
| 183 |
+
STATE → SOVEREIGN (credentials, private data, operational secrets)
|
| 184 |
+
EXECUTION → AUTHORIZED (requires sovereign state — not in this repo)
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
> **"Here is the machine. You do not own the state it operates on."**
|
| 188 |
+
|
| 189 |
+
Reading the source does not grant execution authority. Forking the repo does not grant deployment rights. The code is verifiable. The authority is not transferable.
|
| 190 |
+
|
| 191 |
+
**[→ Full architecture: SOVEREIGN_METHOD.md](./SOVEREIGN_METHOD.md)**
|
| 192 |
+
|
| 193 |
+
**[→ License terms: LICENSE](./LICENSE)** · **[→ IP estate: NOTICE](./NOTICE)**
|
| 194 |
+
|
| 195 |
+
---
|
| 196 |
+
|
| 197 |
+
*Copyright (C) 2026 Bel Esprit D'Accord Irrevocable Trust (EIN 42-697643) · `Ω = TRUST ∧ CODE`*
|
SOVEREIGN_METHOD.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# THE SNAPKITTY METHOD
|
| 2 |
+
|
| 3 |
+
## PUBLIC BY DEFAULT. SOVEREIGN BY CONSTRUCTION.
|
| 4 |
+
|
| 5 |
+
> **Nothing needs to be hidden if the boundary between public knowledge and sovereign execution is formally defined.**
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## The Boundary
|
| 10 |
+
|
| 11 |
+
```
|
| 12 |
+
CODE → PUBLIC
|
| 13 |
+
PROOF → PUBLIC
|
| 14 |
+
SPEC → PUBLIC
|
| 15 |
+
TESTS → PUBLIC
|
| 16 |
+
HISTORY → PUBLIC
|
| 17 |
+
PROVENANCE → PUBLIC
|
| 18 |
+
|
| 19 |
+
AUTHORITY → SOVEREIGN
|
| 20 |
+
STATE → SOVEREIGN
|
| 21 |
+
SECRETS → SOVEREIGN
|
| 22 |
+
EXECUTION → AUTHORIZED
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
The source is public. The **state, credentials, execution authority, and deployment boundaries** remain sovereign.
|
| 26 |
+
|
| 27 |
+
This is not: *"Here is the fake public version."*
|
| 28 |
+
|
| 29 |
+
This is: **"Here is the machine. You don't own the state it operates on."**
|
| 30 |
+
|
| 31 |
+
---
|
| 32 |
+
|
| 33 |
+
## No Stubs. Proofs Instead.
|
| 34 |
+
|
| 35 |
+
If something can be published safely → publish the **real implementation**.
|
| 36 |
+
|
| 37 |
+
If something cannot be published → publish the **formal boundary** describing what it is allowed to do.
|
| 38 |
+
|
| 39 |
+
No theatrical fake API. No TODO implementations. No repository whose only purpose is to look open.
|
| 40 |
+
|
| 41 |
+
---
|
| 42 |
+
|
| 43 |
+
## Cryptographic Provenance
|
| 44 |
+
|
| 45 |
+
Every artifact carries a cryptographic provenance record:
|
| 46 |
+
|
| 47 |
+
```
|
| 48 |
+
ARTIFACT → HASH → SEAL → COMMIT → VERIFICATION → IMMUTABLE PROVENANCE
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
The repository is an evidence trail. Not merely a source-code dump.
|
| 52 |
+
|
| 53 |
+
```
|
| 54 |
+
SHA-256 · Merkle relationships · Ed25519 signatures · WORM records · reproducible builds · formal verification
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
The objective is not: *"This code exists."*
|
| 58 |
+
|
| 59 |
+
It is: **"This artifact existed in this state, was produced through this transformation, and can be independently verified."**
|
| 60 |
+
|
| 61 |
+
---
|
| 62 |
+
|
| 63 |
+
## Automated Provenance Pipeline
|
| 64 |
+
|
| 65 |
+
```
|
| 66 |
+
COMMIT → SCHEMA CHECK → SECRET CHECK → LICENSE CHECK → PROVENANCE CHECK
|
| 67 |
+
→ TEST → FORMAL VERIFICATION → SEAL → PUBLISH
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
A failed invariant stops publication. The system does not negotiate with the failure.
|
| 71 |
+
|
| 72 |
+
```
|
| 73 |
+
INVARIANT FAILED → NO → NO SEAL → NO RELEASE
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
---
|
| 77 |
+
|
| 78 |
+
## AI Agents — Constrained Builders
|
| 79 |
+
|
| 80 |
+
Agents operate inside explicit boundaries:
|
| 81 |
+
|
| 82 |
+
```
|
| 83 |
+
INPUT → AGENT → PROPOSED CHANGE → TEST → STATIC ANALYSIS
|
| 84 |
+
→ FORMAL CHECK → HUMAN / POLICY GATE → CRYPTOGRAPHIC SEAL → MERGE
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
An agent cannot declare its own output correct. It must satisfy an external constraint.
|
| 88 |
+
|
| 89 |
+
> **An agent may propose state transitions. It may not unilaterally define truth.**
|
| 90 |
+
|
| 91 |
+
---
|
| 92 |
+
|
| 93 |
+
## The Zero-Sorry Boundary
|
| 94 |
+
|
| 95 |
+
```
|
| 96 |
+
THEOREM → LEAN 4 → PROOF → ZERO SORRY → VERIFIED ARTIFACT
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
The repository contains the proof. The verifier independently executes the proof.
|
| 100 |
+
|
| 101 |
+
Instead of: *"Trust the developer."*
|
| 102 |
+
|
| 103 |
+
The architecture moves toward: **"Verify the invariant."**
|
| 104 |
+
|
| 105 |
+
---
|
| 106 |
+
|
| 107 |
+
## Public Code ≠ Public Authority
|
| 108 |
+
|
| 109 |
+
```
|
| 110 |
+
Open Source ≠ Open Authority
|
| 111 |
+
Public Code ≠ Public Control
|
| 112 |
+
```
|
| 113 |
+
|
| 114 |
+
A public repository exposes architecture, algorithms, interfaces, schemas, tests, proofs, build systems, and documentation — without exposing credentials, deployment authority, operational state, or execution control.
|
| 115 |
+
|
| 116 |
+
That is the central SnapKitty architectural boundary.
|
| 117 |
+
|
| 118 |
+
---
|
| 119 |
+
|
| 120 |
+
## The Principle
|
| 121 |
+
|
| 122 |
+
> **Don't hide the machine.**
|
| 123 |
+
>
|
| 124 |
+
> **Make the machine verifiable.**
|
| 125 |
+
>
|
| 126 |
+
> **Keep control at the execution boundary.**
|
| 127 |
+
|
| 128 |
+
**PUBLIC SUBSTRATE. SOVEREIGN STATE. FORMAL CONSTRAINTS. CRYPTOGRAPHIC PROVENANCE. ZERO-SORRY WHERE PROVABLE.**
|
| 129 |
+
|
| 130 |
+
---
|
| 131 |
+
|
| 132 |
+
## Trust
|
| 133 |
+
|
| 134 |
+
**Bel Esprit D'Accord Irrevocable Trust (EIN 42-697643)**
|
| 135 |
+
SnapKitty Collective Limited (FLP)
|
| 136 |
+
Operators: Ahmad Ali Parr · Jessica Westerhoff
|
| 137 |
+
Web: https://github.com/SNAPKITTYWEST
|
| 138 |
+
|
| 139 |
+
`Ω = TRUST ∧ CODE`
|
build.gradle.kts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
| 2 |
+
import java.security.MessageDigest
|
| 3 |
+
|
| 4 |
+
plugins {
|
| 5 |
+
`java-library`
|
| 6 |
+
`maven-publish`
|
| 7 |
+
signing
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
group = "org.ortho32"
|
| 11 |
+
version = "0.1.0"
|
| 12 |
+
|
| 13 |
+
subprojects {
|
| 14 |
+
apply(plugin = "java-library")
|
| 15 |
+
apply(plugin = "maven-publish")
|
| 16 |
+
apply(plugin = "signing")
|
| 17 |
+
|
| 18 |
+
group = rootProject.group
|
| 19 |
+
version = rootProject.version
|
| 20 |
+
|
| 21 |
+
java {
|
| 22 |
+
toolchain {
|
| 23 |
+
languageVersion.set(JavaLanguageVersion.of(21))
|
| 24 |
+
}
|
| 25 |
+
withSourcesJar()
|
| 26 |
+
withJavadocJar()
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
tasks.withType<JavaCompile> {
|
| 30 |
+
options.encoding = "UTF-8"
|
| 31 |
+
options.release.set(21)
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
tasks.withType<Javadoc> {
|
| 35 |
+
options.encoding = "UTF-8"
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
tasks.withType<AbstractArchiveTask> {
|
| 39 |
+
isPreserveFileTimestamps = false
|
| 40 |
+
isReproducibleFileOrder = true
|
| 41 |
+
dirPermissions { unix("0755") }
|
| 42 |
+
filePermissions { unix("0644") }
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
tasks.withType<Jar> {
|
| 46 |
+
manifest {
|
| 47 |
+
attributes(
|
| 48 |
+
"Implementation-Title" to project.name,
|
| 49 |
+
"Implementation-Version" to project.version,
|
| 50 |
+
"Implementation-Vendor" to "ORTHO-32"
|
| 51 |
+
)
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
repositories {
|
| 56 |
+
mavenCentral()
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// JUnit BOM available to every module
|
| 60 |
+
dependencies {
|
| 61 |
+
"testImplementation"(platform("org.junit:junit-bom:5.11.0"))
|
| 62 |
+
"testImplementation"("org.junit.jupiter:junit-jupiter")
|
| 63 |
+
"testRuntimeOnly"("org.junit.platform:junit-platform-launcher")
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
tasks.test {
|
| 67 |
+
useJUnitPlatform()
|
| 68 |
+
testLogging { events("passed", "skipped", "failed") }
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
publishing {
|
| 72 |
+
publications {
|
| 73 |
+
create<MavenPublication>("maven") {
|
| 74 |
+
from(components["java"])
|
| 75 |
+
pom {
|
| 76 |
+
name.set("ORTHO-32 ${project.name}")
|
| 77 |
+
description.set("ORTHO-32 Java SDK - ${project.name}")
|
| 78 |
+
url.set("https://github.com/ortho32/ortho32-sdk-java")
|
| 79 |
+
licenses {
|
| 80 |
+
license {
|
| 81 |
+
name.set("Apache-2.0")
|
| 82 |
+
url.set("https://www.apache.org/licenses/LICENSE-2.0")
|
| 83 |
+
}
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
// Checksum generation for reproducible builds
|
| 91 |
+
tasks.register("generateChecksums") {
|
| 92 |
+
group = "verification"
|
| 93 |
+
description = "Generate SHA-256 checksums for all JAR artifacts"
|
| 94 |
+
dependsOn(tasks.named("build"))
|
| 95 |
+
doLast {
|
| 96 |
+
val digest = MessageDigest.getInstance("SHA-256")
|
| 97 |
+
fileTree(layout.buildDirectory.dir("libs")).forEach { file ->
|
| 98 |
+
if (file.isFile && file.extension == "jar") {
|
| 99 |
+
val hash = digest.digest(file.readBytes()).joinToString("") { "%02x".format(it) }
|
| 100 |
+
val checksumFile = file.resolveSibling("${file.name}.sha256")
|
| 101 |
+
checksumFile.writeText("$hash ${file.name}\n")
|
| 102 |
+
}
|
| 103 |
+
}
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
tasks.named("build") { finalizedBy("generateChecksums") }
|
| 107 |
+
|
| 108 |
+
// Dependency locking
|
| 109 |
+
dependencyLocking {
|
| 110 |
+
lockAllConfigurations()
|
| 111 |
+
}
|
| 112 |
+
}
|
examples/agent-client/src/main/java/org/ortho32/examples/AgentClientExample.java
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.examples;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.OrthoRuntime;
|
| 4 |
+
import org.ortho32.OrthoSession;
|
| 5 |
+
import org.ortho32.agent.AgentIntent;
|
| 6 |
+
import org.ortho32.agent.AgentResult;
|
| 7 |
+
import org.ortho32.agent.AgentTask;
|
| 8 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 9 |
+
|
| 10 |
+
import java.time.Duration;
|
| 11 |
+
import java.util.Map;
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Dispatch an AgentTask via AgentClient, print result.
|
| 15 |
+
* Uses SimulatorTransport - no hardware needed.
|
| 16 |
+
* Agents interact via typed intents, never directly mutating desktop state.
|
| 17 |
+
*/
|
| 18 |
+
public class AgentClientExample {
|
| 19 |
+
public static void main(String[] args) throws Exception {
|
| 20 |
+
SimulatorTransport simulator = new SimulatorTransport();
|
| 21 |
+
try (OrthoRuntime runtime = openRuntime(simulator);
|
| 22 |
+
OrthoSession session = runtime.openSession()) {
|
| 23 |
+
|
| 24 |
+
AgentIntent intent = new AgentIntent(
|
| 25 |
+
"intent-001",
|
| 26 |
+
"analyze",
|
| 27 |
+
"trace",
|
| 28 |
+
Map.of("query", "summarize last TMUL", "format", "json"),
|
| 29 |
+
Map.of("maxCycles", 1000)
|
| 30 |
+
);
|
| 31 |
+
|
| 32 |
+
AgentTask task = new AgentTask(
|
| 33 |
+
"task-001",
|
| 34 |
+
intent,
|
| 35 |
+
session.context(),
|
| 36 |
+
Duration.ofSeconds(10)
|
| 37 |
+
);
|
| 38 |
+
|
| 39 |
+
// Via typed AgentClient
|
| 40 |
+
AgentResult result = session.agent().dispatch(task).join();
|
| 41 |
+
|
| 42 |
+
System.out.println("taskId: " + result.taskId());
|
| 43 |
+
System.out.println("status: " + result.status());
|
| 44 |
+
System.out.println("cycles: " + result.cycles());
|
| 45 |
+
System.out.println("auditId: " + result.auditId());
|
| 46 |
+
System.out.println("output: " + result.output());
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 51 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 52 |
+
if (m.getName().equals("open") && m.getParameterCount() == 1
|
| 53 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 54 |
+
try {
|
| 55 |
+
return (OrthoRuntime) m.invoke(null, transport);
|
| 56 |
+
} catch (Exception e) {
|
| 57 |
+
throw new RuntimeException(e);
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
return OrthoRuntime.open();
|
| 62 |
+
}
|
| 63 |
+
}
|
examples/device-list/src/main/java/org/ortho32/examples/DeviceListExample.java
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.examples;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.OrthoRuntime;
|
| 4 |
+
import org.ortho32.OrthoSession;
|
| 5 |
+
import org.ortho32.device.OrthoDevice;
|
| 6 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 7 |
+
|
| 8 |
+
/**
|
| 9 |
+
* Enumerate and print available devices using SimulatorTransport.
|
| 10 |
+
* No hardware needed - SimulatorTransport provides deterministic fake fabric.
|
| 11 |
+
*/
|
| 12 |
+
public class DeviceListExample {
|
| 13 |
+
public static void main(String[] args) throws Exception {
|
| 14 |
+
// Explicit SimulatorTransport usage - deterministic offline fabric
|
| 15 |
+
SimulatorTransport simulator = new SimulatorTransport();
|
| 16 |
+
try (OrthoRuntime runtime = openRuntime(simulator);
|
| 17 |
+
OrthoSession session = runtime.openSession()) {
|
| 18 |
+
|
| 19 |
+
System.out.println("SDK version: " + runtime.version());
|
| 20 |
+
System.out.println("Fabric protocol: " + runtime.version().fabricProtocolVersion());
|
| 21 |
+
System.out.println("Device ABI: " + runtime.version().deviceABIVersion());
|
| 22 |
+
|
| 23 |
+
var devices = session.devices().list();
|
| 24 |
+
if (devices.isEmpty()) {
|
| 25 |
+
System.out.println("No devices found.");
|
| 26 |
+
} else {
|
| 27 |
+
System.out.println("Found " + devices.size() + " device(s):");
|
| 28 |
+
for (OrthoDevice d : devices) {
|
| 29 |
+
System.out.printf(" id=%s name=%s transport=%s arch=%s fw=%s caps=%s state=%s%n",
|
| 30 |
+
d.id(),
|
| 31 |
+
d.info().name(),
|
| 32 |
+
d.info().transport(),
|
| 33 |
+
d.info().architecture(),
|
| 34 |
+
d.info().firmwareVersion(),
|
| 35 |
+
d.capabilities(),
|
| 36 |
+
d.state());
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
// Also demonstrate firstAvailable helper
|
| 40 |
+
try {
|
| 41 |
+
OrthoDevice first = session.devices().firstAvailable();
|
| 42 |
+
System.out.println("firstAvailable: " + first.id());
|
| 43 |
+
} catch (Exception e) {
|
| 44 |
+
System.out.println("firstAvailable: none (" + e.getMessage() + ")");
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 50 |
+
// Try OrthoRuntime.open(OrthoTransport) if present, otherwise fallback to open()
|
| 51 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 52 |
+
if (m.getName().equals("open") && m.getParameterCount() == 1
|
| 53 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 54 |
+
try {
|
| 55 |
+
return (OrthoRuntime) m.invoke(null, transport);
|
| 56 |
+
} catch (Exception e) {
|
| 57 |
+
throw new RuntimeException(e);
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
return OrthoRuntime.open();
|
| 62 |
+
}
|
| 63 |
+
}
|
examples/proof-verify/src/main/java/org/ortho32/examples/ProofVerifyExample.java
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.examples;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.OrthoRuntime;
|
| 4 |
+
import org.ortho32.OrthoSession;
|
| 5 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 6 |
+
import org.ortho32.verify.CrossVerificationResult;
|
| 7 |
+
import org.ortho32.verify.TheoremId;
|
| 8 |
+
import org.ortho32.verify.TheoremResult;
|
| 9 |
+
import org.ortho32.verify.VerificationReport;
|
| 10 |
+
import org.ortho32.verify.VerificationStatus;
|
| 11 |
+
|
| 12 |
+
import java.util.List;
|
| 13 |
+
|
| 14 |
+
/**
|
| 15 |
+
* Verify all 12 theorems via VerifyClient, print status table with Lean and HOL columns separate.
|
| 16 |
+
* Uses SimulatorTransport - no hardware needed.
|
| 17 |
+
*/
|
| 18 |
+
public class ProofVerifyExample {
|
| 19 |
+
public static void main(String[] args) throws Exception {
|
| 20 |
+
SimulatorTransport simulator = new SimulatorTransport();
|
| 21 |
+
try (OrthoRuntime runtime = openRuntime(simulator);
|
| 22 |
+
OrthoSession session = runtime.openSession()) {
|
| 23 |
+
|
| 24 |
+
VerificationReport report = session.verify().verifyAll().join();
|
| 25 |
+
// Fallback: if verify().verifyAll() not present, try VerifyClient
|
| 26 |
+
if (report == null) {
|
| 27 |
+
var client = session.verify();
|
| 28 |
+
// attempt via reflection for VerifyClient name
|
| 29 |
+
try {
|
| 30 |
+
var m = client.getClass().getMethod("verificationReport");
|
| 31 |
+
report = (VerificationReport) m.invoke(client);
|
| 32 |
+
} catch (Exception ignore) {}
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
List<TheoremResult> results;
|
| 36 |
+
if (report != null) {
|
| 37 |
+
results = report.theorems();
|
| 38 |
+
System.out.println("Checker: " + report.checkerVersion() + " sourceHash=" + report.sourceHash() + " at " + report.timestamp());
|
| 39 |
+
} else {
|
| 40 |
+
// Synthetic demo if offline
|
| 41 |
+
results = session.verify().allTheorems();
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
System.out.printf("%-12s | %-14s | %-14s | %-10s | sorry | assumptions%n", "Theorem", "LEAN4", "HOL_LIGHT", "Agreement");
|
| 45 |
+
System.out.println("--------------------------------------------------------------------------------");
|
| 46 |
+
|
| 47 |
+
for (TheoremId tid : TheoremId.allTwelve()) {
|
| 48 |
+
TheoremResult lean = find(results, tid, "LEAN4");
|
| 49 |
+
TheoremResult hol = find(results, tid, "HOL_LIGHT");
|
| 50 |
+
String leanStatus = lean != null ? lean.status().name() : "UNCHECKED";
|
| 51 |
+
String holStatus = hol != null ? hol.status().name() : "UNCHECKED";
|
| 52 |
+
String agreement = "UNCHECKED";
|
| 53 |
+
if (lean != null && hol != null) {
|
| 54 |
+
CrossVerificationResult cross = CrossVerificationResult.of(lean, hol);
|
| 55 |
+
agreement = cross.agreement().name();
|
| 56 |
+
}
|
| 57 |
+
System.out.printf("%-12s | %-14s | %-14s | %-10s | %-5s | %s%n",
|
| 58 |
+
tid.value(),
|
| 59 |
+
leanStatus,
|
| 60 |
+
holStatus,
|
| 61 |
+
agreement,
|
| 62 |
+
lean != null ? lean.sorryCount() : "-",
|
| 63 |
+
lean != null ? lean.assumptions() : "[]");
|
| 64 |
+
}
|
| 65 |
+
System.out.println("\nNote: VERIFIED != TESTED != ASSUMED. Only real checker output sets status.");
|
| 66 |
+
}
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
private static TheoremResult find(List<TheoremResult> list, TheoremId id, String system) {
|
| 70 |
+
if (list == null) return null;
|
| 71 |
+
for (var r : list) {
|
| 72 |
+
if (r.id().equals(id) && r.system().name().equals(system)) return r;
|
| 73 |
+
}
|
| 74 |
+
return null;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 78 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 79 |
+
if (m.getName().equals("open") && m.getParameterCount() == 1
|
| 80 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 81 |
+
try {
|
| 82 |
+
return (OrthoRuntime) m.invoke(null, transport);
|
| 83 |
+
} catch (Exception e) {
|
| 84 |
+
throw new RuntimeException(e);
|
| 85 |
+
}
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
return OrthoRuntime.open();
|
| 89 |
+
}
|
| 90 |
+
}
|
examples/tensor-run/src/main/java/org/ortho32/examples/TensorRunExample.java
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.examples;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.OrthoRuntime;
|
| 4 |
+
import org.ortho32.OrthoSession;
|
| 5 |
+
import org.ortho32.device.OrthoDevice;
|
| 6 |
+
import org.ortho32.tensor.Tensor;
|
| 7 |
+
import org.ortho32.tensor.TensorJob;
|
| 8 |
+
import org.ortho32.tensor.TensorOperation;
|
| 9 |
+
import org.ortho32.tensor.TensorResult;
|
| 10 |
+
import org.ortho32.tensor.TensorShape;
|
| 11 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Build TensorJob, submit TMUL, print cycles and traceHash.
|
| 15 |
+
* Uses SimulatorTransport - no hardware needed.
|
| 16 |
+
*/
|
| 17 |
+
public class TensorRunExample {
|
| 18 |
+
public static void main(String[] args) throws Exception {
|
| 19 |
+
SimulatorTransport simulator = new SimulatorTransport();
|
| 20 |
+
try (OrthoRuntime runtime = openRuntime(simulator);
|
| 21 |
+
OrthoSession session = runtime.openSession()) {
|
| 22 |
+
|
| 23 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 24 |
+
System.out.println("Using device: " + device.id());
|
| 25 |
+
|
| 26 |
+
// 4x4 float32 matrices
|
| 27 |
+
TensorShape shape = new TensorShape(4, 4);
|
| 28 |
+
float[] dataA = new float[16];
|
| 29 |
+
float[] dataB = new float[16];
|
| 30 |
+
for (int i = 0; i < 16; i++) {
|
| 31 |
+
dataA[i] = i + 1;
|
| 32 |
+
dataB[i] = (i % 4 == 0) ? 1 : 0; // identity-ish
|
| 33 |
+
}
|
| 34 |
+
Tensor matrixA = Tensor.of(shape, dataA);
|
| 35 |
+
Tensor matrixB = Tensor.of(shape, dataB);
|
| 36 |
+
|
| 37 |
+
TensorJob job = TensorJob.builder()
|
| 38 |
+
.device(device)
|
| 39 |
+
.operation(TensorOperation.TMUL)
|
| 40 |
+
.inputA(matrixA)
|
| 41 |
+
.inputB(matrixB)
|
| 42 |
+
.build();
|
| 43 |
+
|
| 44 |
+
TensorResult result = session.tensor().submit(job).join();
|
| 45 |
+
|
| 46 |
+
System.out.println("cycles: " + result.cycles());
|
| 47 |
+
System.out.println("trace: " + result.traceHash());
|
| 48 |
+
System.out.println("completionCycle: " + result.completionCycle());
|
| 49 |
+
System.out.println("scratchpadUsed: " + result.scratchpadUsedBytes());
|
| 50 |
+
System.out.println("output shape: " + result.output().shape());
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 55 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 56 |
+
if (m.getName().equals("open") && m.getParameterCount() == 1
|
| 57 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 58 |
+
try {
|
| 59 |
+
return (OrthoRuntime) m.invoke(null, transport);
|
| 60 |
+
} catch (Exception e) {
|
| 61 |
+
throw new RuntimeException(e);
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
return OrthoRuntime.open();
|
| 66 |
+
}
|
| 67 |
+
}
|
examples/trace-replay/src/main/java/org/ortho32/examples/TraceReplayExample.java
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.examples;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.OrthoRuntime;
|
| 4 |
+
import org.ortho32.OrthoSession;
|
| 5 |
+
import org.ortho32.device.OrthoDevice;
|
| 6 |
+
import org.ortho32.tensor.Tensor;
|
| 7 |
+
import org.ortho32.tensor.TensorJob;
|
| 8 |
+
import org.ortho32.tensor.TensorOperation;
|
| 9 |
+
import org.ortho32.tensor.TensorResult;
|
| 10 |
+
import org.ortho32.tensor.TensorShape;
|
| 11 |
+
import org.ortho32.trace.ExecutionTrace;
|
| 12 |
+
import org.ortho32.trace.TraceComparison;
|
| 13 |
+
import org.ortho32.trace.TraceComparator;
|
| 14 |
+
import org.ortho32.trace.TraceHash;
|
| 15 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Capture trace, compute hash, replay, compare hashes (must be equal).
|
| 19 |
+
* Demonstrates H=0 determinism: same input -> same TraceHash.
|
| 20 |
+
*/
|
| 21 |
+
public class TraceReplayExample {
|
| 22 |
+
public static void main(String[] args) throws Exception {
|
| 23 |
+
SimulatorTransport simulator = new SimulatorTransport();
|
| 24 |
+
try (OrthoRuntime runtime = openRuntime(simulator);
|
| 25 |
+
OrthoSession session = runtime.openSession()) {
|
| 26 |
+
|
| 27 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 28 |
+
|
| 29 |
+
TensorShape shape = new TensorShape(4, 4);
|
| 30 |
+
float[] data = new float[16];
|
| 31 |
+
for (int i = 0; i < 16; i++) data[i] = i;
|
| 32 |
+
Tensor a = Tensor.of(shape, data);
|
| 33 |
+
Tensor b = Tensor.of(shape, data);
|
| 34 |
+
|
| 35 |
+
TensorJob job = TensorJob.builder()
|
| 36 |
+
.device(device)
|
| 37 |
+
.operation(TensorOperation.TMUL)
|
| 38 |
+
.inputA(a)
|
| 39 |
+
.inputB(b)
|
| 40 |
+
.build();
|
| 41 |
+
|
| 42 |
+
// First run
|
| 43 |
+
TensorResult r1 = session.tensor().submit(job).join();
|
| 44 |
+
ExecutionTrace trace1 = session.trace().capture(device, r1);
|
| 45 |
+
if (trace1 == null) {
|
| 46 |
+
// Fallback: use trace from result
|
| 47 |
+
trace1 = session.trace().getTrace(r1);
|
| 48 |
+
}
|
| 49 |
+
TraceHash hash1 = TraceHash.of(trace1);
|
| 50 |
+
System.out.println("run1 cycles=" + r1.cycles() + " hash=" + hash1 + " traceHash=" + r1.traceHash());
|
| 51 |
+
|
| 52 |
+
// Replay / second run with identical input
|
| 53 |
+
TensorResult r2 = session.tensor().submit(job).join();
|
| 54 |
+
ExecutionTrace trace2 = session.trace().capture(device, r2);
|
| 55 |
+
if (trace2 == null) trace2 = session.trace().getTrace(r2);
|
| 56 |
+
TraceHash hash2 = TraceHash.of(trace2);
|
| 57 |
+
System.out.println("run2 cycles=" + r2.cycles() + " hash=" + hash2 + " traceHash=" + r2.traceHash());
|
| 58 |
+
|
| 59 |
+
// Hashes must be equal for deterministic execution
|
| 60 |
+
System.out.println("hash1.equals(hash2): " + hash1.equals(hash2));
|
| 61 |
+
System.out.println("r1.traceHash == r2.traceHash: " + r1.traceHash().equals(r2.traceHash()));
|
| 62 |
+
|
| 63 |
+
TraceComparison cmp = TraceComparator.compare(trace1, trace2);
|
| 64 |
+
System.out.println("TraceComparator.equal: " + cmp.isEqual());
|
| 65 |
+
if (!cmp.isEqual()) {
|
| 66 |
+
System.out.println("mismatches: " + cmp.mismatches());
|
| 67 |
+
throw new AssertionError("Determinism violation: traces differ for identical input");
|
| 68 |
+
}
|
| 69 |
+
System.out.println("Replay verified: hashes equal and traces identical (H=0)");
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 74 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 75 |
+
if (m.getName().equals("open") && m.getParameterCount() == 1
|
| 76 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 77 |
+
try {
|
| 78 |
+
return (OrthoRuntime) m.invoke(null, transport);
|
| 79 |
+
} catch (Exception e) {
|
| 80 |
+
throw new RuntimeException(e);
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
return OrthoRuntime.open();
|
| 85 |
+
}
|
| 86 |
+
}
|
gradle/wrapper/gradle-wrapper.properties
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
distributionBase=GRADLE_USER_HOME
|
| 2 |
+
distributionPath=wrapper/dists
|
| 3 |
+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
| 4 |
+
networkTimeout=10000
|
| 5 |
+
validateDistributionUrl=true
|
| 6 |
+
zipStoreBase=GRADLE_USER_HOME
|
| 7 |
+
zipStorePath=wrapper/dists
|
integration-tests/build.gradle.kts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// integration-tests: exercises the full SDK against SimulatorTransport.
|
| 2 |
+
// No hardware required. All tests must pass with SimulatorTransport only.
|
| 3 |
+
plugins { java }
|
| 4 |
+
|
| 5 |
+
dependencies {
|
| 6 |
+
// Depend on ortho-core which transitively pulls all domain modules
|
| 7 |
+
testImplementation(project(":ortho-core"))
|
| 8 |
+
// Transport needed directly for SimulatorTransport tests
|
| 9 |
+
testImplementation(project(":ortho-transport"))
|
| 10 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/CrossVerifyTest.java
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.verify.CrossVerificationResult;
|
| 7 |
+
import org.ortho32.verify.CrossVerificationResult.Agreement;
|
| 8 |
+
import org.ortho32.verify.TheoremId;
|
| 9 |
+
import org.ortho32.verify.TheoremResult;
|
| 10 |
+
import org.ortho32.verify.VerificationStatus;
|
| 11 |
+
import org.ortho32.verify.VerificationSystem;
|
| 12 |
+
|
| 13 |
+
import java.util.List;
|
| 14 |
+
|
| 15 |
+
public class CrossVerifyTest {
|
| 16 |
+
|
| 17 |
+
@Test
|
| 18 |
+
public void mismatchCannotBeTreatedAsVerified() {
|
| 19 |
+
TheoremId id = TheoremId.of("THM_007");
|
| 20 |
+
|
| 21 |
+
TheoremResult lean = new TheoremResult(
|
| 22 |
+
id,
|
| 23 |
+
VerificationSystem.LEAN4,
|
| 24 |
+
VerificationStatus.VERIFIED,
|
| 25 |
+
List.of(),
|
| 26 |
+
"a".repeat(64),
|
| 27 |
+
0
|
| 28 |
+
);
|
| 29 |
+
TheoremResult hol = new TheoremResult(
|
| 30 |
+
id,
|
| 31 |
+
VerificationSystem.HOL_LIGHT,
|
| 32 |
+
VerificationStatus.FAILED,
|
| 33 |
+
List.of(),
|
| 34 |
+
"a".repeat(64),
|
| 35 |
+
0
|
| 36 |
+
);
|
| 37 |
+
|
| 38 |
+
CrossVerificationResult cross = CrossVerificationResult.of(lean, hol);
|
| 39 |
+
|
| 40 |
+
assertEquals(Agreement.MISMATCH, cross.agreement(),
|
| 41 |
+
"LEAN4=VERIFIED HOL_LIGHT=FAILED must yield MISMATCH");
|
| 42 |
+
|
| 43 |
+
// MISMATCH must never be treated as verified - any helper that maps MISMATCH to verified must fail
|
| 44 |
+
assertFalse(cross.isVerified(), "MISMATCH must not be considered verified");
|
| 45 |
+
assertFalse(cross.agreement() == Agreement.AGREE, "MISMATCH != AGREE");
|
| 46 |
+
|
| 47 |
+
// Assertion failure in any code that treats MISMATCH as VERIFIED
|
| 48 |
+
assertThrows(AssertionError.class, () -> {
|
| 49 |
+
if (cross.agreement() == Agreement.MISMATCH) {
|
| 50 |
+
// Simulate buggy code that would treat MISMATCH as verified
|
| 51 |
+
boolean treatAsVerified = cross.isVerified();
|
| 52 |
+
if (treatAsVerified) {
|
| 53 |
+
return; // would be wrong
|
| 54 |
+
}
|
| 55 |
+
// Enforce: treating MISMATCH as verified must throw
|
| 56 |
+
if (cross.agreement() != Agreement.AGREE) {
|
| 57 |
+
throw new AssertionError("Blocking failure: MISMATCH cannot be auto-resolved to VERIFIED");
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}, "MISMATCH must cause assertion failure when treated as VERIFIED");
|
| 61 |
+
|
| 62 |
+
// Also verify via status helper - VERIFIED.isFormallyVerified but cross is not
|
| 63 |
+
assertTrue(lean.status().isFormallyVerified());
|
| 64 |
+
assertFalse(hol.status().isFormallyVerified());
|
| 65 |
+
assertNotEquals(lean.status(), hol.status());
|
| 66 |
+
}
|
| 67 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/DeterminismTest.java
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.OrthoRuntime;
|
| 7 |
+
import org.ortho32.OrthoSession;
|
| 8 |
+
import org.ortho32.device.OrthoDevice;
|
| 9 |
+
import org.ortho32.tensor.Tensor;
|
| 10 |
+
import org.ortho32.tensor.TensorJob;
|
| 11 |
+
import org.ortho32.tensor.TensorOperation;
|
| 12 |
+
import org.ortho32.tensor.TensorResult;
|
| 13 |
+
import org.ortho32.tensor.TensorShape;
|
| 14 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 15 |
+
|
| 16 |
+
public class DeterminismTest {
|
| 17 |
+
|
| 18 |
+
@Test
|
| 19 |
+
public void identicalJobsProduceEqualTraceHash_H0() throws Exception {
|
| 20 |
+
SimulatorTransport transport = new SimulatorTransport();
|
| 21 |
+
try (OrthoRuntime runtime = openRuntime(transport);
|
| 22 |
+
OrthoSession session = runtime.openSession()) {
|
| 23 |
+
|
| 24 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 25 |
+
TensorShape shape = new TensorShape(4, 4);
|
| 26 |
+
float[] data = new float[16];
|
| 27 |
+
for (int i = 0; i < 16; i++) data[i] = i * 1.5f;
|
| 28 |
+
Tensor a = Tensor.of(shape, data);
|
| 29 |
+
Tensor b = Tensor.of(shape, data);
|
| 30 |
+
|
| 31 |
+
TensorJob job = TensorJob.builder()
|
| 32 |
+
.device(device)
|
| 33 |
+
.operation(TensorOperation.TMUL)
|
| 34 |
+
.inputA(a)
|
| 35 |
+
.inputB(b)
|
| 36 |
+
.build();
|
| 37 |
+
|
| 38 |
+
TensorResult result = session.tensor().submit(job).join();
|
| 39 |
+
TensorResult result2 = session.tensor().submit(job).join();
|
| 40 |
+
|
| 41 |
+
assertNotNull(result.traceHash());
|
| 42 |
+
assertNotNull(result2.traceHash());
|
| 43 |
+
// H=0 determinism: same input -> same TraceHash across N runs at Java layer
|
| 44 |
+
assertEquals(result.traceHash(), result2.traceHash(),
|
| 45 |
+
"Determinism violation: identical TensorJob must produce equal traceHash (H=0)");
|
| 46 |
+
assertEquals(result.cycles(), result2.cycles(), "cycles must be deterministic");
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 51 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 52 |
+
if (m.getName().equals("open") && m.getParameterCount()==1
|
| 53 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 54 |
+
try { return (OrthoRuntime) m.invoke(null, transport); } catch (Exception e) { throw new RuntimeException(e); }
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
return OrthoRuntime.open();
|
| 58 |
+
}
|
| 59 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/JavaRoutingTests.java
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.integration;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.*;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import java.time.Instant;
|
| 7 |
+
import java.util.Map;
|
| 8 |
+
import java.util.concurrent.TimeUnit;
|
| 9 |
+
|
| 10 |
+
import org.ortho32.core.OrthoSession;
|
| 11 |
+
import org.ortho32.core.ORTHOEventBus;
|
| 12 |
+
import org.ortho32.fabric.ORTHOBridge;
|
| 13 |
+
import org.ortho32.fabric.SimulatorTransport;
|
| 14 |
+
import org.ortho32.routing.*;
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* Java SDK routing tests – all run with SimulatorTransport. No hardware needed.
|
| 18 |
+
*/
|
| 19 |
+
class JavaRoutingTests {
|
| 20 |
+
|
| 21 |
+
private OrthoSession session;
|
| 22 |
+
private OrthoRouter router;
|
| 23 |
+
private OrthoRouteContext adminContext;
|
| 24 |
+
|
| 25 |
+
@BeforeEach
|
| 26 |
+
void setUp() {
|
| 27 |
+
// All tests use SimulatorTransport
|
| 28 |
+
session = OrthoSession.withSimulator("sess-test-" + System.nanoTime());
|
| 29 |
+
router = session.router();
|
| 30 |
+
adminContext = new OrthoRouteContext("test-user", null, session.sessionId(), "admin", Instant.now());
|
| 31 |
+
assertNotNull(router, "Router must be obtained via OrthoSession.router()");
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
@AfterEach
|
| 35 |
+
void tearDown() throws Exception {
|
| 36 |
+
session.close().get(1, TimeUnit.SECONDS);
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
// ---- test_route_parse_roundtrip ---------------------------------------
|
| 40 |
+
|
| 41 |
+
@Test
|
| 42 |
+
@DisplayName("test_route_parse_roundtrip: parse -> toUrl -> parse produces equal routes")
|
| 43 |
+
void test_route_parse_roundtrip() {
|
| 44 |
+
String original = "ortho://proof/rtl_deterministic";
|
| 45 |
+
OrthoRoute route = OrthoRoute.parse(original);
|
| 46 |
+
assertNotNull(route);
|
| 47 |
+
assertInstanceOf(OrthoRoute.ProofRoute.class, route);
|
| 48 |
+
|
| 49 |
+
String serialized = route.toUrl();
|
| 50 |
+
assertEquals(original, serialized, "toUrl must be canonical");
|
| 51 |
+
|
| 52 |
+
OrthoRoute reparsed = OrthoRoute.parse(serialized);
|
| 53 |
+
assertEquals(route, reparsed, "parse -> toUrl -> parse must produce equal routes");
|
| 54 |
+
assertEquals(reparsed.toUrl(), original);
|
| 55 |
+
|
| 56 |
+
// Additional round-trips
|
| 57 |
+
String[] urls = {
|
| 58 |
+
"ortho://app/terminal",
|
| 59 |
+
"ortho://trace/cycle/420",
|
| 60 |
+
"ortho://hardware/device/ortho0?op=tensor",
|
| 61 |
+
"ortho://ide/file/rtl/fabric/arbiter.sv?line=184",
|
| 62 |
+
"ortho://settings/security",
|
| 63 |
+
"https://github.com/ortho/ortho32"
|
| 64 |
+
};
|
| 65 |
+
for (String url : urls) {
|
| 66 |
+
OrthoRoute r = OrthoRoute.parse(url);
|
| 67 |
+
assertEquals(url, r.toUrl(), "round-trip failed for " + url);
|
| 68 |
+
assertEquals(r, OrthoRoute.parse(r.toUrl()));
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
// ---- test_agent_uses_intent_route -------------------------------------
|
| 73 |
+
|
| 74 |
+
@Test
|
| 75 |
+
@DisplayName("test_agent_uses_intent_route: agent dispatches IntentRoute not direct state mutation")
|
| 76 |
+
void test_agent_uses_intent_route() throws Exception {
|
| 77 |
+
// Simulate agent – must use OrthoRoute.IntentRoute, never raw string or direct state
|
| 78 |
+
OrthoRouteContext agentCtx = OrthoRouteContext.forAgent("agent-verify-1", session.sessionId(), "proofExecute");
|
| 79 |
+
|
| 80 |
+
// Agent creates a typed IntentRoute – not a raw String
|
| 81 |
+
OrthoRoute.IntentRoute intent = new OrthoRoute.IntentRoute("proof.verify", "rtl_deterministic", Map.of("mode","check"));
|
| 82 |
+
assertNotNull(intent.intent());
|
| 83 |
+
assertNotNull(intent.target());
|
| 84 |
+
assertEquals("proof.verify", intent.intent());
|
| 85 |
+
|
| 86 |
+
// Dispatch via router – this is the ONLY allowed path
|
| 87 |
+
OrthoRouteResult result = router.perform(intent, agentCtx).get(2, TimeUnit.SECONDS);
|
| 88 |
+
|
| 89 |
+
assertInstanceOf(OrthoRouteResult.Success.class, result);
|
| 90 |
+
OrthoRouteResult.Success success = (OrthoRouteResult.Success) result;
|
| 91 |
+
assertNotNull(success.output());
|
| 92 |
+
assertTrue(success.output().toString().contains("proof.verify"));
|
| 93 |
+
|
| 94 |
+
// Verify we did not mutate state directly – router path was IntentRoute
|
| 95 |
+
// The following would not compile if raw string routing were used:
|
| 96 |
+
// router.perform("proof.verify", ...) // <-- no such method, typed route required
|
| 97 |
+
assertInstanceOf(OrthoRoute.IntentRoute.class, intent);
|
| 98 |
+
|
| 99 |
+
// Ensure no direct State mutation API exists on the agent – compile-time guarantee
|
| 100 |
+
// If agent tried: agent.state.set(...), it would not exist; only router.perform is available
|
| 101 |
+
// We verify the intent round-trips via URL as well (same language as Swift)
|
| 102 |
+
String url = intent.toUrl();
|
| 103 |
+
assertTrue(url.startsWith("ortho://intent/"));
|
| 104 |
+
OrthoRoute reparsed = OrthoRoute.parse(url);
|
| 105 |
+
assertInstanceOf(OrthoRoute.IntentRoute.class, reparsed);
|
| 106 |
+
assertEquals(intent, reparsed);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
// ---- test_hardware_route_is_typed -------------------------------------
|
| 110 |
+
|
| 111 |
+
@Test
|
| 112 |
+
@DisplayName("test_hardware_route_is_typed: HardwareRoute fields are typed not raw strings")
|
| 113 |
+
void test_hardware_route_is_typed() throws Exception {
|
| 114 |
+
// HardwareRoute must have typed fields device: String, operation: String, params: Map
|
| 115 |
+
OrthoRoute.HardwareRoute hw = new OrthoRoute.HardwareRoute("ortho0", "tensor", Map.of("dtype","fp8"));
|
| 116 |
+
assertEquals("ortho0", hw.device());
|
| 117 |
+
assertEquals("tensor", hw.operation());
|
| 118 |
+
assertEquals("fp8", hw.params().get("dtype"));
|
| 119 |
+
|
| 120 |
+
// toUrl is structured, not ad-hoc string concatenation
|
| 121 |
+
String url = hw.toUrl();
|
| 122 |
+
assertTrue(url.startsWith("ortho://hardware/device/ortho0"));
|
| 123 |
+
assertTrue(url.contains("op=tensor"));
|
| 124 |
+
|
| 125 |
+
OrthoRoute parsed = OrthoRoute.parse(url);
|
| 126 |
+
assertInstanceOf(OrthoRoute.HardwareRoute.class, parsed);
|
| 127 |
+
OrthoRoute.HardwareRoute reparsed = (OrthoRoute.HardwareRoute) parsed;
|
| 128 |
+
assertEquals(hw.device(), reparsed.device());
|
| 129 |
+
assertEquals(hw.operation(), reparsed.operation());
|
| 130 |
+
|
| 131 |
+
// Perform via router – goes through HardwareRouter -> ORTHOBridge (SimulatorTransport) – not raw PCIe
|
| 132 |
+
OrthoRouteContext hwCtx = new OrthoRouteContext("hw-test", null, session.sessionId(), "hardwareAccess", Instant.now());
|
| 133 |
+
OrthoRouteResult result = router.perform(hw, hwCtx).get(2, TimeUnit.SECONDS);
|
| 134 |
+
// SimulatorTransport returns success
|
| 135 |
+
assertInstanceOf(OrthoRouteResult.Success.class, result);
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
// ---- test_route_result_sealed -----------------------------------------
|
| 139 |
+
|
| 140 |
+
@Test
|
| 141 |
+
@DisplayName("test_route_result_sealed: RouteResult is sealed – compiler forces handling all cases")
|
| 142 |
+
void test_route_result_sealed() throws Exception {
|
| 143 |
+
OrthoRoute route = OrthoRoute.parse("ortho://app/terminal");
|
| 144 |
+
OrthoRouteResult result = router.open(route, adminContext).get(2, TimeUnit.SECONDS);
|
| 145 |
+
|
| 146 |
+
// Exhaustive switch – compiler enforces all sealed permits; this must compile with --enable-preview
|
| 147 |
+
String handled = switch (result) {
|
| 148 |
+
case OrthoRouteResult.Success s -> "success:" + s.windowId();
|
| 149 |
+
case OrthoRouteResult.Failure f -> "failure:" + f.error().name();
|
| 150 |
+
case OrthoRouteResult.Deferred d -> "deferred:" + d.id();
|
| 151 |
+
};
|
| 152 |
+
assertNotNull(handled);
|
| 153 |
+
assertTrue(handled.startsWith("success:"));
|
| 154 |
+
|
| 155 |
+
// Failure case also exercises sealed handling
|
| 156 |
+
OrthoRouteContext noCap = new OrthoRouteContext("user", null, session.sessionId(), "readOnly", Instant.now());
|
| 157 |
+
OrthoRoute.HardwareRoute hw = new OrthoRoute.HardwareRoute("ortho0", "tensor", Map.of());
|
| 158 |
+
OrthoRouteResult denied = router.perform(hw, noCap).get(2, TimeUnit.SECONDS);
|
| 159 |
+
String handledDenied = switch (denied) {
|
| 160 |
+
case OrthoRouteResult.Success s -> "success";
|
| 161 |
+
case OrthoRouteResult.Failure f -> {
|
| 162 |
+
assertEquals(OrthoRouteError.CAPABILITY_DENIED, f.error());
|
| 163 |
+
yield "failure:" + f.error();
|
| 164 |
+
}
|
| 165 |
+
case OrthoRouteResult.Deferred d -> "deferred";
|
| 166 |
+
};
|
| 167 |
+
assertEquals("failure:CAPABILITY_DENIED", handledDenied);
|
| 168 |
+
|
| 169 |
+
// Verify router is sealed result – no raw string status
|
| 170 |
+
assertTrue(OrthoRouteResult.class.isSealed(), "OrthoRouteResult must be sealed");
|
| 171 |
+
assertEquals(3, OrthoRouteResult.class.getPermittedSubclasses().length);
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
@Test
|
| 175 |
+
@DisplayName("router obtained only via OrthoSession.router() – constructor not public")
|
| 176 |
+
void test_router_not_directly_constructed() {
|
| 177 |
+
// Verify OrthoRouter has no public constructor – only OrthoSession can create it
|
| 178 |
+
var ctors = OrthoRouter.class.getDeclaredConstructors();
|
| 179 |
+
for (var c : ctors) {
|
| 180 |
+
assertFalse(java.lang.reflect.Modifier.isPublic(c.getModifiers()), "OrthoRouter must not have public constructor – use OrthoSession.router()");
|
| 181 |
+
}
|
| 182 |
+
// The only way to get a router is via session
|
| 183 |
+
OrthoRouter r1 = session.router();
|
| 184 |
+
OrthoRouter r2 = session.router();
|
| 185 |
+
assertSame(r1, r2, "Same session must return same router instance");
|
| 186 |
+
}
|
| 187 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/SessionLifecycleTest.java
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.OrthoRuntime;
|
| 7 |
+
import org.ortho32.OrthoSession;
|
| 8 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 9 |
+
|
| 10 |
+
public class SessionLifecycleTest {
|
| 11 |
+
|
| 12 |
+
@Test
|
| 13 |
+
public void sessionLifecycleUsesAllSubclientsAndCleansUp() throws Exception {
|
| 14 |
+
SimulatorTransport transport = new SimulatorTransport();
|
| 15 |
+
OrthoRuntime runtime = openRuntime(transport);
|
| 16 |
+
assertNotNull(runtime);
|
| 17 |
+
|
| 18 |
+
OrthoSession session = runtime.openSession();
|
| 19 |
+
assertNotNull(session);
|
| 20 |
+
assertTrue(session instanceof AutoCloseable, "OrthoSession must be AutoCloseable");
|
| 21 |
+
|
| 22 |
+
// Use all sub-clients as per OrthoSession API
|
| 23 |
+
assertNotNull(session.devices(), "devices() must be present");
|
| 24 |
+
assertNotNull(session.tensor(), "tensor() must be present");
|
| 25 |
+
assertNotNull(session.trace(), "trace() must be present");
|
| 26 |
+
assertNotNull(session.verify(), "verify() must be present");
|
| 27 |
+
assertNotNull(session.security(), "security() must be present");
|
| 28 |
+
assertNotNull(session.agent(), "agent() must be present");
|
| 29 |
+
|
| 30 |
+
// Exercise devices
|
| 31 |
+
var devices = session.devices().list();
|
| 32 |
+
assertNotNull(devices);
|
| 33 |
+
|
| 34 |
+
// Context and version
|
| 35 |
+
assertNotNull(session.context(), "context must be present");
|
| 36 |
+
assertNotNull(runtime.version(), "version must be present");
|
| 37 |
+
|
| 38 |
+
// AutoCloseable cleanup via close()
|
| 39 |
+
session.close();
|
| 40 |
+
runtime.close();
|
| 41 |
+
|
| 42 |
+
// Verify closed resources throw or are marked closed
|
| 43 |
+
// After close, opening a new session on closed runtime should fail or new runtime works
|
| 44 |
+
try (OrthoRuntime r2 = openRuntime(new SimulatorTransport());
|
| 45 |
+
OrthoSession s2 = r2.openSession()) {
|
| 46 |
+
assertNotNull(s2.devices());
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
// Try-with-resources path
|
| 50 |
+
try (OrthoRuntime r3 = openRuntime(new SimulatorTransport());
|
| 51 |
+
OrthoSession s3 = r3.openSession()) {
|
| 52 |
+
assertDoesNotThrow(() -> s3.devices().list());
|
| 53 |
+
}
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 57 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 58 |
+
if (m.getName().equals("open") && m.getParameterCount()==1
|
| 59 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 60 |
+
try { return (OrthoRuntime) m.invoke(null, transport); } catch (Exception e) { throw new RuntimeException(e); }
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
return OrthoRuntime.open();
|
| 64 |
+
}
|
| 65 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/SimulatorTransportTest.java
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.fabric.FabricAddress;
|
| 7 |
+
import org.ortho32.fabric.FabricCommand;
|
| 8 |
+
import org.ortho32.fabric.FabricCompletion;
|
| 9 |
+
import org.ortho32.fabric.FabricOpcode;
|
| 10 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 11 |
+
|
| 12 |
+
import java.util.concurrent.TimeUnit;
|
| 13 |
+
|
| 14 |
+
public class SimulatorTransportTest {
|
| 15 |
+
|
| 16 |
+
@Test
|
| 17 |
+
public void connectAndSubmitFabricCommandVerifiesArchitecturalCycles() throws Exception {
|
| 18 |
+
SimulatorTransport transport = new SimulatorTransport();
|
| 19 |
+
transport.connect();
|
| 20 |
+
|
| 21 |
+
long sequence = 42L;
|
| 22 |
+
FabricCommand cmd = FabricCommand.builder()
|
| 23 |
+
.opcode(FabricOpcode.TENSOR)
|
| 24 |
+
.device("sim0")
|
| 25 |
+
.address(new FabricAddress(0x1000L))
|
| 26 |
+
.length(64)
|
| 27 |
+
.epoch(0)
|
| 28 |
+
.slot(0)
|
| 29 |
+
.sequence(sequence)
|
| 30 |
+
.payloadHash("a".repeat(64))
|
| 31 |
+
.flags(0)
|
| 32 |
+
.build();
|
| 33 |
+
|
| 34 |
+
// SimulatorTransport is deterministic fake fabric - no hardware
|
| 35 |
+
FabricCompletion completion = transport.submit(cmd).get(5, TimeUnit.SECONDS);
|
| 36 |
+
|
| 37 |
+
assertNotNull(completion, "completion must not be null");
|
| 38 |
+
assertEquals(sequence, completion.sequence(), "completion sequence must echo command sequence");
|
| 39 |
+
assertNotNull(completion.status(), "status must be present");
|
| 40 |
+
// Cycles are architectural integers, not wall-clock
|
| 41 |
+
assertTrue(completion.acceptedCycle() >= 0, "acceptedCycle must be >=0 architectural cycle");
|
| 42 |
+
assertTrue(completion.completionCycle() >= completion.acceptedCycle(),
|
| 43 |
+
"completionCycle must be >= acceptedCycle (architectural)");
|
| 44 |
+
assertNotNull(completion.resultHash(), "resultHash must be present");
|
| 45 |
+
assertNotNull(completion.traceRoot(), "traceRoot must be present");
|
| 46 |
+
|
| 47 |
+
transport.disconnect();
|
| 48 |
+
}
|
| 49 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/TensorJobTest.java
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.OrthoRuntime;
|
| 7 |
+
import org.ortho32.OrthoSession;
|
| 8 |
+
import org.ortho32.device.OrthoDevice;
|
| 9 |
+
import org.ortho32.tensor.Tensor;
|
| 10 |
+
import org.ortho32.tensor.TensorJob;
|
| 11 |
+
import org.ortho32.tensor.TensorLatency;
|
| 12 |
+
import org.ortho32.tensor.TensorOperation;
|
| 13 |
+
import org.ortho32.tensor.TensorResult;
|
| 14 |
+
import org.ortho32.tensor.TensorShape;
|
| 15 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 16 |
+
|
| 17 |
+
public class TensorJobTest {
|
| 18 |
+
|
| 19 |
+
@Test
|
| 20 |
+
public void submitTMUL4x4VerifiesLatencyAndTraceHash() throws Exception {
|
| 21 |
+
SimulatorTransport transport = new SimulatorTransport();
|
| 22 |
+
try (OrthoRuntime runtime = openRuntime(transport);
|
| 23 |
+
OrthoSession session = runtime.openSession()) {
|
| 24 |
+
|
| 25 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 26 |
+
assertNotNull(device, "firstAvailable device must exist on simulator");
|
| 27 |
+
|
| 28 |
+
TensorShape shape = new TensorShape(4, 4);
|
| 29 |
+
float[] a = new float[16];
|
| 30 |
+
float[] b = new float[16];
|
| 31 |
+
for (int i = 0; i < 16; i++) { a[i] = i; b[i] = i; }
|
| 32 |
+
|
| 33 |
+
Tensor tensorA = Tensor.of(shape, a);
|
| 34 |
+
Tensor tensorB = Tensor.of(shape, b);
|
| 35 |
+
|
| 36 |
+
TensorJob job = TensorJob.builder()
|
| 37 |
+
.device(device)
|
| 38 |
+
.operation(TensorOperation.TMUL)
|
| 39 |
+
.inputA(tensorA)
|
| 40 |
+
.inputB(tensorB)
|
| 41 |
+
.build();
|
| 42 |
+
|
| 43 |
+
TensorResult result = session.tensor().submit(job).join();
|
| 44 |
+
|
| 45 |
+
// TensorLatency.TMUL_CYCLES is architectural constant 4L, never wall-clock
|
| 46 |
+
assertEquals(TensorLatency.TMUL_CYCLES, result.cycles(),
|
| 47 |
+
"TMUL must take exactly TMUL_CYCLES architectural cycles");
|
| 48 |
+
assertEquals(4L, result.cycles(), "TMUL_CYCLES must be 4");
|
| 49 |
+
assertNotNull(result.traceHash(), "traceHash must be non-null");
|
| 50 |
+
assertNotNull(result.output(), "output must be present");
|
| 51 |
+
assertTrue(result.completionCycle() >= 0, "completionCycle architectural");
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
private static OrthoRuntime openRuntime(SimulatorTransport transport) {
|
| 56 |
+
for (var m : OrthoRuntime.class.getMethods()) {
|
| 57 |
+
if (m.getName().equals("open") && m.getParameterCount()==1
|
| 58 |
+
&& m.getParameterTypes()[0].isAssignableFrom(transport.getClass())) {
|
| 59 |
+
try { return (OrthoRuntime) m.invoke(null, transport); } catch (Exception e) { throw new RuntimeException(e); }
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
return OrthoRuntime.open();
|
| 63 |
+
}
|
| 64 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/TraceComparatorTest.java
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.trace.CycleRecord;
|
| 7 |
+
import org.ortho32.trace.ExecutionTrace;
|
| 8 |
+
import org.ortho32.trace.TraceComparison;
|
| 9 |
+
import org.ortho32.trace.TraceComparator;
|
| 10 |
+
|
| 11 |
+
import java.util.ArrayList;
|
| 12 |
+
import java.util.List;
|
| 13 |
+
|
| 14 |
+
public class TraceComparatorTest {
|
| 15 |
+
|
| 16 |
+
@Test
|
| 17 |
+
public void identicalTracesAreEqualAndMutatedAreNot() {
|
| 18 |
+
ExecutionTrace t1 = sampleTrace();
|
| 19 |
+
ExecutionTrace t2 = sampleTrace();
|
| 20 |
+
|
| 21 |
+
TraceComparison eq = TraceComparator.compare(t1, t2);
|
| 22 |
+
assertTrue(eq.isEqual(), "identical traces must be equal");
|
| 23 |
+
assertTrue(eq.mismatches().isEmpty(), "no mismatches for identical traces");
|
| 24 |
+
|
| 25 |
+
// Mutate one cycle
|
| 26 |
+
ExecutionTrace mutated = mutate(t1);
|
| 27 |
+
TraceComparison neq = TraceComparator.compare(t1, mutated);
|
| 28 |
+
assertFalse(neq.isEqual(), "mutated trace must not be equal");
|
| 29 |
+
assertFalse(neq.mismatches().isEmpty(), "mismatches must be reported");
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
private ExecutionTrace sampleTrace() {
|
| 33 |
+
List<CycleRecord> cycles = new ArrayList<>();
|
| 34 |
+
for (int i = 0; i < 4; i++) {
|
| 35 |
+
cycles.add(new CycleRecord(
|
| 36 |
+
i,
|
| 37 |
+
"EX",
|
| 38 |
+
"TMUL",
|
| 39 |
+
"COMMITTED",
|
| 40 |
+
List.of(new CycleRecord.RegisterWrite("r" + i, "0x" + i)),
|
| 41 |
+
List.of()
|
| 42 |
+
));
|
| 43 |
+
}
|
| 44 |
+
return new ExecutionTrace(cycles);
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
private ExecutionTrace mutate(ExecutionTrace original) {
|
| 48 |
+
List<CycleRecord> cycles = new ArrayList<>(original.cycles());
|
| 49 |
+
// flip first cycle's commitStatus
|
| 50 |
+
CycleRecord first = cycles.get(0);
|
| 51 |
+
CycleRecord mutated = new CycleRecord(
|
| 52 |
+
first.cycleNumber(),
|
| 53 |
+
first.scalarStage(),
|
| 54 |
+
first.tensorStage(),
|
| 55 |
+
"FLUSHED",
|
| 56 |
+
first.registerWrites(),
|
| 57 |
+
first.memoryEvents()
|
| 58 |
+
);
|
| 59 |
+
cycles.set(0, mutated);
|
| 60 |
+
return new ExecutionTrace(cycles);
|
| 61 |
+
}
|
| 62 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/TransportAgnosticTest.java
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.OrthoRuntime;
|
| 7 |
+
import org.ortho32.OrthoSession;
|
| 8 |
+
import org.ortho32.device.OrthoDevice;
|
| 9 |
+
import org.ortho32.tensor.Tensor;
|
| 10 |
+
import org.ortho32.tensor.TensorJob;
|
| 11 |
+
import org.ortho32.tensor.TensorLatency;
|
| 12 |
+
import org.ortho32.tensor.TensorOperation;
|
| 13 |
+
import org.ortho32.tensor.TensorResult;
|
| 14 |
+
import org.ortho32.tensor.TensorShape;
|
| 15 |
+
|
| 16 |
+
/**
|
| 17 |
+
* This test must import ZERO transport-specific classes.
|
| 18 |
+
* It verifies the same OrthoSession API works with SimulatorTransport
|
| 19 |
+
* without any transport-specific import in the test class.
|
| 20 |
+
*/
|
| 21 |
+
public class TransportAgnosticTest {
|
| 22 |
+
|
| 23 |
+
@Test
|
| 24 |
+
public void sameOrthoSessionApiWorksWithoutTransportImport() throws Exception {
|
| 25 |
+
// No SimulatorTransport import - OrthoRuntime.open() defaults to simulator in test env
|
| 26 |
+
try (OrthoRuntime runtime = OrthoRuntime.open();
|
| 27 |
+
OrthoSession session = runtime.openSession()) {
|
| 28 |
+
|
| 29 |
+
assertNotNull(runtime.version(), "version must be available");
|
| 30 |
+
assertNotNull(session.devices());
|
| 31 |
+
assertNotNull(session.tensor());
|
| 32 |
+
assertNotNull(session.trace());
|
| 33 |
+
assertNotNull(session.verify());
|
| 34 |
+
assertNotNull(session.agent());
|
| 35 |
+
assertNotNull(session.security());
|
| 36 |
+
|
| 37 |
+
OrthoDevice device = session.devices().firstAvailable();
|
| 38 |
+
assertNotNull(device, "device must be available via agnostic API");
|
| 39 |
+
|
| 40 |
+
TensorShape shape = new TensorShape(4, 4);
|
| 41 |
+
float[] data = new float[16];
|
| 42 |
+
for (int i = 0; i < 16; i++) data[i] = i + 1;
|
| 43 |
+
Tensor a = Tensor.of(shape, data);
|
| 44 |
+
Tensor b = Tensor.of(shape, data);
|
| 45 |
+
|
| 46 |
+
TensorJob job = TensorJob.builder()
|
| 47 |
+
.device(device)
|
| 48 |
+
.operation(TensorOperation.TMUL)
|
| 49 |
+
.inputA(a)
|
| 50 |
+
.inputB(b)
|
| 51 |
+
.build();
|
| 52 |
+
|
| 53 |
+
TensorResult result = session.tensor().submit(job).join();
|
| 54 |
+
assertNotNull(result);
|
| 55 |
+
assertEquals(TensorLatency.TMUL_CYCLES, result.cycles(),
|
| 56 |
+
"Agnostic API must still return architectural TMUL cycles");
|
| 57 |
+
assertNotNull(result.traceHash());
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
}
|
integration-tests/src/test/java/org/ortho32/tests/VerificationStatusTest.java
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.tests;
|
| 2 |
+
|
| 3 |
+
import org.junit.jupiter.api.Test;
|
| 4 |
+
import static org.junit.jupiter.api.Assertions.*;
|
| 5 |
+
|
| 6 |
+
import org.ortho32.verify.VerificationStatus;
|
| 7 |
+
|
| 8 |
+
public class VerificationStatusTest {
|
| 9 |
+
|
| 10 |
+
@Test
|
| 11 |
+
public void verifiedIsFormallyVerifiedAndTestedIsNotAndNeverInterchangeable() {
|
| 12 |
+
assertTrue(VerificationStatus.VERIFIED.isFormallyVerified(),
|
| 13 |
+
"VERIFIED must be formally verified");
|
| 14 |
+
assertFalse(VerificationStatus.TESTED.isFormallyVerified(),
|
| 15 |
+
"TESTED must NOT be formally verified");
|
| 16 |
+
|
| 17 |
+
assertNotEquals(VerificationStatus.VERIFIED, VerificationStatus.TESTED,
|
| 18 |
+
"VERIFIED != TESTED - never interchangeable");
|
| 19 |
+
|
| 20 |
+
// Additional invariants
|
| 21 |
+
assertTrue(VerificationStatus.CROSS_VERIFIED.isFormallyVerified(),
|
| 22 |
+
"CROSS_VERIFIED must be formally verified");
|
| 23 |
+
assertFalse(VerificationStatus.ASSUMED.isFormallyVerified(),
|
| 24 |
+
"ASSUMED must not be formally verified");
|
| 25 |
+
assertFalse(VerificationStatus.FAILED.isFormallyVerified(),
|
| 26 |
+
"FAILED must not be formally verified");
|
| 27 |
+
assertFalse(VerificationStatus.UNVERIFIED.isFormallyVerified(),
|
| 28 |
+
"UNVERIFIED must not be formally verified");
|
| 29 |
+
}
|
| 30 |
+
}
|
ortho-agent/build.gradle.kts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
plugins { `java-library` }
|
| 2 |
+
|
| 3 |
+
dependencies {
|
| 4 |
+
api(project(":ortho-fabric"))
|
| 5 |
+
api(project(":ortho-device"))
|
| 6 |
+
api(project(":ortho-security"))
|
| 7 |
+
}
|
ortho-agent/src/main/java/org/ortho32/agent/AgentCapability.java
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.agent;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Capability advertised by an agent.
|
| 7 |
+
*
|
| 8 |
+
* @param id stable capability identifier, must not be null
|
| 9 |
+
* @param name human-readable name, must not be null
|
| 10 |
+
* @param description description, must not be null
|
| 11 |
+
* @param resourceLimit resource limit for this capability, must be >=0
|
| 12 |
+
*/
|
| 13 |
+
public record AgentCapability(
|
| 14 |
+
String id,
|
| 15 |
+
String name,
|
| 16 |
+
String description,
|
| 17 |
+
long resourceLimit) {
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Compact canonical constructor.
|
| 21 |
+
*
|
| 22 |
+
* @param id capability id
|
| 23 |
+
* @param name name
|
| 24 |
+
* @param description description
|
| 25 |
+
* @param resourceLimit resource limit
|
| 26 |
+
*/
|
| 27 |
+
public AgentCapability {
|
| 28 |
+
Objects.requireNonNull(id, "id");
|
| 29 |
+
Objects.requireNonNull(name, "name");
|
| 30 |
+
Objects.requireNonNull(description, "description");
|
| 31 |
+
if (resourceLimit < 0) throw new IllegalArgumentException("resourceLimit must be >=0");
|
| 32 |
+
}
|
| 33 |
+
}
|
ortho-agent/src/main/java/org/ortho32/agent/AgentClient.java
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.agent;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Objects;
|
| 5 |
+
import java.util.concurrent.CompletableFuture;
|
| 6 |
+
|
| 7 |
+
/**
|
| 8 |
+
* Session sub-client for agent dispatch.
|
| 9 |
+
*/
|
| 10 |
+
public interface AgentClient {
|
| 11 |
+
|
| 12 |
+
/**
|
| 13 |
+
* Dispatches a task to an agent.
|
| 14 |
+
*
|
| 15 |
+
* @param task task to dispatch, must not be null
|
| 16 |
+
* @return future completing with agent result containing architectural cycles
|
| 17 |
+
*/
|
| 18 |
+
CompletableFuture<AgentResult> dispatch(AgentTask task);
|
| 19 |
+
|
| 20 |
+
/**
|
| 21 |
+
* Lists intents supported by the agent.
|
| 22 |
+
*
|
| 23 |
+
* @return unmodifiable list of intents, never null
|
| 24 |
+
*/
|
| 25 |
+
List<AgentIntent> intents();
|
| 26 |
+
}
|
ortho-agent/src/main/java/org/ortho32/agent/AgentIntent.java
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.agent;
|
| 2 |
+
|
| 3 |
+
import java.util.List;
|
| 4 |
+
import java.util.Map;
|
| 5 |
+
import java.util.Objects;
|
| 6 |
+
|
| 7 |
+
/**
|
| 8 |
+
* Typed intent describing an agent action.
|
| 9 |
+
*
|
| 10 |
+
* @param id stable intent identifier, must not be null
|
| 11 |
+
* @param verb action verb, must not be null
|
| 12 |
+
* @param noun target noun, must not be null
|
| 13 |
+
* @param parameters parameter map, never null, unmodifiable
|
| 14 |
+
* @param requiredCapabilities required capabilities for execution, never null, unmodifiable
|
| 15 |
+
*/
|
| 16 |
+
public record AgentIntent(
|
| 17 |
+
String id,
|
| 18 |
+
String verb,
|
| 19 |
+
String noun,
|
| 20 |
+
Map<String, String> parameters,
|
| 21 |
+
List<String> requiredCapabilities) {
|
| 22 |
+
|
| 23 |
+
/**
|
| 24 |
+
* Compact canonical constructor.
|
| 25 |
+
*
|
| 26 |
+
* @param id intent id
|
| 27 |
+
* @param verb verb
|
| 28 |
+
* @param noun noun
|
| 29 |
+
* @param parameters parameters
|
| 30 |
+
* @param requiredCapabilities required capabilities
|
| 31 |
+
*/
|
| 32 |
+
public AgentIntent {
|
| 33 |
+
Objects.requireNonNull(id, "id");
|
| 34 |
+
Objects.requireNonNull(verb, "verb");
|
| 35 |
+
Objects.requireNonNull(noun, "noun");
|
| 36 |
+
Objects.requireNonNull(requiredCapabilities, "requiredCapabilities");
|
| 37 |
+
parameters = parameters == null ? Map.of() : Map.copyOf(parameters);
|
| 38 |
+
requiredCapabilities = List.copyOf(requiredCapabilities);
|
| 39 |
+
}
|
| 40 |
+
}
|
ortho-agent/src/main/java/org/ortho32/agent/AgentResult.java
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.agent;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Result of an agent task.
|
| 7 |
+
*
|
| 8 |
+
* @param taskId originating task id, must not be null
|
| 9 |
+
* @param status status string, must not be null
|
| 10 |
+
* @param output output payload, may be null
|
| 11 |
+
* @param cycles architectural cycles consumed, never wall-clock
|
| 12 |
+
* @param auditId audit identifier for traceability, must not be null
|
| 13 |
+
*/
|
| 14 |
+
public record AgentResult(
|
| 15 |
+
String taskId,
|
| 16 |
+
String status,
|
| 17 |
+
String output,
|
| 18 |
+
long cycles,
|
| 19 |
+
String auditId) {
|
| 20 |
+
|
| 21 |
+
/**
|
| 22 |
+
* Compact canonical constructor.
|
| 23 |
+
*
|
| 24 |
+
* @param taskId task id
|
| 25 |
+
* @param status status
|
| 26 |
+
* @param output output
|
| 27 |
+
* @param cycles architectural cycles
|
| 28 |
+
* @param auditId audit id
|
| 29 |
+
*/
|
| 30 |
+
public AgentResult {
|
| 31 |
+
Objects.requireNonNull(taskId, "taskId");
|
| 32 |
+
Objects.requireNonNull(status, "status");
|
| 33 |
+
Objects.requireNonNull(auditId, "auditId");
|
| 34 |
+
if (cycles < 0) throw new IllegalArgumentException("cycles must be >=0");
|
| 35 |
+
}
|
| 36 |
+
}
|
ortho-agent/src/main/java/org/ortho32/agent/AgentTask.java
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.agent;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Task submitted to an agent.
|
| 7 |
+
*
|
| 8 |
+
* @param id task identifier, must not be null
|
| 9 |
+
* @param intent intent to execute, must not be null
|
| 10 |
+
* @param context context string for execution, may be null
|
| 11 |
+
* @param timeout timeout in milliseconds, must be >=0
|
| 12 |
+
*/
|
| 13 |
+
public record AgentTask(
|
| 14 |
+
String id,
|
| 15 |
+
AgentIntent intent,
|
| 16 |
+
String context,
|
| 17 |
+
long timeout) {
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* Compact canonical constructor.
|
| 21 |
+
*
|
| 22 |
+
* @param id task id
|
| 23 |
+
* @param intent intent
|
| 24 |
+
* @param context context
|
| 25 |
+
* @param timeout timeout
|
| 26 |
+
*/
|
| 27 |
+
public AgentTask {
|
| 28 |
+
Objects.requireNonNull(id, "id");
|
| 29 |
+
Objects.requireNonNull(intent, "intent");
|
| 30 |
+
if (timeout < 0) throw new IllegalArgumentException("timeout must be >=0");
|
| 31 |
+
}
|
| 32 |
+
}
|
ortho-compute/build.gradle.kts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
plugins {
|
| 2 |
+
`java-library`
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
dependencies {
|
| 6 |
+
api(project(":ortho-device"))
|
| 7 |
+
api(project(":ortho-fabric"))
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
java {
|
| 11 |
+
toolchain { languageVersion.set(JavaLanguageVersion.of(21)) }
|
| 12 |
+
}
|
ortho-compute/src/main/java/org/ortho32/compute/ComputeBackend.java
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.compute;
|
| 2 |
+
|
| 3 |
+
public enum ComputeBackend {
|
| 4 |
+
ORTHO,
|
| 5 |
+
CUDA_REFERENCE,
|
| 6 |
+
SIMULATOR
|
| 7 |
+
}
|
ortho-compute/src/main/java/org/ortho32/compute/ComputeJob.java
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.compute;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.device.OrthoDeviceId;
|
| 4 |
+
import java.util.Arrays;
|
| 5 |
+
import java.util.Collections;
|
| 6 |
+
import java.util.HashMap;
|
| 7 |
+
import java.util.Map;
|
| 8 |
+
import java.util.Objects;
|
| 9 |
+
|
| 10 |
+
/**
|
| 11 |
+
* Immutable compute job descriptor.
|
| 12 |
+
*
|
| 13 |
+
* @param device target device id
|
| 14 |
+
* @param backend execution backend
|
| 15 |
+
* @param options immutable options map
|
| 16 |
+
* @param payload opaque payload (defensive copy)
|
| 17 |
+
*/
|
| 18 |
+
public record ComputeJob(
|
| 19 |
+
OrthoDeviceId device,
|
| 20 |
+
ComputeBackend backend,
|
| 21 |
+
Map<String, String> options,
|
| 22 |
+
byte[] payload
|
| 23 |
+
) {
|
| 24 |
+
public ComputeJob {
|
| 25 |
+
Objects.requireNonNull(device);
|
| 26 |
+
Objects.requireNonNull(backend);
|
| 27 |
+
if (options == null) options = Map.of();
|
| 28 |
+
options = Collections.unmodifiableMap(new HashMap<>(options));
|
| 29 |
+
if (payload == null) payload = new byte[0];
|
| 30 |
+
payload = Arrays.copyOf(payload, payload.length);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
@Override
|
| 34 |
+
public Map<String, String> options() {
|
| 35 |
+
return Collections.unmodifiableMap(options);
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
@Override
|
| 39 |
+
public byte[] payload() {
|
| 40 |
+
return Arrays.copyOf(payload, payload.length);
|
| 41 |
+
}
|
| 42 |
+
}
|
ortho-compute/src/main/java/org/ortho32/compute/ComputeResult.java
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.compute;
|
| 2 |
+
|
| 3 |
+
import java.util.Arrays;
|
| 4 |
+
import java.util.Objects;
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* Immutable compute result with architectural cycle accounting.
|
| 8 |
+
*
|
| 9 |
+
* @param status execution status
|
| 10 |
+
* @param output output bytes (defensive copy)
|
| 11 |
+
* @param cycles architectural cycles (long, never wall-clock)
|
| 12 |
+
* @param traceHash trace hash (SHA-256 hex)
|
| 13 |
+
*/
|
| 14 |
+
public record ComputeResult(
|
| 15 |
+
String status,
|
| 16 |
+
byte[] output,
|
| 17 |
+
long cycles,
|
| 18 |
+
String traceHash
|
| 19 |
+
) {
|
| 20 |
+
public ComputeResult {
|
| 21 |
+
Objects.requireNonNull(status);
|
| 22 |
+
Objects.requireNonNull(traceHash);
|
| 23 |
+
if (output == null) output = new byte[0];
|
| 24 |
+
output = Arrays.copyOf(output, output.length);
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
@Override
|
| 28 |
+
public byte[] output() {
|
| 29 |
+
return Arrays.copyOf(output, output.length);
|
| 30 |
+
}
|
| 31 |
+
}
|
ortho-core/build.gradle.kts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ortho-core: top-level aggregator. OrthoRuntime/OrthoSession compose all sub-clients.
|
| 2 |
+
plugins { `java-library` }
|
| 3 |
+
|
| 4 |
+
dependencies {
|
| 5 |
+
api(project(":ortho-fabric"))
|
| 6 |
+
api(project(":ortho-device"))
|
| 7 |
+
api(project(":ortho-transport"))
|
| 8 |
+
api(project(":ortho-compute"))
|
| 9 |
+
api(project(":ortho-tensor"))
|
| 10 |
+
api(project(":ortho-trace"))
|
| 11 |
+
api(project(":ortho-verify"))
|
| 12 |
+
api(project(":ortho-security"))
|
| 13 |
+
api(project(":ortho-agent"))
|
| 14 |
+
api(project(":ortho-routing"))
|
| 15 |
+
}
|
ortho-core/src/main/java/org/ortho32/OrthoContext.java
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32;
|
| 2 |
+
|
| 3 |
+
import java.util.Set;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Session context: immutable snapshot of session identity, capabilities and activity.
|
| 7 |
+
*
|
| 8 |
+
* @param identity stable session identifier
|
| 9 |
+
* @param capabilities granted capabilities
|
| 10 |
+
* @param active whether session is active
|
| 11 |
+
* @param requestCount number of requests issued in this session
|
| 12 |
+
*/
|
| 13 |
+
public record OrthoContext(
|
| 14 |
+
String identity,
|
| 15 |
+
Set<String> capabilities,
|
| 16 |
+
boolean active,
|
| 17 |
+
long requestCount
|
| 18 |
+
) {
|
| 19 |
+
public OrthoContext {
|
| 20 |
+
if (identity == null) throw new IllegalArgumentException("identity is null");
|
| 21 |
+
if (capabilities == null) throw new IllegalArgumentException("capabilities is null");
|
| 22 |
+
capabilities = Set.copyOf(capabilities);
|
| 23 |
+
}
|
| 24 |
+
}
|
ortho-core/src/main/java/org/ortho32/OrthoResult.java
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32;
|
| 2 |
+
|
| 3 |
+
import java.util.Arrays;
|
| 4 |
+
import java.util.Objects;
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* Typed result with architectural cycle accounting.
|
| 8 |
+
*
|
| 9 |
+
* @param status result status
|
| 10 |
+
* @param payload opaque payload bytes (defensive copy)
|
| 11 |
+
* @param cycles architectural cycles (long, never wall-clock)
|
| 12 |
+
* @param traceHash SHA-256 of canonical trace or empty
|
| 13 |
+
*/
|
| 14 |
+
public record OrthoResult(
|
| 15 |
+
String status,
|
| 16 |
+
byte[] payload,
|
| 17 |
+
long cycles,
|
| 18 |
+
String traceHash
|
| 19 |
+
) {
|
| 20 |
+
public OrthoResult {
|
| 21 |
+
Objects.requireNonNull(status, "status");
|
| 22 |
+
Objects.requireNonNull(traceHash, "traceHash");
|
| 23 |
+
if (payload == null) payload = new byte[0];
|
| 24 |
+
payload = Arrays.copyOf(payload, payload.length);
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
@Override
|
| 28 |
+
public byte[] payload() {
|
| 29 |
+
return Arrays.copyOf(payload, payload.length);
|
| 30 |
+
}
|
| 31 |
+
}
|
ortho-core/src/main/java/org/ortho32/OrthoRuntime.java
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.transport.SimulatorTransport;
|
| 4 |
+
import org.ortho32.transport.TransportFactory;
|
| 5 |
+
import org.ortho32.transport.OrthoTransport;
|
| 6 |
+
|
| 7 |
+
/**
|
| 8 |
+
* Entry point for ORTHO-32 SDK.
|
| 9 |
+
* Applications obtain a runtime via {@link #open()} and then open sessions.
|
| 10 |
+
*/
|
| 11 |
+
public final class OrthoRuntime implements AutoCloseable {
|
| 12 |
+
|
| 13 |
+
private final OrthoTransport transport;
|
| 14 |
+
private volatile boolean closed;
|
| 15 |
+
|
| 16 |
+
private OrthoRuntime(OrthoTransport transport) {
|
| 17 |
+
this.transport = transport;
|
| 18 |
+
this.transport.connect();
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
/**
|
| 22 |
+
* Open a runtime backed by SimulatorTransport (deterministic, no hardware).
|
| 23 |
+
*/
|
| 24 |
+
public static OrthoRuntime open() {
|
| 25 |
+
return new OrthoRuntime(TransportFactory.simulator());
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
/**
|
| 29 |
+
* Open with an explicit transport (internal use). Public surface uses {@link #open()}.
|
| 30 |
+
*/
|
| 31 |
+
static OrthoRuntime open(OrthoTransport transport) {
|
| 32 |
+
return new OrthoRuntime(transport);
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
public OrthoSession openSession() {
|
| 36 |
+
if (closed) {
|
| 37 |
+
throw new IllegalStateException("OrthoRuntime is closed");
|
| 38 |
+
}
|
| 39 |
+
OrthoContext context = new OrthoContext(
|
| 40 |
+
"ortho32-session-" + System.nanoTime(),
|
| 41 |
+
java.util.Set.of("tensor", "trace", "verify"),
|
| 42 |
+
true,
|
| 43 |
+
0L
|
| 44 |
+
);
|
| 45 |
+
return new OrthoSession(context, transport);
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
public OrthoVersion version() {
|
| 49 |
+
return new OrthoVersion("0.1.0", "1.0.0", "32-1.0");
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
@Override
|
| 53 |
+
public void close() {
|
| 54 |
+
if (!closed) {
|
| 55 |
+
closed = true;
|
| 56 |
+
transport.disconnect();
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
}
|
ortho-core/src/main/java/org/ortho32/OrthoSession.java
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.device.DeviceClient;
|
| 4 |
+
import org.ortho32.transport.OrthoTransport;
|
| 5 |
+
import java.util.Objects;
|
| 6 |
+
import java.util.concurrent.atomic.AtomicLong;
|
| 7 |
+
|
| 8 |
+
/**
|
| 9 |
+
* Session is the main interaction scope. AutoCloseable. Provides sub-clients.
|
| 10 |
+
*/
|
| 11 |
+
public final class OrthoSession implements AutoCloseable {
|
| 12 |
+
|
| 13 |
+
private final OrthoContext context;
|
| 14 |
+
private final OrthoTransport transport;
|
| 15 |
+
private final AtomicLong requestCount = new AtomicLong(0);
|
| 16 |
+
private final DeviceClient devices;
|
| 17 |
+
|
| 18 |
+
// Stub sub-clients for modules not yet wired in this slice
|
| 19 |
+
public interface TensorClient {
|
| 20 |
+
java.util.concurrent.CompletableFuture<org.ortho32.compute.ComputeResult> submit(org.ortho32.compute.ComputeJob job);
|
| 21 |
+
}
|
| 22 |
+
public interface TraceClient {}
|
| 23 |
+
public interface VerifyClient {}
|
| 24 |
+
public interface AgentClient {}
|
| 25 |
+
public interface SecurityClient {}
|
| 26 |
+
|
| 27 |
+
private final TensorClient tensorClient;
|
| 28 |
+
private final TraceClient traceClient;
|
| 29 |
+
private final VerifyClient verifyClient;
|
| 30 |
+
private final AgentClient agentClient;
|
| 31 |
+
private final SecurityClient securityClient;
|
| 32 |
+
|
| 33 |
+
OrthoSession(OrthoContext context, OrthoTransport transport) {
|
| 34 |
+
this.context = Objects.requireNonNull(context);
|
| 35 |
+
this.transport = Objects.requireNonNull(transport);
|
| 36 |
+
this.devices = new DeviceClient(transport);
|
| 37 |
+
this.tensorClient = job -> java.util.concurrent.CompletableFuture.failedFuture(
|
| 38 |
+
new UnsupportedOperationException("tensor not wired in core slice"));
|
| 39 |
+
this.traceClient = new TraceClient() {};
|
| 40 |
+
this.verifyClient = new VerifyClient() {};
|
| 41 |
+
this.agentClient = new AgentClient() {};
|
| 42 |
+
this.securityClient = new SecurityClient() {};
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
public OrthoContext context() {
|
| 46 |
+
return new OrthoContext(
|
| 47 |
+
context.identity(),
|
| 48 |
+
context.capabilities(),
|
| 49 |
+
context.active(),
|
| 50 |
+
requestCount.get()
|
| 51 |
+
);
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
long nextRequestId() {
|
| 55 |
+
return requestCount.incrementAndGet();
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
public DeviceClient devices() {
|
| 59 |
+
return devices;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
public TensorClient tensor() {
|
| 63 |
+
return tensorClient;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
public TraceClient trace() {
|
| 67 |
+
return traceClient;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
public VerifyClient verify() {
|
| 71 |
+
return verifyClient;
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
public AgentClient agent() {
|
| 75 |
+
return agentClient;
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
public SecurityClient security() {
|
| 79 |
+
return securityClient;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
@Override
|
| 83 |
+
public void close() {
|
| 84 |
+
// no-op for simulator; disconnect is owned by runtime
|
| 85 |
+
}
|
| 86 |
+
}
|
ortho-core/src/main/java/org/ortho32/OrthoVersion.java
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Compatibility tuple for SDK + Fabric Protocol + Device ABI.
|
| 5 |
+
*
|
| 6 |
+
* @param sdkVersion SDK semantic version
|
| 7 |
+
* @param fabricProtocolVersion fabric protocol version
|
| 8 |
+
* @param deviceABIVersion device ABI version
|
| 9 |
+
*/
|
| 10 |
+
public record OrthoVersion(
|
| 11 |
+
String sdkVersion,
|
| 12 |
+
String fabricProtocolVersion,
|
| 13 |
+
String deviceABIVersion
|
| 14 |
+
) {
|
| 15 |
+
public OrthoVersion {
|
| 16 |
+
if (sdkVersion == null || fabricProtocolVersion == null || deviceABIVersion == null) {
|
| 17 |
+
throw new IllegalArgumentException("version components must not be null");
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
}
|
ortho-device/build.gradle.kts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
plugins {
|
| 2 |
+
`java-library`
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
dependencies {
|
| 6 |
+
api(project(":ortho-fabric"))
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
java {
|
| 10 |
+
toolchain { languageVersion.set(JavaLanguageVersion.of(21)) }
|
| 11 |
+
}
|
ortho-device/src/main/java/org/ortho32/device/DeviceClient.java
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.transport.OrthoTransport;
|
| 4 |
+
import java.util.List;
|
| 5 |
+
import java.util.Objects;
|
| 6 |
+
import java.util.Optional;
|
| 7 |
+
|
| 8 |
+
/**
|
| 9 |
+
* Session sub-client for device enumeration. Immutable, thread-safe.
|
| 10 |
+
*/
|
| 11 |
+
public final class DeviceClient {
|
| 12 |
+
|
| 13 |
+
private final List<OrthoDevice> devices;
|
| 14 |
+
|
| 15 |
+
public DeviceClient(OrthoTransport transport) {
|
| 16 |
+
Objects.requireNonNull(transport);
|
| 17 |
+
// Deterministic simulator device set. In real transports this would query host service.
|
| 18 |
+
OrthoDevice sim = new SimulatedDevice();
|
| 19 |
+
this.devices = List.of(sim);
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// Test constructor
|
| 23 |
+
DeviceClient(List<OrthoDevice> devices) {
|
| 24 |
+
this.devices = List.copyOf(Objects.requireNonNull(devices));
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
public OrthoDevice firstAvailable() {
|
| 28 |
+
return devices.stream()
|
| 29 |
+
.filter(d -> d.state() != OrthoDeviceState.ERROR)
|
| 30 |
+
.findFirst()
|
| 31 |
+
.orElseThrow(() -> new java.util.NoSuchElementException("No available ORTHO device"));
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
public List<OrthoDevice> list() {
|
| 35 |
+
return devices;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
public Optional<OrthoDevice> find(OrthoDeviceId id) {
|
| 39 |
+
Objects.requireNonNull(id);
|
| 40 |
+
return devices.stream().filter(d -> d.id().equals(id)).findFirst();
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
private static final class SimulatedDevice implements OrthoDevice {
|
| 44 |
+
private final OrthoDeviceId id = new OrthoDeviceId("sim-0001");
|
| 45 |
+
private final OrthoDeviceInfo info = new OrthoDeviceInfo("ORTHO-32 Simulator", "simulator", "ortho-32", "0.1.0-sim");
|
| 46 |
+
private final OrthoDeviceCapabilities caps = new OrthoDeviceCapabilities(true, true, true, 1 << 20);
|
| 47 |
+
private volatile OrthoDeviceState state = OrthoDeviceState.CONNECTED;
|
| 48 |
+
|
| 49 |
+
@Override public OrthoDeviceId id() { return id; }
|
| 50 |
+
@Override public OrthoDeviceInfo info() { return info; }
|
| 51 |
+
@Override public OrthoDeviceCapabilities capabilities() { return caps; }
|
| 52 |
+
@Override public OrthoDeviceState state() { return state; }
|
| 53 |
+
@Override public void connect() { state = OrthoDeviceState.CONNECTED; }
|
| 54 |
+
@Override public void disconnect() { state = OrthoDeviceState.DISCONNECTED; }
|
| 55 |
+
@Override public void reset() { state = OrthoDeviceState.CONNECTED; }
|
| 56 |
+
}
|
| 57 |
+
}
|
ortho-device/src/main/java/org/ortho32/device/OrthoDevice.java
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Public device handle. Applications interact via this interface, never via transport internals.
|
| 5 |
+
*/
|
| 6 |
+
public interface OrthoDevice {
|
| 7 |
+
|
| 8 |
+
OrthoDeviceId id();
|
| 9 |
+
|
| 10 |
+
OrthoDeviceInfo info();
|
| 11 |
+
|
| 12 |
+
OrthoDeviceCapabilities capabilities();
|
| 13 |
+
|
| 14 |
+
OrthoDeviceState state();
|
| 15 |
+
|
| 16 |
+
void connect();
|
| 17 |
+
|
| 18 |
+
void disconnect();
|
| 19 |
+
|
| 20 |
+
void reset();
|
| 21 |
+
}
|
ortho-device/src/main/java/org/ortho32/device/OrthoDeviceCapabilities.java
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* @param hasTensor whether tensor unit is present
|
| 5 |
+
* @param hasTrace whether trace buffer is present
|
| 6 |
+
* @param hasVerify whether verification attest is supported
|
| 7 |
+
* @param maxScratchpadBytes max tensor scratchpad in bytes
|
| 8 |
+
*/
|
| 9 |
+
public record OrthoDeviceCapabilities(
|
| 10 |
+
boolean hasTensor,
|
| 11 |
+
boolean hasTrace,
|
| 12 |
+
boolean hasVerify,
|
| 13 |
+
long maxScratchpadBytes
|
| 14 |
+
) {}
|
ortho-device/src/main/java/org/ortho32/device/OrthoDeviceId.java
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Stable device identifier.
|
| 7 |
+
*
|
| 8 |
+
* @param value stable identifier string
|
| 9 |
+
*/
|
| 10 |
+
public record OrthoDeviceId(String value) {
|
| 11 |
+
|
| 12 |
+
public OrthoDeviceId {
|
| 13 |
+
Objects.requireNonNull(value, "value");
|
| 14 |
+
if (value.isBlank()) throw new IllegalArgumentException("OrthoDeviceId value must not be blank");
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
@Override
|
| 18 |
+
public String toString() {
|
| 19 |
+
return value;
|
| 20 |
+
}
|
| 21 |
+
}
|
ortho-device/src/main/java/org/ortho32/device/OrthoDeviceInfo.java
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* @param name human readable name
|
| 7 |
+
* @param transport transport type (simulator, pcie, usb, ethernet, native)
|
| 8 |
+
* @param architecture architecture identifier (e.g., ortho-32)
|
| 9 |
+
* @param firmwareVersion firmware version string
|
| 10 |
+
*/
|
| 11 |
+
public record OrthoDeviceInfo(
|
| 12 |
+
String name,
|
| 13 |
+
String transport,
|
| 14 |
+
String architecture,
|
| 15 |
+
String firmwareVersion
|
| 16 |
+
) {
|
| 17 |
+
public OrthoDeviceInfo {
|
| 18 |
+
Objects.requireNonNull(name);
|
| 19 |
+
Objects.requireNonNull(transport);
|
| 20 |
+
Objects.requireNonNull(architecture);
|
| 21 |
+
Objects.requireNonNull(firmwareVersion);
|
| 22 |
+
}
|
| 23 |
+
}
|
ortho-device/src/main/java/org/ortho32/device/OrthoDeviceState.java
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.device;
|
| 2 |
+
|
| 3 |
+
public enum OrthoDeviceState {
|
| 4 |
+
CONNECTED,
|
| 5 |
+
DISCONNECTED,
|
| 6 |
+
ERROR
|
| 7 |
+
}
|
ortho-fabric/build.gradle.kts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
plugins {
|
| 2 |
+
`java-library`
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
java {
|
| 6 |
+
toolchain { languageVersion.set(JavaLanguageVersion.of(21)) }
|
| 7 |
+
}
|
ortho-fabric/src/main/java/org/ortho32/fabric/FabricAddress.java
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.fabric;
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Typed address in ORTHO-32 memory map.
|
| 5 |
+
*
|
| 6 |
+
* @param value 32-bit address value (stored in long to avoid signed issues)
|
| 7 |
+
*/
|
| 8 |
+
public record FabricAddress(long value) {
|
| 9 |
+
|
| 10 |
+
public static final FabricAddress SCALAR_RAM = new FabricAddress(0x00000000L);
|
| 11 |
+
public static final FabricAddress TENSOR_SCRATCHPAD = new FabricAddress(0x10000000L);
|
| 12 |
+
public static final FabricAddress MMIO = new FabricAddress(0x20000000L);
|
| 13 |
+
public static final FabricAddress TRACE_BUFFER = new FabricAddress(0x30000000L);
|
| 14 |
+
public static final FabricAddress HOST_APERTURE = new FabricAddress(0x40000000L);
|
| 15 |
+
|
| 16 |
+
public FabricAddress {
|
| 17 |
+
if (value < 0 || value > 0xFFFFFFFFL) {
|
| 18 |
+
throw new IllegalArgumentException("FabricAddress out of 32-bit range: " + Long.toHexString(value));
|
| 19 |
+
}
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
@Override
|
| 23 |
+
public String toString() {
|
| 24 |
+
return String.format("0x%08X", value);
|
| 25 |
+
}
|
| 26 |
+
}
|
ortho-fabric/src/main/java/org/ortho32/fabric/FabricCommand.java
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.fabric;
|
| 2 |
+
|
| 3 |
+
import org.ortho32.device.OrthoDeviceId;
|
| 4 |
+
import java.util.Objects;
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* Logical fabric command. Applications never write PCIe BAR registers directly.
|
| 8 |
+
*
|
| 9 |
+
* @param opcode operation
|
| 10 |
+
* @param device target device
|
| 11 |
+
* @param address typed ORTHO address
|
| 12 |
+
* @param length length in bytes
|
| 13 |
+
* @param epoch epoch for deterministic arbitration
|
| 14 |
+
* @param slot slot in static grant table
|
| 15 |
+
* @param sequence monotonic sequence number
|
| 16 |
+
* @param payloadHash SHA-256 hex of payload
|
| 17 |
+
* @param flags opaque flags
|
| 18 |
+
*/
|
| 19 |
+
public record FabricCommand(
|
| 20 |
+
FabricOpcode opcode,
|
| 21 |
+
OrthoDeviceId device,
|
| 22 |
+
FabricAddress address,
|
| 23 |
+
int length,
|
| 24 |
+
FabricEpoch epoch,
|
| 25 |
+
FabricSlot slot,
|
| 26 |
+
long sequence,
|
| 27 |
+
String payloadHash,
|
| 28 |
+
int flags
|
| 29 |
+
) {
|
| 30 |
+
public FabricCommand {
|
| 31 |
+
Objects.requireNonNull(opcode);
|
| 32 |
+
Objects.requireNonNull(device);
|
| 33 |
+
Objects.requireNonNull(address);
|
| 34 |
+
Objects.requireNonNull(epoch);
|
| 35 |
+
Objects.requireNonNull(slot);
|
| 36 |
+
Objects.requireNonNull(payloadHash);
|
| 37 |
+
if (length < 0) throw new IllegalArgumentException("length < 0");
|
| 38 |
+
if (sequence < 0) throw new IllegalArgumentException("sequence < 0");
|
| 39 |
+
}
|
| 40 |
+
}
|
ortho-fabric/src/main/java/org/ortho32/fabric/FabricCompletion.java
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package org.ortho32.fabric;
|
| 2 |
+
|
| 3 |
+
import java.util.Objects;
|
| 4 |
+
|
| 5 |
+
/**
|
| 6 |
+
* Fabric completion with architectural cycle accounting.
|
| 7 |
+
* cycles = completionCycle - acceptedCycle. Both are ORTHO architectural cycles, NOT wall-clock milliseconds.
|
| 8 |
+
*
|
| 9 |
+
* @param sequence echoed sequence
|
| 10 |
+
* @param status 0=ok non-zero=error
|
| 11 |
+
* @param acceptedCycle cycle when fabric accepted the command (long)
|
| 12 |
+
* @param completionCycle cycle when execution completed (long)
|
| 13 |
+
* @param resultHash SHA-256 hex of result
|
| 14 |
+
* @param traceRoot Merkle root / trace hash
|
| 15 |
+
*/
|
| 16 |
+
public record FabricCompletion(
|
| 17 |
+
long sequence,
|
| 18 |
+
int status,
|
| 19 |
+
long acceptedCycle,
|
| 20 |
+
long completionCycle,
|
| 21 |
+
String resultHash,
|
| 22 |
+
String traceRoot
|
| 23 |
+
) {
|
| 24 |
+
public FabricCompletion {
|
| 25 |
+
Objects.requireNonNull(resultHash);
|
| 26 |
+
Objects.requireNonNull(traceRoot);
|
| 27 |
+
if (completionCycle < acceptedCycle) {
|
| 28 |
+
throw new IllegalArgumentException("completionCycle < acceptedCycle");
|
| 29 |
+
}
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
/**
|
| 33 |
+
* Architectural cycles consumed. Derived, not wall-clock.
|
| 34 |
+
*/
|
| 35 |
+
public long cycles() {
|
| 36 |
+
return completionCycle - acceptedCycle;
|
| 37 |
+
}
|
| 38 |
+
}
|