# Portable `mtran` ROS2 Package Design

## 1. Goal

Turn the current `migrate_ws` directory into one self-contained ROS2 source package that can be copied directly to:

```text
smart_healthcare_2026/src/mtran
```

After copying, the target machine must not need any file from the original MTranServer repository. A first-time online preparation script installs non-ROS dependencies, builds a native MTranServer sidecar, and downloads the fixed English-to-Simplified-Chinese runtime data. The user remains responsible for installing ROS2 Humble and running `colcon build` from `smart_healthcare_2026`.

## 2. Fixed Product Scope

The package provides one synchronous ROS2 service:

```text
/translate_en_to_zh
```

The request contains one English string. The response contains success status, the Simplified Chinese translation, and an error code.

The migration does not add topics, multiple languages, batch translation, HTML support, automatic language detection, or native C++ Bergamot integration.

## 3. Target Environment

- Ubuntu 22.04
- ROS2 Humble already installed by the user
- Supported CPU architectures: `x86_64` and `aarch64`
- C++17
- Initial preparation may access apt, npm, Mozilla translation-model endpoints, and package registries
- Runtime must work without network access after preparation and `colcon build`

The preparation script must not configure ROS apt repositories, install `ros-humble-ros-base`, or execute `colcon build`.

## 4. Package Identity and Interface

The ROS2 package and source-directory name are both `mtran`.

The service type becomes:

```text
mtran/srv/TranslateEnglishToChinese
```

The service definition remains:

```srv
string text
---
bool success
string translation
string error
```

The executable and node names remain `mtran_bridge_node`. Existing source namespaces change from `mtran_ros2` to `mtran`.

The resulting commands are:

```bash
colcon build --packages-select mtran
ros2 launch mtran translator.launch.py
ros2 service call /translate_en_to_zh \
  mtran/srv/TranslateEnglishToChinese \
  "{text: 'Hello.'}"
```

## 5. Final Directory Layout

The source package contains:

```text
mtran/
├── CMakeLists.txt
├── package.xml
├── README.md
├── .gitignore
├── config/
│   └── translator.yaml
├── dependencies/
│   ├── auto_install.sh
│   ├── dependencies.txt
│   └── tools/
├── docs/
│   └── superpowers/
├── include/
│   └── mtran/
│       ├── http_translation_client.hpp
│       └── translator_node.hpp
├── launch/
│   └── translator.launch.py
├── models/
│   └── en_zh-Hans/
├── runtime/
│   ├── bin/
│   │   └── mtranserver
│   └── config/
│       └── records.json
├── src/
│   ├── http_translation_client.cpp
│   ├── main.cpp
│   └── translator_node.cpp
├── srv/
│   └── TranslateEnglishToChinese.srv
├── test/
│   ├── test_http_translation_client.cpp
│   └── test_translator_node.cpp
├── vendor/
│   └── mtranserver/
└── .build/
    └── mtranserver/
```

`dependencies/tools`, `.build`, `runtime/bin/mtranserver`, `runtime/config`, model files, colcon outputs, Python bytecode, and logs are generated and ignored by Git. `vendor/mtranserver` is committed source.

## 6. Vendored MTranServer Source

`vendor/mtranserver` contains a fixed copy of MTranServer v4.0.33 at source commit `f5672a9`. It includes every source, lock, UI-resource, WASM, build-script, and metadata file required by the existing single-binary Bun build.

The vendored copy excludes:

- `.git`
- `migrate_ws`
- `node_modules`
- `dist`
- `release`
- local logs and caches

The vendored directory is treated as read-only input. Build-generated files must never be written there.

## 7. Build Staging Boundary

`dependencies/auto_install.sh` resolves all paths relative to its own location:

```bash
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)
package_root=$(cd "${script_dir}/.." && pwd -P)
vendor_source="${package_root}/vendor/mtranserver"
build_dir="${package_root}/.build/mtranserver"
runtime_bin_dir="${package_root}/runtime/bin"
```

The build sequence is:

```text
vendor/mtranserver
  -> rsync into .build/mtranserver
  -> install Bun packages in .build/mtranserver
  -> run the existing single-binary build in .build/mtranserver
  -> copy dist/mtranserver to runtime/bin/mtranserver
```

The script installs workspace-local Bun under `dependencies/tools`. Bun caches must also remain below `dependencies/tools`. Electron binary downloads are disabled because the sidecar does not use Electron.

Running on x86_64 produces an x86-64 sidecar. Running on aarch64 produces an ARM64 sidecar. The script rejects unsupported architectures before downloading build dependencies.

## 8. `auto_install.sh` Responsibilities

The script performs these operations in order:

1. Validate Ubuntu 22.04.
2. Validate that `ROS_DISTRO=humble` or `/opt/ros/humble` exists.
3. Validate CPU architecture is `x86_64` or `aarch64`.
4. Verify required ROS2 Humble packages are present; report missing ROS packages without installing them.
5. Install required non-ROS apt packages with `sudo apt-get`.
6. Install pinned workspace-local Bun.
7. Copy the vendored source into `.build/mtranserver`.
8. Install locked Bun dependencies and build the native sidecar.
9. Stage the executable at `runtime/bin/mtranserver` and verify its architecture.
10. Download Mozilla `translations-models-v2` records into `runtime/config/records.json`.
11. Download only the `en -> zh-Hans` model into `models/en_zh-Hans`.
12. Verify the four required model files and their hashes from the Mozilla records.
13. Print the exact `colcon build` and launch commands the user should run next.

The script does not source a user workspace, run `colcon`, modify parent directories, install ROS2, or start a persistent server.

The script is idempotent. It reuses valid Bun tools, downloaded files, and native artifacts. It rebuilds or redownloads an artifact when that artifact is missing, has the wrong architecture, or fails integrity validation.

Any failed command terminates the script with a non-zero status. Temporary downloads use a temporary filename and are renamed only after verification, so interrupted downloads cannot appear valid.

## 9. Dependency Manifest

`dependencies/dependencies.txt` is a human-readable manifest, not an executable package-manager lock file. It records:

### User-Provided Prerequisites

- Ubuntu 22.04
- ROS2 Humble
- Required ROS packages: `ament_cmake`, `ament_cmake_gtest`, `rclcpp`, `rosidl_default_generators`, `rosidl_default_runtime`, `launch`, and `launch_ros`

These are checked but not installed by `auto_install.sh`.

### Installed Apt Packages

- `build-essential`
- `cmake`
- `pkg-config`
- `curl`
- `ca-certificates`
- `rsync`
- `npm`
- `libcurl4-openssl-dev`
- `nlohmann-json3-dev`

### Workspace Tools

- Bun 1.3.14
- Installation method and package-registry source

### Included Source

- MTranServer 4.0.33
- Commit `f5672a9`
- Upstream repository URL
- Apache-2.0 license reference

### Downloaded Runtime Data

- Mozilla translations-models-v2 records endpoint
- Mozilla attachment CDN base URL
- Exact direction `en -> zh-Hans`
- Expected model file roles: model, lexicon, source vocabulary, target vocabulary
- Integrity checks based on `decompressedHash` from `records.json`

The manifest must distinguish user-provided prerequisites, packages installed by the script, included source, and generated runtime artifacts.

## 10. CMake and Install Space

`CMakeLists.txt` never downloads from the network and never invokes Bun. It requires the preparation outputs before configuration:

```text
runtime/bin/mtranserver
runtime/config/records.json
models/en_zh-Hans/<four model files>
```

If any required output is missing, CMake stops with a message instructing the user to run:

```bash
./dependencies/auto_install.sh
```

CMake installs:

```text
runtime/bin/mtranserver
  -> install/mtran/lib/mtran/mtranserver

models/en_zh-Hans
  -> install/mtran/share/mtran/models/en_zh-Hans

runtime/config/records.json
  -> install/mtran/share/mtran/mtranserver_config/records.json
```

The launch file resolves all defaults from the installed package prefix and share directory. It must not search upward for the source workspace or contain an absolute local path.

## 11. Runtime Behavior

Launch starts the installed MTranServer and C++ bridge. MTranServer receives:

```text
MT_HOST=127.0.0.1
MT_PORT=8989
MT_ENABLE_UI=false
MT_OFFLINE=true
MT_CHECK_UPDATE=false
MT_CONFIG_DIR=<installed mtranserver_config directory>
MT_MODEL_DIR=<installed models directory>
MT_WORKER_IDLE_TIMEOUT=86400
MT_CACHE_SIZE=100
```

The bridge waits for health and a successful warm-up translation before advertising `/translate_en_to_zh`. It continues checking sidecar health, serializes requests on one executor thread, and preserves the existing validation and error semantics.

## 12. README Onboarding Requirements

README.md is written for a teammate who knows basic shell and ROS2 commands but has never seen MTranServer or this package.

The first screen of the README must answer:

- What the package does
- Which operating system and ROS2 version it expects
- Where to copy the directory
- The shortest path from a copied directory to the first successful translation

The README contains these sections in this order:

1. Purpose and architecture in plain language
2. Prerequisites, including the explicit statement that ROS2 is not installed by the script
3. Copy/install directory example under `smart_healthcare_2026/src/mtran`
4. Run `dependencies/auto_install.sh`
5. Expected preparation outputs and how to verify them
6. Run `colcon build --packages-select mtran` from `smart_healthcare_2026`
7. Source the workspace and launch the package
8. Call `/translate_en_to_zh` and show a successful response
9. Explain service fields and error codes
10. Explain persistent model warm-up and offline runtime
11. x86_64 and ARM64 behavior
12. Repeat installation, clean rebuild, and generated-directory cleanup
13. Troubleshooting for missing ROS Humble, apt failure, Bun failure, missing model, port 8989 conflict, sidecar restart, service discovery delay, and Python user-site conflicts
14. Directory reference for maintainers

Every command block states the directory from which it is run. Expected success output is shown after preparation, build, launch, and service-call commands. README commands use relative paths wherever possible so the copied workspace location can vary.

## 13. Testing and Verification

Automated verification covers:

- Package name and generated service namespace are `mtran`
- Existing HTTP client and node tests pass after namespace changes
- `auto_install.sh` shell syntax
- Package-root resolution independent of absolute workspace path
- Rejection of unsupported OS, missing ROS Humble, and unsupported CPU architecture
- Idempotent detection of already-valid generated files
- Failure when vendored source is missing
- CMake failure with a clear instruction when preparation outputs are missing
- CMake success after fixture preparation outputs exist
- Launch defaults resolve only from install space
- Clean `colcon build --packages-select mtran`
- Full ROS2 test suite
- Real offline launch and `mtran/srv/TranslateEnglishToChinese` service call
- Copying the package to a temporary `smart_healthcare_2026/src/mtran` workspace and building it without access to the original repository tree

The final real translation smoke test uses:

```text
The robot has completed the inspection.
```

and requires a successful response with a non-empty Chinese translation.

## 14. Acceptance Criteria

- The entire package can be copied as one `mtran` directory.
- No script or launch file refers to `/home/hikos/MTranServer` or a parent source tree.
- The package is named `mtran` and exposes `mtran/srv/TranslateEnglishToChinese`.
- Vendored MTranServer source is sufficient to rebuild the sidecar without the original repository.
- `dependencies/auto_install.sh` installs non-ROS dependencies, builds the sidecar, and downloads/verifies runtime data.
- `auto_install.sh` does not install ROS2 and does not execute `colcon`.
- `dependencies/dependencies.txt` completely describes user-provided, installed, included, and downloaded dependencies.
- `colcon build --packages-select mtran` runs only after preparation and performs no network access.
- Launch uses only install-space resources.
- Runtime translation remains offline and keeps the model resident.
- README enables a new teammate to reach a successful service call without knowledge of the original repository.
