420 lines
26 KiB
Markdown
420 lines
26 KiB
Markdown
# CLAUDE.md — Rules for Claude on the Argonaut 3 Project
|
||
**Version:** 3.5
|
||
**Updated:** 8 July 2026
|
||
|
||
**Changelog 3.5:** Added `[VSC]` terminal label. Added SESSION LOG section + write triggers
|
||
(bridges Claude Code work back to claude.ai chat, which has no native access to Claude Code
|
||
sessions).
|
||
|
||
---
|
||
|
||
## PRIME DIRECTIVES — These override everything else
|
||
|
||
### 1. Research before acting. Always.
|
||
Before any technical decision, code change, or command:
|
||
- Read project docs (handover, UI design, DIR, this file) and search past chat history
|
||
- Read source code and official docs before acting; GitHub source/issues are more
|
||
authoritative than official docs for Cockpit/BlueOS specifics
|
||
- Confirm facts from sources, not from memory
|
||
|
||
If uncertain: **search first, then act**. Never guess.
|
||
|
||
### 2. Time and tokens are finite and valuable
|
||
- **Time wasting is FORBIDDEN. Token wasting is FORBIDDEN.**
|
||
- Short replies. No preamble padding. To the point.
|
||
- Never repeat an approach that has already failed
|
||
- Never ask for information already in the project docs
|
||
- Never issue a command without knowing what it will do and why
|
||
|
||
### 3. Facts only. Never assumptions.
|
||
- Do not proceed based on what "should" work
|
||
- Do not assume port, routing, or API behaviour — measure it
|
||
- Do not infer system state — verify it before issuing commands
|
||
- If a claim cannot be verified from a source, say so explicitly
|
||
- Never present a prior session's confirmed state as the current running state
|
||
|
||
---
|
||
|
||
## Working Style
|
||
|
||
### One command at a time
|
||
Give one command, wait for feedback, then give the next. Never batch commands unless asked.
|
||
|
||
### Lead with context and corrections BEFORE instructions, never after.
|
||
|
||
### Copy-paste friendly commands
|
||
Commands inside terminal blocks must be immediately copy-pasteable and suitable for the
|
||
terminal in use (Git Bash on the laptop, bash on the Pis/server). Never include:
|
||
- Placeholders like `<YOUR_IP>` or `path/to/file`
|
||
- Hashed `#` comments inside the command block
|
||
- Options that require editing before running
|
||
|
||
### Code comments
|
||
When writing code (Python, config, scripts), always include full inline comments
|
||
explaining what each section does and why. This is a standing user preference.
|
||
NOTE: this applies to CODE files only — NOT to terminal command blocks, which must
|
||
stay clean and copy-paste ready with no inline comments.
|
||
|
||
### Terminal labels
|
||
Every command block is preceded by a plain-text terminal label above the block.
|
||
Grant pastes terminal output including the shell prompt — use these to identify
|
||
which device the output came from:
|
||
|
||
| Label | Shell prompt | Device | IP |
|
||
|---|---|---|---|
|
||
| `[SERVER]` | `grant@symbytech:~$` | Dell PowerEdge R210 | 192.168.1.175 |
|
||
| `[RPi5]` | `ubuntu@rov-brain:~$` | Raspberry Pi 5 autonomy brain | 192.168.1.101 |
|
||
| `[RPi4]` | `pi@blueos:~$` | Raspberry Pi 4 BlueOS gateway | 192.168.1.100 |
|
||
| `[LAPTOP — Git Bash]` | `grant@BB8 MINGW64 ...` | Windows field laptop BB8 | — |
|
||
| `[VSC]` | — | VS Code integrated terminal on BB8 (local Windows session at `C:\Users\grant\Desktop\Autonomous ROV System`) | — |
|
||
| `[BROWSER]` | — | Web browser on laptop | — |
|
||
| `[COCKPIT]` | — | Cockpit native desktop app on laptop | — |
|
||
|
||
`[VSC]` is a **local Windows session on BB8, NOT a Remote-SSH session to rov-brain**, unless
|
||
explicitly stated otherwise. Do not assume `[VSC]` == RPi5 working copy.
|
||
|
||
Never put the label inside the bash block.
|
||
|
||
> The BlueOS KVM VM (`blueos-vm`) was decommissioned once RPi4/RPi5 hardware became
|
||
> operational. `[VM]` is no longer a valid label. Any VM artefacts remaining on the
|
||
> server are for reference only.
|
||
|
||
### Verify before modifying
|
||
Always read a file before modifying it. Always check current state before changing it.
|
||
State what you observed before proposing a change.
|
||
|
||
### File operations
|
||
Read the exact file first, then `str_replace` with exact matching text. Remove old
|
||
versions before writing new ones. Complete files, not fragments — no partial code.
|
||
|
||
### No guessing at code
|
||
When writing code that interfaces with an external system:
|
||
1. Find the official documentation or source code
|
||
2. Find a working example from the official repo or community
|
||
3. Build on the confirmed example
|
||
Never invent API calls, message formats, or connection strings.
|
||
|
||
### Own mistakes once
|
||
Acknowledge an error once and fix it. No repeated apologies, no grovelling.
|
||
|
||
### KISS
|
||
Recommend the simple correct path, not a menu of options.
|
||
|
||
---
|
||
|
||
## CREATE-THEN-BACKUP (non-negotiable)
|
||
When any new component (device, drive, service, config, OS install) is created or
|
||
configured, a backup must be put in place immediately as part of that work — not
|
||
deferred. Backups and foundational architecture (storage, recovery, monitoring) are
|
||
prerequisites, prioritised BEFORE new feature/build work. The RPi4 SD failed with no
|
||
backup because this was deferred — do not repeat.
|
||
|
||
---
|
||
|
||
## Project-Specific Rules
|
||
|
||
### Cockpit DIY widgets
|
||
- Cockpit is **v1.18.2** (native desktop app mandatory — browser/Lite extension does
|
||
NOT support DIY widgets)
|
||
- JSON format with `html`/`css`/`js` string fields
|
||
- CSS hard constraints: no `body {}`/`:root {}` global blocks, no `@keyframes`, no
|
||
unicode in JS strings, no `position: fixed`, no global tag selectors
|
||
- No `async/await` in widget JS — use `.then()/.catch()`
|
||
- Use `var` not `let`/`const` in widget JS for compatibility
|
||
- Correct live-value getter: `window.cockpit.getDataLakeVariableData(variableId)`
|
||
(CONFIRMED v1.18.2). `getDataLakeValue()` and `listenToDatalakeVariable()` do NOT
|
||
exist in DIY widget scope. `getAllDataLakeVariablesInfo()` is metadata-only.
|
||
- Widget JSON files in the repo use underscore naming: `w6_altitude.json` (matches
|
||
W0–W5). The Cockpit-loaded widget is stored by internal config, not filename, so the
|
||
repo filename is the canonical reference.
|
||
|
||
### Data injection into Cockpit data lake
|
||
- ONLY working external-injection method is the Generic WebSocket Connections feature
|
||
(Settings → General). Production path is the `cockpit_bridge` ROS2 node (rov_mission,
|
||
WebSocket :9001).
|
||
- Message format: `variable-name=value` (one per send). Data lake key: `external/{name}`.
|
||
- ALWAYS use hyphens — Cockpit normalises underscores to hyphens in IDs.
|
||
- HTTP POST to mavlink2rest does NOT work for data lake injection. MAVLink UDP injection
|
||
from external scripts does NOT work. Tested and confirmed — do not suggest them.
|
||
- Current data lake variables published by `cockpit_bridge` (19 total — 8 telemetry + 11 mode-profile flags):
|
||
|
||
| Variable | Source topic | Meaning |
|
||
|---|---|---|
|
||
| `external/rov-failsafe` | `/rov/failsafe` | 0=GREEN, 1=AMBER, 2=RED |
|
||
| `external/rov-depth` | `/rov/depth` | Depth in metres |
|
||
| `external/rov-voltage` | `/mavros/battery` | Battery voltage |
|
||
| `external/rov-heading` | `/mavros/mavros/compass_hdg` | Compass heading degrees |
|
||
| `external/rov-ms` | `/rov/mission/status` | Mission state integer |
|
||
| `external/rov-mp` | `/rov/mission/status` | Mission progress 0-100% |
|
||
| `external/rov-recording` | `/rov/recording/active` | 1=recording, 0=not recording |
|
||
| `external/rov-altitude` | `/ping2/altitude` | Ping2 altitude metres (-1.0=NO SONAR) |
|
||
| `external/rov-mode` | `/rov/mode/profile` | Active profile name: ROV / AUV / hybrid |
|
||
| `external/rov-mode-base` | `/rov/mode/profile` | Base mode: 0=ROV, 1=AUV |
|
||
| `external/rov-hilt` | `/rov/mode/profile` | HILT: 1=present, 0=absent |
|
||
| `external/rov-health-role` | `/rov/mode/profile` | W1: 0=advisory, 1=gate |
|
||
| `external/rov-rec-control` | `/rov/mode/profile` | Recording: 0=manual, 1=auto |
|
||
| `external/rov-nogo-gate` | `/rov/mode/profile` | No-go: 0=relaxed, 1=enforced |
|
||
| `external/rov-rec-reminder` | `/rov/mode/profile` | ARM reminder: 1=on, 0=off |
|
||
| `external/rov-return-mode` | `/rov/mode/profile` | Return: 0=operator-selectable, 1=autonomous |
|
||
| `external/rov-live-telem` | `/rov/mode/profile` | Telemetry: 0=on, 1=predive-only |
|
||
| `external/rov-nav-display` | `/rov/mode/profile` | Nav: 1=shown, 0=autonomy-only |
|
||
| `external/rov-camera-role` | `/rov/mode/profile` | Camera: 0=pilot-primary, 1=record-only |
|
||
|
||
### FastAPI backend (rov_api)
|
||
- `rov_api` package provides the HTTP-to-ROS2 bridge on port 8081. Runs as
|
||
`argonaut-api.service` (manual-start in dev, same policy as argonaut.service).
|
||
- Architecture: uvicorn/FastAPI in the main thread, an embedded rclpy node
|
||
(`RovApiNode`) spinning in a daemon background thread. HTTP handlers call thread-safe
|
||
methods on the node. Do NOT call `rclpy.spin()` more than once.
|
||
- Core endpoints (Stage 2, live): `GET /health`, `POST /abort` (W3 RETURN TO SAFE,
|
||
publishes Bool to `/rov/mission/abort`), `POST /mission/start` (MissionCommand START),
|
||
`POST /mission/stop` (MissionCommand ABORT).
|
||
- Deferred to Stage 2b: `/return_budget` (W5), `/backup/status` + `/backup/delay` (W7,
|
||
Option A design), `/mission/upload`.
|
||
- **W3 abort path is vehicle-layer:** publishes Bool(true) to `/rov/mission/abort`, which
|
||
failsafe_monitor latches as `flag_manual_abort` → FSM NORMAL → HOLD_AND_RECOVER. This is
|
||
DIR-5 return-to-safe, NOT the mission ABORT service. Do not confuse the two.
|
||
- **Python dependencies:** fastapi + uvicorn installed system-wide on RPi5 via
|
||
`sudo pip3 install fastapi uvicorn --break-system-packages --ignore-installed typing_extensions`.
|
||
The `--ignore-installed typing_extensions` flag is required — the Debian-managed
|
||
typing_extensions has no pip RECORD file and blocks the install otherwise.
|
||
|
||
### Deploy files (version-controlled)
|
||
- systemd units and launch wrappers live outside the workspace but are version-controlled
|
||
in the repo `deploy/` folder (copies; authoritative running copies at deploy locations).
|
||
- `deploy/argonaut.service` → `/etc/systemd/system/argonaut.service`
|
||
- `deploy/argonaut-stack.sh` → `/usr/local/bin/argonaut-stack.sh`
|
||
- `deploy/argonaut-api.service` → `/etc/systemd/system/argonaut-api.service`
|
||
- `deploy/argonaut-api.sh` → `/usr/local/bin/argonaut-api.sh`
|
||
- `deploy/README.md` documents locations, pip deps, and install procedure.
|
||
- `/home/ubuntu/ros2_ws` is a symlink to `/data/ros2_ws` — both wrappers rely on it.
|
||
|
||
### Recording architecture (DIR-9a — ARM-bounded black-box)
|
||
- Recording is a **single ARM-bounded tier** for black-box/debug/ML/fault-finding via
|
||
`recording_manager`. **AUV:** starts on ARM, stops on DISARM. **ROV:** operator
|
||
start/stop; the ARM edge fires a reminder ("armed, not recording"). Keyed to the
|
||
`recording_control` flag, not the mode. (Supersedes the old continuous DIR-9 model.)
|
||
- **No-go coupling:** AUV `enforced` — recording fail → mission stops, vehicle recovered.
|
||
ROV `relaxed` — recording fail after ARM → pilot alerted; operator resolves in-water
|
||
or recovers.
|
||
- Certified deliverable capture is OUT of scope pending Class-approved devices; recorded
|
||
data is dev/debug/ML only, never a client deliverable until then.
|
||
- The recorder manages a `ros2 bag record` subprocess — MCAP format, zstd compression,
|
||
500MB bag splitting, 10GB free-space retention on `/data`.
|
||
- **`foxglove_bridge` is visualisation only — it does NOT record MCAP.** Correct this
|
||
wherever the old "MCAP via foxglove_bridge" claim appears.
|
||
- Bags written to `/data/bags/dive_<timestamp>/` on NVMe.
|
||
- No camera in the topic set currently — recording ~2.5 MB/s (nav/MAVLink only).
|
||
- **Storage (no reliable in-field server backup):** primary lever is LOWER PUBLISH RATES
|
||
on heavy streams (keep topics present for debug); ARM-bounded runs self-limit; retention
|
||
cap tunable; NVMe expansion later. Topic/rate review is an open action.
|
||
|
||
### Operating-mode profiles (DIR-1/2, mode_profiles.yaml)
|
||
- One widget set; behaviour is set by flags from a mode profile. Dominant axis is HILT
|
||
(tether present = ROV / live interfaces; absent = AUV / headless).
|
||
- **Source of truth:** `mode_profiles.yaml` in `rov_mission/config` — ROV/AUV defaults
|
||
plus custom hybrid via "Save As". Hybrid is NOT a third mode; it is any saved profile
|
||
with overrides.
|
||
- `mode_profile_loader` (rov_mission) resolves the active profile into a `ModeProfile`
|
||
message (rov_interfaces), publishes it LATCHED on `/rov/mode/profile`, reloadable via
|
||
the `/rov/mode/reload` (std_srvs/Trigger) service. Fail-safe: invalid flag values are
|
||
rejected and the last-good profile is retained.
|
||
- `cockpit_bridge` surfaces the 11 flags to the data lake as `external/rov-*`. Widgets
|
||
read the flags, NOT the mode.
|
||
- Flags: hilt, health_role (advisory|gate), recording_control (manual|auto), nogo_gate
|
||
(relaxed|enforced), record_reminder_on_arm, return_mode (operator_selectable|autonomous),
|
||
live_telemetry (on|predive_only), nav_display, camera_role (pilot_primary|record_only).
|
||
- **YAML gotcha:** YAML 1.1 parses bare `on`/`off`/`yes`/`no` as booleans — quote enum
|
||
values like `"on"`. The loader also normalises bool→string as a guard.
|
||
|
||
### BlueOS / MAVLink router
|
||
- **MAVLinkRouter** is the confirmed router. Do NOT recommend MAVP2P — BlueOS itself
|
||
warns "MAVP2P has been presenting issues and is not currently recommended."
|
||
- MAVP2P was tried and reverted. Do not suggest it again.
|
||
- **ardupilot-manager FD exhaustion — CORRECTED ROOT CAUSE (9 Jul 2026).** The earlier claim that this was "fixed permanently" by `/etc/docker/daemon.json` `nofile: 65536`, with root cause "UI polling TCP sockets," is WRONG on both counts. The `nofile` change only raised the ceiling (failure at ~10 min → ~11 h of cumulative exposure); it fixed nothing. The leaked FDs are `/dev/i2c-1` handles, NOT TCP sockets. Measured mechanism: BlueOS's Autopilot Firmware / board-config page polls `GET /v1.0/available_boards`; each request triggers 20 `flight_controller_detector.linux.detector:detect_boards` probes for Navigator / NavigatorPi4 / NavigatorPi5 / Argonot. Each Linux-board probe opens `/dev/i2c-1` and never closes it on failure. We run a Pixhawk 2.4.8 on USB serial (PlatformType.Serial), so every probe fails and every probe leaks. Measured leak rate ~100–108 FD/min with the board-config page open; exactly zero with it closed (4630 flat over 65 min, then +90 FD in 50 s on opening the page, flat again immediately on closing). Confirmed cause-and-effect, reversible. Note: FD count accumulates across sessions and only resets when `blueos-core` is recreated (core restart/reboot) — cumulative page-open time, not wall-clock, drives time-to-failure. At 65536 FDs, ardupilot-manager can no longer open new handles → AUTOPILOT_VEHICLE_TYPE_FETCH_FAIL, AUTOPILOT_ENDPOINT_FETCH_FAIL, BAG_OF_HOLDING_GET_DATA_FAIL, "No board running". Core restart recreates the container with a fresh FD table, which is why restarting always "fixed" it. This is an upstream BlueOS 1.4.3 bug; do NOT patch BlueOS (updates would revert it).
|
||
- **Mitigation (dev):** do not leave the BlueOS Autopilot Firmware / board-config page open. Open, act, close. Other BlueOS pages and Cockpit are unaffected.
|
||
- **Mitigation (field) — NOT YET IMPLEMENTED:** operator discipline is not a field-safe control. The exposure is launching with a nearly-exhausted FD table after pre-dive setup, not leakage during the dive itself. Required: (a) FD-count check on ardupilot_manager as part of the AUV pre-dive gate, blocking launch above a threshold; (b) failsafe_monitor must detect FC comms loss so W1 goes RED when the board is unreachable. See open items.
|
||
|
||
### Hardware facts (do not re-question)
|
||
- **RPi5 storage:** boots from SD card (`/dev/mmcblk0`). NVMe holds DATA ONLY (`/data` —
|
||
ros2_ws, bags, logs). Backup images the SD for OS, rsyncs `/data` for data.
|
||
- **Flight controller:** Pixhawk 2.4.8 on `/dev/ttyACM0` is the active flight controller.
|
||
SITL is NOT used in production. BlueOS `preferred_board` = Pixhawk1.
|
||
- **Tailscale on RPi5:** installed but stopped and disabled (`tailscaled.service` disabled
|
||
2 Jul 2026). Re-enable with `sudo systemctl enable --now tailscaled` if remote access
|
||
to RPi5 is needed.
|
||
|
||
### Hostname resolution (DNS)
|
||
- Hostnames `symbytech` (192.168.1.175), `blueos` (192.168.1.100), and `rov-brain`
|
||
(192.168.1.101) are resolvable from the laptop (Windows hosts file) and RPi5
|
||
(`/etc/hosts`). Grant prefers hostnames over IPs.
|
||
- Git remotes use the hostname form: `ssh://git@symbytech:222/administrator/rov-autonomy.git`
|
||
- If a "Could not resolve hostname symbytech" error appears on a machine, that machine is
|
||
missing the hosts entries — add them rather than switching remotes to IPs.
|
||
|
||
### Backup system (built 30 Jun 2026)
|
||
- Push model: each Pi self-backs-up via root cron, pushes to server over SSH (no inbound
|
||
access to Pis).
|
||
- RPi4: `/usr/local/bin/rov-brain-pi4-backup.sh`, 00:00 daily.
|
||
- RPi5: `/usr/local/bin/rov-brain-pi5-backup.sh`, 00:30 daily (staggered).
|
||
- Server monitor `check_rov_backup` alerts on FAILED (always) and OVERDUE (≥2 days,
|
||
online or offline, throttled weekly).
|
||
- Field/ops backup model is operator-aware, never unattended mid-dive (DIR-11, W7).
|
||
|
||
### argonaut.service / argonaut-api.service (RPi5)
|
||
- Manual start is deliberate for both. Verify BlueOS heartbeat first, then
|
||
`sudo systemctl start argonaut.service`. Do NOT enable auto-start until field-ready.
|
||
Restate this rule each time it comes up.
|
||
- `argonaut-api.service` orders After=argonaut.service but does not Require it — the API
|
||
can start independently for /health checks; mission commands return a clear
|
||
"service unavailable" error if the stack is down.
|
||
|
||
### ROS2 code
|
||
- Check `rov_interfaces` message definitions before writing any node code
|
||
- Use `self.get_logger()` not `print()`
|
||
- Do not hardcode IPs, ports, or thresholds
|
||
- Do not deploy `rov_simulation` in production launch files
|
||
- Editing an installed launch/config requires `colcon build --packages-select <pkg>` —
|
||
the running launch uses the installed copy under install/, not src/
|
||
- ARM64 Docker builds on the laptop only (buildx), never on the server
|
||
|
||
### Git workflow
|
||
- Commit to `master` on `administrator/rov-autonomy`
|
||
- Gitea SSH remote (hostname form): `ssh://git@symbytech:222/administrator/rov-autonomy.git`
|
||
- Both laptop and RPi5 resolve `symbytech` via hosts entries (see Hostname resolution).
|
||
- Widget JSON files are re-imported from the laptop (source of truth for widgets) and
|
||
pushed to Gitea — never overwritten from chat history.
|
||
- UFW rules before starting new services on new ports.
|
||
|
||
### Security — deferred to pre-field hardening pass
|
||
- **UFW:** currently inactive on RPi5. Deferred because there is no online exposure
|
||
(Tailscale disabled, no proxy rules to the Pis). When enabling: allow SSH (22),
|
||
operator TCP (8765, 9001, 8081), and all traffic from LAN subnet 192.168.1.0/24
|
||
(covers ROS2 DDS dynamic ports — do NOT try to pin them individually), then default
|
||
deny incoming. Bundle with SSH password change. Trigger: before remote ops or field.
|
||
- **RPi5 SSH password:** weak dev password, password auth enabled. Change to strong
|
||
password before field deployment.
|
||
|
||
---
|
||
|
||
## What Claude MUST do
|
||
- State confirmed facts before proposing an action; cite the source of any technical claim
|
||
- Acknowledge when something has already been tried and failed
|
||
- Provide complete, working code (fully commented) based on confirmed examples
|
||
- Verify system state before and after changes
|
||
- Update the handover doc at the end of each session (version-controlled, changelog)
|
||
|
||
## What Claude MUST NOT do
|
||
- Guess at how a system works and propose commands based on that guess
|
||
- Repeat a failed approach
|
||
- Issue commands whose outcome is uncertain
|
||
- Provide partial code requiring manual editing to work
|
||
- Assume a system is stable without checking
|
||
- Use `print()` in ROS2 nodes; hardcode addresses/ports/thresholds
|
||
- Build x86 Docker images for vehicle deployment
|
||
- Change the failsafe priority order without design review
|
||
- Present prior-session state as current running state
|
||
- Recommend MAVP2P as the MAVLink router
|
||
- Commit docs to Gitea — only code and README go to Gitea; docs live in Claude project knowledge
|
||
|
||
---
|
||
|
||
## Documentation discipline
|
||
- All project docs (handover, UI design, DIR, this file, sim/ML plan) are maintained as
|
||
COMPLETE replacement files uploaded to Claude project knowledge — never patches or
|
||
fragments, never committed to Gitea.
|
||
- Version numbers and changelogs maintained on every update.
|
||
- Only code and README files go to Gitea.
|
||
|
||
---
|
||
|
||
## SESSION LOG (bridges Claude Code → claude.ai chat)
|
||
|
||
**Why this exists:** Claude Code (VS Code) and the claude.ai chat are separate systems with
|
||
no shared memory. Claude Code reads this file at session start but the claude.ai chat cannot
|
||
see Claude Code's session history at all. This log is the bridge.
|
||
|
||
**Format:** `YYYY-MM-DD — one-line summary of decision/change (commit hash if applicable)`
|
||
|
||
**Claude Code MUST append an entry here at the end of any session where one of these
|
||
happened** — not for routine edits, refactors, or in-progress work:
|
||
- A design/architecture decision was made or changed (DIR-level, mode-flag behaviour,
|
||
failsafe priority, recording behaviour)
|
||
- A hardware fact was confirmed or changed (wiring, storage layout, board config)
|
||
- A security-relevant change was made (SSH, UFW, credentials, exposure)
|
||
- A backup/recovery-relevant change was made
|
||
- A bug was root-caused and fixed (not just patched)
|
||
- A previously-deferred item was completed or its trigger condition changed
|
||
- Anything Grant would reasonably expect the claude.ai chat to already know next time he
|
||
opens it
|
||
|
||
**Skip:** typo fixes, comment-only changes, WIP/incomplete work, anything already fully
|
||
captured by the git commit message with no extra context needed.
|
||
|
||
**Workflow:** Grant pastes new entries into the claude.ai chat when relevant; Claude folds
|
||
them into chat memory via the memory tool. This log is append-only — do not edit past
|
||
entries; correct forward with a new dated entry if something needs revising.
|
||
|
||
- 2026-07-05 — Widget housekeeping: added W6 altitude widget, removed probe diagnostics
|
||
widget (`785ec56`)
|
||
- 2026-07-08 — rov_api: added GET /mode and POST /mode endpoints (validate-before-write +
|
||
/rov/mode/reload trigger); deployed and tested on RPi5, all paths verified (9109439)
|
||
- 2026-07-08 — Root-caused chronic widget "no data": cockpit_bridge (feeds Cockpit data
|
||
lake on :9001) launched but had no respawn, so a boot-time race left it permanently
|
||
dead. Added respawn=True to its launch Node. W8 mode indicator built + validated live
|
||
(render+data). W1/W8 confirmed GREEN/AUV once bridge up.
|
||
- 2026-07-08 — FLAGGED (open): recording_manager.py still implements superseded DIR-9
|
||
(continuous-from-boot recording), NOT the governing DIR-9a (ARM-bounded black-box:
|
||
AUV ARM-start/DISARM-stop, ROV operator manual + arm reminder). Design decision
|
||
exists only in handover + CLAUDE.md; code never updated. foxglove_mcap.launch.py
|
||
comments also still say DIR-9. Also: argonaut-stack.sh passes record:=${RECORD} but
|
||
rov_full.launch.py declares no such arg, so RECORD=false is silently ignored and
|
||
bags record regardless. Both deferred to a dedicated DIR-9a recorder-rework session
|
||
— do NOT wire RECORD into the current DIR-9 model.
|
||
- 2026-07-08 — Added respawn=True/respawn_delay=5.0 to failsafe_monitor,
|
||
motion_controller, ekf_filter_node, depth_node, mission_executor. Deliberately NOT
|
||
applied to: mavros_node (respawn could mask/worsen the chronic FCU-link instability
|
||
— belongs in that investigation), recording_manager (pending DIR-9a rework),
|
||
camera_node/feature_detector (perception not operational yet), foxglove_bridge
|
||
(viz-only). NOTE: failsafe_monitor respawn has a coverage gap during the 5s respawn
|
||
delay — no failsafe assessment in that window; flagged for future design
|
||
consideration.
|
||
- 2026-07-09 — Root-caused the recurring "No board running" / AUTOPILOT_*_FETCH_FAIL
|
||
failure. NOT the previously-documented TCP-socket/UI-polling cause. Real cause:
|
||
/dev/i2c-1 FD leak in ardupilot_manager's Linux board detector, driven by the BlueOS
|
||
board-config page polling available_boards (20 probes/request, ~100-108 FD/min).
|
||
Zero leak with page closed; confirmed reversible by controlled test (4630 flat 65min,
|
||
+90 FD in 50s on open, flat on close). nofile=65536 only delayed failure to ~11h
|
||
cumulative page-open time. Upstream BlueOS 1.4.3 bug — not patching. Corrected the
|
||
stale root cause in this file.
|
||
- 2026-07-09 — FLAGGED (open, safety-critical): failsafe_monitor reports GREEN with the
|
||
flight controller unreachable. W1 is the AUV pre-dive GO/NO-GO gate (health_role=gate)
|
||
— it would pass a dive with a dead FC. failsafe_monitor must consume /mavros/state
|
||
connection + heartbeat and drive W1 RED on FC comms loss. W1 status line should carry
|
||
cause text (e.g. "Vehicle Disconnected", "Heartbeat Lost", "No Board Running"). Also
|
||
flagged: no FD-count check on ardupilot_manager in the pre-dive gate.
|
||
|
||
---
|
||
|
||
## Key Reference Documents (current versions)
|
||
|
||
| Document | Purpose |
|
||
|---|---|
|
||
| `ROV_Project_Handover_v2_21.md` | Master reference — architecture, environment, commands, status board |
|
||
| `design_intent_register_DRAFT.md` | DIR-1…DIR-11 (+ DIR-9a) — owner/operator intent, source of truth for *why*; recording now ARM-bounded per DIR-9a |
|
||
| `ROV_Failsafe_Design_v2_0.md` | Failsafe state machine, sensor roadmap, priority order |
|
||
| `Argonaut3_UI_Design_v1_9.md` | Cockpit widget specs (W0–W7) and confirmed data paths |
|
||
| `Mission_and_Data-Recording_Lifecycle_for_AUV_ROV_Systems...md` | Lifecycle research backing DIR-9/10 |
|
||
| `Argonaut3_Simulation_ML_Tooling_Plan_v1_0.md` | Simulation + ML tooling: dev-PC tiers, cloud options/cost, training assets/datasets/models, PCIe Gen 3 decision |
|
||
|
||
> When referencing these, use the latest version present in the project folder — do not
|
||
> cite a version number from memory if a newer file exists.
|
||
|
||
---
|
||
|
||
## Safety Notice
|
||
This is a production-oriented autonomous safety system. All code must be treated as if it
|
||
will run on a real vehicle in open water with no operator present. Safety, correctness,
|
||
and reliability are non-negotiable. Shortcuts taken during development become risks during
|
||
field operations.
|