|
| 1 | +# LinuxCNC Fork — Agent Guidelines |
| 2 | + |
| 3 | +Reference: https://linuxcnc.org/docs/devel/html/code/building-linuxcnc.html |
| 4 | + |
| 5 | +Build mode: **run-in-place**, **uspace** (Preempt-RT / non-realtime simulator). |
| 6 | +Do not build docs or packages unless explicitly asked. |
| 7 | + |
| 8 | +## Public fork warning |
| 9 | + |
| 10 | +This is `is-primary-dev/linuxcnc`, a **public** fork of upstream LinuxCNC. **Never reference private repo names, paths, hardware specifics, internal customer data, or personal information in any committed file.** Cross-references only go from private repos → public fork, never public → private. Before committing, grep for any leaked terms. See `memory/feedback_public_fork.md`. |
| 11 | + |
| 12 | +## Upstream composability |
| 13 | + |
| 14 | +This is a fork. Every commit must stay composable with upstream LinuxCNC pulls — modifications to upstream files create merge conflict surface on every `git pull upstream master`. |
| 15 | + |
| 16 | +- **Do NOT modify upstream-authored files** — `README.md`, `INSTALL`, `COPYING`, `AUTHORS`, `src/`, `lib/`, `configs/`, `docs/`, `tcl/`, `python/`, `scripts/`, `debian/`, etc. If a fix needs to go upstream, use the **Upstream PR prep** workflow below — never modify upstream files directly in fork master. |
| 17 | +- **Do NOT create new human docs at linuxcnc root** — `DEVELOPMENT.md`, `TESTING.md`, `BUILD.md` would overlap with upstream's `README.md` and `scripts/` and may collide on syncs. Fork-specific dev notes go in `memory/reference_*.md`, lazy-loaded. |
| 18 | +- **Fork-only additions go in fork-only files:** `AGENTS.md`, `CLAUDE.md`, `MEMORY.md`, `memory/`, `TODO.md`, `.claude/settings.json` (gitignore exception), `agent-helpers/`. |
| 19 | +- **If unsure whether a file is upstream-owned, ask the operator before editing.** Default to "don't touch." |
| 20 | + |
| 21 | +## Safe Action Protocol |
| 22 | + |
| 23 | +All agent actions that touch shared state (build, test, git, halcmd, file edits to the deployed source tree) go through `agent-helpers/safe-agent-action.sh`. The wrapper is the single permission entry — no per-command prompts. |
| 24 | + |
| 25 | +**Wrapper covers:** |
| 26 | +- `git <subcommand>` — feature-branch git work (commit, push, fetch, rebase, merge, checkout, reset, clean, cherry-pick, worktree, `commit --amend`, force-push to feature branches) |
| 27 | +- Session lifecycle: `session-start <name>`, `session-push`, `session-merge <name>` |
| 28 | +- Build: `make`, `make-raw`, `setuid`, `configure`, `autogen`, `syntax-check` |
| 29 | +- Read-only inspection: `grep`, `find`, `view`, `tail`, `du`, `ps`, `pgrep` |
| 30 | +- LinuxCNC: `linuxcnc`, `halcmd`, `halrun`, `halcompile`, `runtests`, `latency-watch` |
| 31 | +- Upstream contribution: `upstream-pr-prep` (see Upstream PR prep section below) |
| 32 | + |
| 33 | +**Built-in Read/Edit/Write/Grep/Glob do NOT need the wrapper** — they don't go through Bash. |
| 34 | + |
| 35 | +**Bare git is permitted only for these cases the wrapper intentionally refuses:** |
| 36 | +1. `git push` / `git merge` targeting `master` or `main` |
| 37 | +2. `git push` to the `upstream` remote |
| 38 | +3. `git filter-branch`, `git update-ref` |
| 39 | +4. `git branch -D master` / `branch -M main` |
| 40 | + |
| 41 | +The merge-to-master sequence (`git switch master && git merge --no-ff <feature> && git push`) is the canonical bare-git case. **Merging to master is always an operator approval gate.** "Continue" is NOT merge approval — ask explicitly ("merge now?") and wait for a clear yes. |
| 42 | + |
| 43 | +**Subagents don't inherit wrapper permission.** When spawning one (Agent tool), tell it to use built-in Read/Grep/Glob, or to call `safe-agent-action.sh` explicitly. |
| 44 | + |
| 45 | +**If the wrapper lacks a subcommand you need, add it** (one `case` branch in the script) rather than falling back to bare bash. |
| 46 | + |
| 47 | +## Session startup |
| 48 | + |
| 49 | +Pre-flight checklist before any work in a new session: |
| 50 | + |
| 51 | +1. **Read AGENTS.md** (auto-loaded via `CLAUDE.md` → `@AGENTS.md`). |
| 52 | +2. **Scan `MEMORY.md`** for topic-relevant entries; read individual `memory/*.md` entries on demand. |
| 53 | +3. **Create/switch to a session branch** via `agent-helpers/safe-agent-action.sh session-start <plan-name>`. Plan file basename (without `.md`) is the branch name. |
| 54 | +4. **Use the wrapper from command #1.** No bare git, no bare grep, no subagents shelling out. |
| 55 | + |
| 56 | +If the user hands off a task, acknowledge it, run the checklist, then start work. |
| 57 | + |
| 58 | +## File ownership and audience separation |
| 59 | + |
| 60 | +| File | Audience | Purpose | |
| 61 | +|---|---|---| |
| 62 | +| `README.md` (upstream) | Human + agent | Upstream LinuxCNC build/usage docs | |
| 63 | +| `AGENTS.md` | Agent only | Hard rules + protocols. Always loaded via `CLAUDE.md`. | |
| 64 | +| `MEMORY.md` | Agent only | One-line-per-entry index. Pure index. | |
| 65 | +| `memory/*.md` | Agent only | Topic knowledge, judgments, learnings. Lazy-loaded on demand. | |
| 66 | +| `TODO.md` | Human + agent | Deferred work, known issues, plain bullets. | |
| 67 | +| `agent-helpers/README.md` | Human + agent | Wrapper and helper script docs. | |
| 68 | + |
| 69 | +**Routing rule:** when AGENTS.md covers a topic that has a human doc (upstream `README.md`, `agent-helpers/README.md`), AGENTS.md should **point**, not **restate**. |
| 70 | + |
| 71 | +## Memory routing |
| 72 | + |
| 73 | +`MEMORY.md` is a one-line-per-entry index. **Scan it at session startup** (step 2 of the checklist) and read individual `memory/*.md` entries on demand when task-relevant. |
| 74 | + |
| 75 | +Auto-memory (harness-level) is **disabled** via `.claude/settings.json:autoMemoryEnabled=false`. In-repo `memory/` is the sole source of truth for persistent agent knowledge. |
| 76 | + |
| 77 | +## Git conventions |
| 78 | + |
| 79 | +- **`origin`** = `https://github.com/is-primary-dev/linuxcnc.git` (the fork). All `git push` goes here. |
| 80 | +- **`upstream`** = `https://github.com/LinuxCNC/linuxcnc.git` (main project). Pulled from, never pushed to (the wrapper refuses). |
| 81 | +- **Sync from upstream:** `git fetch upstream && git merge upstream/master`. |
| 82 | + |
| 83 | +## Build / Run / Test / Clean |
| 84 | + |
| 85 | +```bash |
| 86 | +# Build (incremental, auto-restores setuid) |
| 87 | +agent-helpers/safe-agent-action.sh make -j$(nproc) |
| 88 | + |
| 89 | +# Build a single target |
| 90 | +agent-helpers/safe-agent-action.sh make ../bin/<name> |
| 91 | + |
| 92 | +# Run with an INI (auto-sources rip-environment, requires DISPLAY=:0) |
| 93 | +agent-helpers/safe-agent-action.sh linuxcnc <path-to-ini> |
| 94 | + |
| 95 | +# Test |
| 96 | +source scripts/rip-environment && runtests |
| 97 | +# Options: -v verbose, -s stop on failure, -n keep artifacts, -u skip sudo tests |
| 98 | + |
| 99 | +# Clean |
| 100 | +agent-helpers/safe-agent-action.sh make-raw clean |
| 101 | +agent-helpers/safe-agent-action.sh make-raw distclean # full reset, must re-run setup steps 4–5 |
| 102 | +``` |
| 103 | + |
| 104 | +**Common sim configs:** |
| 105 | +- `configs/sim/axis/axis.ini` — classic Axis GUI |
| 106 | +- `configs/sim/qtdragon_hd/qtdragon_hd_xyz/qtdragon_hd_xyz.ini` — QtDragon HD |
| 107 | + |
| 108 | +**Background launch with output capture:** `script -qec "DISPLAY=:0 linuxcnc" /dev/null 2>&1` and use Bash `run_in_background`. `script` provides a pseudo-TTY — without it, the launcher redirects output to temp files that are deleted on exit. Spawn a monitoring agent to watch the background output, report status, and summarize when done. |
| 109 | + |
| 110 | +**Full build with documentation** (only when asked, significantly slower): |
| 111 | +```bash |
| 112 | +cd src && ./configure --with-realtime=uspace --enable-build-documentation && make clean && make -j$(nproc) && cd .. |
| 113 | +``` |
| 114 | + |
| 115 | +## One-Time Setup |
| 116 | + |
| 117 | +For first-time setup on a fresh clone (8 numbered steps with checks, covering Debian verification, debian/control generation, build deps, runtime deps, configure script generation, build configuration, agent-helpers hook installation, realtime/setuid setup, and optional RT machine tuning): see [memory/reference_fork_setup.md](memory/reference_fork_setup.md). |
| 118 | + |
| 119 | +## Upstream PR prep |
| 120 | + |
| 121 | +To upstream a fix from fork `master` to `LinuxCNC/linuxcnc`, use the wrapper subcommand (not raw cherry-pick, not the helper script directly — the latter bypasses the auto-approval hook): |
| 122 | + |
| 123 | +```bash |
| 124 | +agent-helpers/safe-agent-action.sh upstream-pr-prep \ |
| 125 | + --commit <fork-sha> \ |
| 126 | + --branch <pr-branch-name> \ |
| 127 | + --message /tmp/upstream-commit-msg.txt \ |
| 128 | + --worktree /var/tmp/linuxcnc-pr-<branch> \ |
| 129 | + [--build] [--push] [--cleanup] [--dry-run] |
| 130 | +``` |
| 131 | + |
| 132 | +The wrapper dispatches to `agent-helpers/upstream-pr-prep.sh`. The script uses `git worktree` (not `git switch -c`, which would wipe `agent-helpers/` from the main working tree) so the main fork tree stays intact, dynamically resolves the GitHub-noreply author via `gh api user`, and verifies the cherry-picked diff against `upstream/master`. Prerequisites: `gh auth login`, `jq`. |
| 133 | + |
| 134 | +**Full procedure, prerequisites, workflow notes (worktree rationale, message handling, build flags, why `travis-install-build-deps.sh` is forbidden), and worked example (PR #3933):** see [memory/reference_upstream_pr_workflow.md](memory/reference_upstream_pr_workflow.md). |
| 135 | + |
| 136 | +## Gotchas |
| 137 | + |
| 138 | +- `apt-get build-dep .` only installs build deps — runtime deps (e.g., `python3-qtpy`) must be installed separately for run-in-place. New deps added in 2.10 won't be present from a 2.9.8 system install. |
| 139 | +- **Run latest build requires `rip-environment`** — without sourcing `scripts/rip-environment`, the system-installed LinuxCNC runs instead of the source build. The `linuxcnc` launcher auto-sources it, but bare commands like `halcmd`, `halrun`, `runtests` need it explicitly. |
| 140 | +- **`DISPLAY=:0` required** — `linuxcnc` without an INI opens a Tk GUI picker. |
| 141 | + |
| 142 | +## Environment |
| 143 | + |
| 144 | +- OS: Debian Trixie (13), Python 3.13, PREEMPT_RT kernel |
| 145 | +- LinuxCNC version: 2.10.0~pre1 |
| 146 | +- Build mode: run-in-place (RIP), uspace |
0 commit comments