mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
Normalize line endings to LF
.gitattributes sets text=auto with eol=lf, so every text file is stored and checked out with LF, and a patch keeps its bytes. The files that carried CRLF from a Windows editor are renormalized. No content changes.
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# Every text file is stored and checked out with LF; a patch keeps its bytes.
|
||||||
|
* text=auto eol=lf
|
||||||
|
*.patch -text
|
||||||
|
*.diff -text
|
||||||
@@ -1,398 +1,398 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
Instructions for AI coding agents that work in this repository. A human
|
Instructions for AI coding agents that work in this repository. A human
|
||||||
contributor is welcome to read it too: it is the same set of rules.
|
contributor is welcome to read it too: it is the same set of rules.
|
||||||
|
|
||||||
## ForgeFIRM repository rules
|
## ForgeFIRM repository rules
|
||||||
|
|
||||||
### Safety on the machine
|
### Safety on the machine
|
||||||
|
|
||||||
- The laser never fires with the coolant pump deliberately off. The heater-only
|
- The laser never fires with the coolant pump deliberately off. The heater-only
|
||||||
flow-calibrate and flow-verify tools are the only pump-off state, and the
|
flow-calibrate and flow-verify tools are the only pump-off state, and the
|
||||||
tube stays dark during them.
|
tube stays dark during them.
|
||||||
- The 40 V motor rail stays up while the machine is on. Never cycle it for a
|
- The 40 V motor rail stays up while the machine is on. Never cycle it for a
|
||||||
controller handover. A rail glitch can leave the stepper drivers
|
controller handover. A rail glitch can leave the stepper drivers
|
||||||
unserviceable.
|
unserviceable.
|
||||||
|
|
||||||
### The iteration loop
|
### The iteration loop
|
||||||
|
|
||||||
- Edit, cross-build in the Yocto build environment, hot-deploy to the
|
- Edit, cross-build in the Yocto build environment, hot-deploy to the
|
||||||
machine, prove. Then one commit, one push, one pin bump for the proven
|
machine, prove. Then one commit, one push, one pin bump for the proven
|
||||||
change.
|
change.
|
||||||
- A full image build happens once, at the end of a work item, never per fix.
|
- A full image build happens once, at the end of a work item, never per fix.
|
||||||
- Kernel and BSP changes ride one image flash, batched. Validate a `.ko` or
|
- Kernel and BSP changes ride one image flash, batched. Validate a `.ko` or
|
||||||
overlay change on the image that ships it. Never hot-swap a `.ko` onto a
|
overlay change on the image that ships it. Never hot-swap a `.ko` onto a
|
||||||
board that is about to be reflashed.
|
board that is about to be reflashed.
|
||||||
|
|
||||||
### Acceptance coverage
|
### Acceptance coverage
|
||||||
|
|
||||||
- Evaluate every change against the acceptance catalog in
|
- Evaluate every change against the acceptance catalog in
|
||||||
`forgetest/forgetest/suite/`. Does an existing test exercise the changed
|
`forgetest/forgetest/suite/`. Does an existing test exercise the changed
|
||||||
behavior? Does its `covers` map name the files you touched? If not, add or
|
behavior? Does its `covers` map name the files you touched? If not, add or
|
||||||
widen one in the same change. The coverage lint
|
widen one in the same change. The coverage lint
|
||||||
(`python3 -m forgetest.coverage --enforce`) is the floor.
|
(`python3 -m forgetest.coverage --enforce`) is the floor.
|
||||||
- The `SRCREV` of a component and the `PV` that moves with it live in
|
- The `SRCREV` of a component and the `PV` that moves with it live in
|
||||||
`<recipe>-pin.inc` next to the recipe. Nothing else goes in that file. The
|
`<recipe>-pin.inc` next to the recipe. Nothing else goes in that file. The
|
||||||
image manifest keeps `*-pin.inc` out of the layer content hash. Thus a pin
|
image manifest keeps `*-pin.inc` out of the layer content hash. Thus a pin
|
||||||
bump invalidates only the acceptance tests that cover that component. A
|
bump invalidates only the acceptance tests that cover that component. A
|
||||||
pin in a recipe body counts as a platform change and needs a full
|
pin in a recipe body counts as a platform change and needs a full
|
||||||
acceptance campaign.
|
acceptance campaign.
|
||||||
- Test a harness change yourself, on the host, before you hand it to the
|
- Test a harness change yourself, on the host, before you hand it to the
|
||||||
operator for a bench run. A harness that fails on its own defect costs the
|
operator for a bench run. A harness that fails on its own defect costs the
|
||||||
operator a full re-run cycle.
|
operator a full re-run cycle.
|
||||||
- A test declares its `mode`, and the runner switches. Cloud tests stay in
|
- A test declares its `mode`, and the runner switches. Cloud tests stay in
|
||||||
cloud mode. Keep `requires` lists minimal, and never gate one test behind a
|
cloud mode. Keep `requires` lists minimal, and never gate one test behind a
|
||||||
chain of others.
|
chain of others.
|
||||||
- Never exercise a gate or a limit through the `GFCOOL_*` environment
|
- Never exercise a gate or a limit through the `GFCOOL_*` environment
|
||||||
overrides in a test. Use the settings API, and restore it in the teardown.
|
overrides in a test. Use the settings API, and restore it in the teardown.
|
||||||
|
|
||||||
### CI couplings that set the push order
|
### CI couplings that set the push order
|
||||||
|
|
||||||
- The CI of `grblHAL-glowforge` gets the laser harnesses from `scripts/bench/`
|
- The CI of `grblHAL-glowforge` gets the laser harnesses from `scripts/bench/`
|
||||||
at the head of `master`, unpinned. Push a harness change here before the
|
at the head of `master`, unpinned. Push a harness change here before the
|
||||||
driver change that needs it.
|
driver change that needs it.
|
||||||
- The acceptance page shares its theme and its vendored Bootstrap with the
|
- The acceptance page shares its theme and its vendored Bootstrap with the
|
||||||
`forgectrl` panel, byte for byte. Land a UI change in `forgectrl` first.
|
`forgectrl` panel, byte for byte. Land a UI change in `forgectrl` first.
|
||||||
Push it and pin it. Only then push this repository.
|
Push it and pin it. Only then push this repository.
|
||||||
- The CI of `kernel-module-glowforge` cross-builds against the BSP from
|
- The CI of `kernel-module-glowforge` cross-builds against the BSP from
|
||||||
`meta-openglow`. Push `meta-openglow` before a module change that needs a
|
`meta-openglow`. Push `meta-openglow` before a module change that needs a
|
||||||
BSP change.
|
BSP change.
|
||||||
|
|
||||||
### Builds and images
|
### Builds and images
|
||||||
|
|
||||||
- Builds run only in the dedicated Yocto build environment that the Build page
|
- Builds run only in the dedicated Yocto build environment that the Build page
|
||||||
of the site defines (kas and bitbake). Never use a native host build of a
|
of the site defines (kas and bitbake). Never use a native host build of a
|
||||||
component as proof, not even for a compile check.
|
component as proof, not even for a compile check.
|
||||||
- Every build makes both images: `forgefirm-image` (the release image) and
|
- Every build makes both images: `forgefirm-image` (the release image) and
|
||||||
`forgefirm-image-dev` (the bench image, with `forgetest` on port 8090). The
|
`forgefirm-image-dev` (the bench image, with `forgetest` on port 8090). The
|
||||||
dev image needs an explicit `--target`. Report both artifact names.
|
dev image needs an explicit `--target`. Report both artifact names.
|
||||||
- After a kernel-module pin bump, rebuild the kernel and the module in the
|
- After a kernel-module pin bump, rebuild the kernel and the module in the
|
||||||
same run: `bitbake -c cleansstate linux-fslc kernel-module-glowforge`, then
|
same run: `bitbake -c cleansstate linux-fslc kernel-module-glowforge`, then
|
||||||
the images. The kernel version suffix is not reproducible across
|
the images. The kernel version suffix is not reproducible across
|
||||||
re-checkouts, and a rootfs whose kernel and module disagree fails.
|
re-checkouts, and a rootfs whose kernel and module disagree fails.
|
||||||
- Read the layer HEAD lines at the top of a build log before you trust a build
|
- Read the layer HEAD lines at the top of a build log before you trust a build
|
||||||
that moves a pin.
|
that moves a pin.
|
||||||
|
|
||||||
### The record of the work
|
### The record of the work
|
||||||
|
|
||||||
This repository carries no status document and no dated log. Both were
|
This repository carries no status document and no dated log. Both were
|
||||||
retired: every fact about the machine and the firmware is on the
|
retired: every fact about the machine and the firmware is on the
|
||||||
documentation site, and **the record of a piece of work is the commit message
|
documentation site, and **the record of a piece of work is the commit message
|
||||||
that carries it**: what was done, how it was proven, and what it replaced, in
|
that carries it**: what was done, how it was proven, and what it replaced, in
|
||||||
the same place as the change itself.
|
the same place as the change itself.
|
||||||
|
|
||||||
A measurement session or a bench drill is written up in the commit that
|
A measurement session or a bench drill is written up in the commit that
|
||||||
lands its result. Nothing accumulates in a file.
|
lands its result. Nothing accumulates in a file.
|
||||||
|
|
||||||
### On the bench
|
### On the bench
|
||||||
|
|
||||||
These rules apply whenever an agent works with the operator at a machine.
|
These rules apply whenever an agent works with the operator at a machine.
|
||||||
|
|
||||||
- **One armed run per turn.** Start the run, let it finish, stop, report what
|
- **One armed run per turn.** Start the run, let it finish, stop, report what
|
||||||
happened against what was expected, and wait for the operator's
|
happened against what was expected, and wait for the operator's
|
||||||
confirmation before any further armed run or machine command. Never chain a
|
confirmation before any further armed run or machine command. Never chain a
|
||||||
jog, a fix, or a re-run onto a burn in the same step. Dry runs (latch
|
jog, a fix, or a re-run onto a burn in the same step. Dry runs (latch
|
||||||
locked, no emission) can be batched. Say which is which before you start.
|
locked, no emission) can be batched. Say which is which before you start.
|
||||||
- **Zero inference during live fire.** Report only what the combined
|
- **Zero inference during live fire.** Report only what the combined
|
||||||
observations confirm: the operator's eyes, the drill output, the logs, the
|
observations confirm: the operator's eyes, the drill output, the logs, the
|
||||||
sysfs readbacks. Everything else is labeled "unconfirmed" and is not acted
|
sysfs readbacks. Everything else is labeled "unconfirmed" and is not acted
|
||||||
on.
|
on.
|
||||||
- **One Grbl connection.** Never open a second connection to TCP port 23 while
|
- **One Grbl connection.** Never open a second connection to TCP port 23 while
|
||||||
a drill, an acceptance test, or a sender holds one. The last connection
|
a drill, an acceptance test, or a sender holds one. The last connection
|
||||||
wins, the displaced client's cleanup never arrives, and its queued commands
|
wins, the displaced client's cleanup never arrives, and its queued commands
|
||||||
wait behind the arm gate. Read state through `forgectrl` (HTTP) and sysfs
|
wait behind the arm gate. Read state through `forgectrl` (HTTP) and sysfs
|
||||||
only. After a displaced or aborted drill: soft reset, confirm that the RX
|
only. After a displaced or aborted drill: soft reset, confirm that the RX
|
||||||
buffer reads full, `M5`, confirm that `armed` is false, before anyone
|
buffer reads full, `M5`, confirm that `armed` is false, before anyone
|
||||||
touches the button.
|
touches the button.
|
||||||
- **The operator touches the machine.** The operator runs the install, the
|
- **The operator touches the machine.** The operator runs the install, the
|
||||||
service restart, and the reflash on the machine. Never modify the software
|
service restart, and the reflash on the machine. Never modify the software
|
||||||
of a running machine unless the operator asks for that exact step.
|
of a running machine unless the operator asks for that exact step.
|
||||||
- **Bench hygiene.** Stage test files in `/tmp`. A file that must survive a
|
- **Bench hygiene.** Stage test files in `/tmp`. A file that must survive a
|
||||||
reboot goes in `/data/bench-scratch/`, and that directory is deleted whole
|
reboot goes in `/data/bench-scratch/`, and that directory is deleted whole
|
||||||
at the end of the session. Nothing goes loose in `/data`. Remove everything
|
at the end of the session. Nothing goes loose in `/data`. Remove everything
|
||||||
you put on the board, in the same session, and list `/data` before you end.
|
you put on the board, in the same session, and list `/data` before you end.
|
||||||
A bench tool worth a second use goes in `scripts/bench/`. The dev image
|
A bench tool worth a second use goes in `scripts/bench/`. The dev image
|
||||||
installs those tools under `/usr/share/forgetest/bench/`. Run them from
|
installs those tools under `/usr/share/forgetest/bench/`. Run them from
|
||||||
there.
|
there.
|
||||||
|
|
||||||
## Project-wide rules
|
## Project-wide rules
|
||||||
|
|
||||||
The sections above are specific to this repository. The rules below apply to
|
The sections above are specific to this repository. The rules below apply to
|
||||||
every repository of the OpenGlow ForgeFIRM project: the firmware components,
|
every repository of the OpenGlow ForgeFIRM project: the firmware components,
|
||||||
the build base, the documentation, and the hardware designs. Where a
|
the build base, the documentation, and the hardware designs. Where a
|
||||||
repository rule and a rule below conflict, the safety, proof, and hygiene
|
repository rule and a rule below conflict, the safety, proof, and hygiene
|
||||||
rules below win. The documentation site, <https://docs.forgefirm.org/>, is
|
rules below win. The documentation site, <https://docs.forgefirm.org/>, is
|
||||||
the source of truth for every fact about the machine and the firmware. Read
|
the source of truth for every fact about the machine and the firmware. Read
|
||||||
its Developers section before you change code.
|
its Developers section before you change code.
|
||||||
|
|
||||||
### What ForgeFIRM is
|
### What ForgeFIRM is
|
||||||
|
|
||||||
ForgeFIRM is open firmware for stock Glowforge lasers (Basic, Plus, Pro). It
|
ForgeFIRM is open firmware for stock Glowforge lasers (Basic, Plus, Pro). It
|
||||||
runs on the factory NXP i.MX6 control board with no hardware modification. It
|
runs on the factory NXP i.MX6 control board with no hardware modification. It
|
||||||
replaces the cloud-dependent factory userspace with an open Linux image that
|
replaces the cloud-dependent factory userspace with an open Linux image that
|
||||||
controls the machine locally. In GRBL mode the machine is a standard grblHAL
|
controls the machine locally. In GRBL mode the machine is a standard grblHAL
|
||||||
controller for LightBurn and other senders on TCP port 23. Cloud mode runs the
|
controller for LightBurn and other senders on TCP port 23. Cloud mode runs the
|
||||||
factory experience through the Glowforge web service, and it is a deliberate,
|
factory experience through the Glowforge web service, and it is a deliberate,
|
||||||
maintained feature. The stack is hardware validated: GRBL mode cuts real jobs,
|
maintained feature. The stack is hardware validated: GRBL mode cuts real jobs,
|
||||||
and cloud mode runs end to end.
|
and cloud mode runs end to end.
|
||||||
|
|
||||||
One controller runs at a time under `forgectrl`, the machine-services daemon,
|
One controller runs at a time under `forgectrl`, the machine-services daemon,
|
||||||
which owns the pulse device, the cooling engine, the cameras, and the control
|
which owns the pulse device, the cooling engine, the cameras, and the control
|
||||||
panel. The kernel module plays the pulse stream into the stepper drivers and
|
panel. The kernel module plays the pulse stream into the stepper drivers and
|
||||||
owns the laser latch and the safety readbacks. The Technical section of the
|
owns the laser latch and the safety readbacks. The Technical section of the
|
||||||
site describes the whole stack.
|
site describes the whole stack.
|
||||||
|
|
||||||
### The repositories
|
### The repositories
|
||||||
|
|
||||||
All repositories live under the OpenGlow organization on GitHub,
|
All repositories live under the OpenGlow organization on GitHub,
|
||||||
<https://github.com/openglow-org>. For development, check every repository out
|
<https://github.com/openglow-org>. For development, check every repository out
|
||||||
as a sibling in one base directory named `openglow-forgefirm`. The build
|
as a sibling in one base directory named `openglow-forgefirm`. The build
|
||||||
scripts expect that layout. Each repository is its own git repository. The
|
scripts expect that layout. Each repository is its own git repository. The
|
||||||
base directory is not.
|
base directory is not.
|
||||||
|
|
||||||
| Repository | Role | Default branch | License |
|
| Repository | Role | Default branch | License |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `forgefirm` | The build and release base: the `meta-forgefirm` Yocto layer, the kas configuration, the image recipes, the install and release scripts, the acceptance tool `forgetest/`, the bench tools `scripts/bench/`, and the bench actuator firmware `fixture/`. It carries no project documentation. | `master` | MIT (layer metadata) |
|
| `forgefirm` | The build and release base: the `meta-forgefirm` Yocto layer, the kas configuration, the image recipes, the install and release scripts, the acceptance tool `forgetest/`, the bench tools `scripts/bench/`, and the bench actuator firmware `fixture/`. It carries no project documentation. | `master` | MIT (layer metadata) |
|
||||||
| `meta-openglow` | The BSP layers `meta-glowforge-bsp` and `meta-openglow-core`: kernel, device tree, U-Boot, board recipes. | `scarthgap` | MIT (layer metadata) |
|
| `meta-openglow` | The BSP layers `meta-glowforge-bsp` and `meta-openglow-core`: kernel, device tree, U-Boot, board recipes. | `scarthgap` | MIT (layer metadata) |
|
||||||
| `forgectrl` | The machine-services daemon (C) on HTTPS port 443, with the read-only routes on HTTP port 80: supervisor, pulse-device broker, motion-liveness gate, cooling engine, cameras, telemetry, settings, diagnostics, control panel, A/B updates. | `main` | MIT |
|
| `forgectrl` | The machine-services daemon (C) on HTTPS port 443, with the read-only routes on HTTP port 80: supervisor, pulse-device broker, motion-liveness gate, cooling engine, cameras, telemetry, settings, diagnostics, control panel, A/B updates. | `main` | MIT |
|
||||||
| `grblHAL-glowforge` | The grblHAL driver for the stock board, the GRBL-mode controller. The core is a submodule at `src/grbl`. Machine constants are in `src/boards/glowforge.h`. | `main` | GPL-3.0-or-later |
|
| `grblHAL-glowforge` | The grblHAL driver for the stock board, the GRBL-mode controller. The core is a submodule at `src/grbl`. Machine constants are in `src/boards/glowforge.h`. | `main` | GPL-3.0-or-later |
|
||||||
| `grblHAL-core` | The fork of the grblHAL core that the driver uses. Minimum change, no rationale comments. | `forgefirm` | The upstream grblHAL license |
|
| `grblHAL-core` | The fork of the grblHAL core that the driver uses. Minimum change, no rationale comments. | `forgefirm` | The upstream grblHAL license |
|
||||||
| `kernel-module-glowforge` | `glowforge.ko`: the SDMA + EPIT pulse engine, the laser latch, the safety readbacks, the sensors. | `master` | GPL-2.0-or-later |
|
| `kernel-module-glowforge` | `glowforge.ko`: the SDMA + EPIT pulse engine, the laser latch, the safety readbacks, the sensors. | `master` | GPL-2.0-or-later |
|
||||||
| `python3-gfhardware` | The `gfhardware` hardware library and the cloud-mode applications in `forgefirm-app/`. | `master` | MIT, with one LGPL-2.1-or-later component |
|
| `python3-gfhardware` | The `gfhardware` hardware library and the cloud-mode applications in `forgefirm-app/`. | `master` | MIT, with one LGPL-2.1-or-later component |
|
||||||
| `Glowforge-Utilities` | `gfutilities` on PyPI: the factory protocol and service layer that cloud mode uses. | `master` | MIT |
|
| `Glowforge-Utilities` | `gfutilities` on PyPI: the factory protocol and service layer that cloud mode uses. | `master` | MIT |
|
||||||
| `forgefirm-docs` | The documentation site. | `main` | CC BY-SA 4.0 |
|
| `forgefirm-docs` | The documentation site. | `main` | CC BY-SA 4.0 |
|
||||||
| `openglow-serial-adapter` | The USB-C serial-console adapter for the control board. | `main` | CC BY-NC-SA 4.0 |
|
| `openglow-serial-adapter` | The USB-C serial-console adapter for the control board. | `main` | CC BY-NC-SA 4.0 |
|
||||||
|
|
||||||
The full table, the license details, and the component diagram are on the
|
The full table, the license details, and the component diagram are on the
|
||||||
site: <https://docs.forgefirm.org/developers/>.
|
site: <https://docs.forgefirm.org/developers/>.
|
||||||
|
|
||||||
### Safety first, and in that order
|
### Safety first, and in that order
|
||||||
|
|
||||||
The machine is a laser, and the operator is the safety authority at it. These
|
The machine is a laser, and the operator is the safety authority at it. These
|
||||||
rules bind every change, in every repository, that can affect what the machine
|
rules bind every change, in every repository, that can affect what the machine
|
||||||
does.
|
does.
|
||||||
|
|
||||||
- The hardware chain is the safety boundary. Software only adds gates on top
|
- The hardware chain is the safety boundary. Software only adds gates on top
|
||||||
of it. `LASER_ON` is never a bare GPIO. The kernel laser latch is locked by
|
of it. `LASER_ON` is never a bare GPIO. The kernel laser latch is locked by
|
||||||
default, and every close of the pulse device locks it again.
|
default, and every close of the pulse device locks it again.
|
||||||
- Never defeat a switch, an interlock, or a readback, in hardware or in
|
- Never defeat a switch, an interlock, or a readback, in hardware or in
|
||||||
software, not even for a test.
|
software, not even for a test.
|
||||||
- Never change a fire gate, a thermal limit, or a safety default to make a
|
- Never change a fire gate, a thermal limit, or a safety default to make a
|
||||||
test pass.
|
test pass.
|
||||||
- The order of work is absolute: emission and motion first, robustness and
|
- The order of work is absolute: emission and motion first, robustness and
|
||||||
hygiene after. Review a change that touches emission or motion for that
|
hygiene after. Review a change that touches emission or motion for that
|
||||||
before anything else.
|
before anything else.
|
||||||
- A change that can put energy where it was not commanded gets a regression
|
- A change that can put energy where it was not commanded gets a regression
|
||||||
test with the fix, in the same commit, never after.
|
test with the fix, in the same commit, never after.
|
||||||
- Position counters, homing anchors, and a homed flag are not proof of
|
- Position counters, homing anchors, and a homed flag are not proof of
|
||||||
physical motion. The head accelerometer is, and so are the operator's eyes.
|
physical motion. The head accelerometer is, and so are the operator's eyes.
|
||||||
|
|
||||||
### Proof before done
|
### Proof before done
|
||||||
|
|
||||||
A feature or fix is not complete until it is proven. The order of preference:
|
A feature or fix is not complete until it is proven. The order of preference:
|
||||||
|
|
||||||
1. A host test that runs in CI. The Test page of the site lists the host tests
|
1. A host test that runs in CI. The Test page of the site lists the host tests
|
||||||
of each repository.
|
of each repository.
|
||||||
2. A bench drill on the bench reference, recorded in the commit message that
|
2. A bench drill on the bench reference, recorded in the commit message that
|
||||||
carries the change.
|
carries the change.
|
||||||
3. Documented reasoning.
|
3. Documented reasoning.
|
||||||
|
|
||||||
Also:
|
Also:
|
||||||
|
|
||||||
- Run the host tests of this repository before every commit. Where the build
|
- Run the host tests of this repository before every commit. Where the build
|
||||||
uses `-Werror`, a warning is a failure.
|
uses `-Werror`, a warning is a failure.
|
||||||
- A component that ships in the image is also evaluated against the release
|
- A component that ships in the image is also evaluated against the release
|
||||||
acceptance catalog in the `forgefirm` repository (Test page, "Coverage
|
acceptance catalog in the `forgefirm` repository (Test page, "Coverage
|
||||||
currency"). A behavior change with no catalog consequence gets a sentence
|
currency"). A behavior change with no catalog consequence gets a sentence
|
||||||
of justification in the commit message.
|
of justification in the commit message.
|
||||||
- For a component that ships in the image, the proof build is the Yocto
|
- For a component that ships in the image, the proof build is the Yocto
|
||||||
cross-build that the Build page of the site defines, never a native host
|
cross-build that the Build page of the site defines, never a native host
|
||||||
build.
|
build.
|
||||||
- Report outcomes faithfully. Quote failing output as it is. Name a skipped
|
- Report outcomes faithfully. Quote failing output as it is. Name a skipped
|
||||||
step as skipped. Never narrate an expected result as an observed one.
|
step as skipped. Never narrate an expected result as an observed one.
|
||||||
|
|
||||||
### The workflow: prove locally, push when proven
|
### The workflow: prove locally, push when proven
|
||||||
|
|
||||||
- Nothing goes to a public repository until it is proven: in the host tests
|
- Nothing goes to a public repository until it is proven: in the host tests
|
||||||
for host-only changes, on the bench for changes that alter what the machine
|
for host-only changes, on the bench for changes that alter what the machine
|
||||||
does.
|
does.
|
||||||
- Iterate locally. Then make one commit and one push for the proven change.
|
- Iterate locally. Then make one commit and one push for the proven change.
|
||||||
No chains of fix-up pushes. Every push runs CI, and CI minutes are a budget.
|
No chains of fix-up pushes. Every push runs CI, and CI minutes are a budget.
|
||||||
- Commit only finished work, and only when asked. Never commit intermediate
|
- Commit only finished work, and only when asked. Never commit intermediate
|
||||||
findings, working notes, plans, audits, or status files. If a conclusion is
|
findings, working notes, plans, audits, or status files. If a conclusion is
|
||||||
still moving, it is not ready for a repository. Unpushed mistakes come out
|
still moving, it is not ready for a repository. Unpushed mistakes come out
|
||||||
with `git reset --mixed <base>`, which keeps the working tree.
|
with `git reset --mixed <base>`, which keeps the working tree.
|
||||||
- "Commit" and "commit and build" include the push of every touched
|
- "Commit" and "commit and build" include the push of every touched
|
||||||
repository, in dependency order. Never hold a push back to protect earlier
|
repository, in dependency order. Never hold a push back to protect earlier
|
||||||
unpushed commits on the same branch. The only exception is an explicit "do
|
unpushed commits on the same branch. The only exception is an explicit "do
|
||||||
not push" for that session.
|
not push" for that session.
|
||||||
- Never push, force-push, tag, cut a release, refresh a lockfile, bump a
|
- Never push, force-push, tag, cut a release, refresh a lockfile, bump a
|
||||||
submodule pointer, or bump a pin unless asked.
|
submodule pointer, or bump a pin unless asked.
|
||||||
|
|
||||||
### Pins
|
### Pins
|
||||||
|
|
||||||
A firmware component reaches the image only through its pin: an exact
|
A firmware component reaches the image only through its pin: an exact
|
||||||
`SRCREV` in `meta-forgefirm` (in the `forgefirm` repository) for ForgeFIRM
|
`SRCREV` in `meta-forgefirm` (in the `forgefirm` repository) for ForgeFIRM
|
||||||
components, or in `meta-openglow` for BSP components. There is no `AUTOREV`.
|
components, or in `meta-openglow` for BSP components. There is no `AUTOREV`.
|
||||||
A commit in a component repository changes nothing on a machine until its pin
|
A commit in a component repository changes nothing on a machine until its pin
|
||||||
moves. The order is always: push the source repository, bump its pin, then
|
moves. The order is always: push the source repository, bump its pin, then
|
||||||
run `bitbake -c fetch <recipe>` to make sure that the pin resolves. Some
|
run `bitbake -c fetch <recipe>` to make sure that the pin resolves. Some
|
||||||
pairs of repositories have a CI coupling that fixes the push order between
|
pairs of repositories have a CI coupling that fixes the push order between
|
||||||
them. The Release flow page of the site lists them, and each affected
|
them. The Release flow page of the site lists them, and each affected
|
||||||
repository names its own in the section above.
|
repository names its own in the section above.
|
||||||
|
|
||||||
### Git conventions
|
### Git conventions
|
||||||
|
|
||||||
- A commit is attributed to the human who is responsible for it, in both the
|
- A commit is attributed to the human who is responsible for it, in both the
|
||||||
author and the committer fields. Never list an AI assistant as an author or
|
author and the committer fields. Never list an AI assistant as an author or
|
||||||
a co-author. Never add an AI attribution trailer or a "Generated with" line
|
a co-author. Never add an AI attribution trailer or a "Generated with" line
|
||||||
to a commit message or a pull request. In a fresh clone, set the local
|
to a commit message or a pull request. In a fresh clone, set the local
|
||||||
`user.name` and `user.email` before the first commit.
|
`user.name` and `user.email` before the first commit.
|
||||||
- A commit message says what changed and why, in the present tense, in
|
- A commit message says what changed and why, in the present tense, in
|
||||||
Simplified Technical English. The "why" of a change to fork code lives here
|
Simplified Technical English. The "why" of a change to fork code lives here
|
||||||
and nowhere else.
|
and nowhere else.
|
||||||
- Keep line endings LF in every file that Linux tooling consumes: patches,
|
- Keep line endings LF in every file that Linux tooling consumes: patches,
|
||||||
shell scripts, recipes, device trees. Check the bytes after an edit from a
|
shell scripts, recipes, device trees. Check the bytes after an edit from a
|
||||||
Windows tool. A CRLF patch breaks `do_patch`.
|
Windows tool. A CRLF patch breaks `do_patch`.
|
||||||
- Never commit build output, `__pycache__`, virtual environments, editor
|
- Never commit build output, `__pycache__`, virtual environments, editor
|
||||||
files, a local knowledge graph (`graphify-out/`), captured machine data that
|
files, a local knowledge graph (`graphify-out/`), captured machine data that
|
||||||
carries an identity, tokens, keys, or passwords.
|
carries an identity, tokens, keys, or passwords.
|
||||||
- Never rewrite published history unless the operator asks for it.
|
- Never rewrite published history unless the operator asks for it.
|
||||||
- A pull request to an upstream repository is never automatic. The developer
|
- A pull request to an upstream repository is never automatic. The developer
|
||||||
decides if and when to send one. You can remind them that upstream
|
decides if and when to send one. You can remind them that upstream
|
||||||
candidates exist, but the decision is theirs.
|
candidates exist, but the decision is theirs.
|
||||||
|
|
||||||
### Writing rules
|
### Writing rules
|
||||||
|
|
||||||
They apply to everything: documentation, README files, code comments,
|
They apply to everything: documentation, README files, code comments,
|
||||||
docstrings, log and console text, commit messages, issue text, and replies.
|
docstrings, log and console text, commit messages, issue text, and replies.
|
||||||
|
|
||||||
- **American English.** analyze, behavior, color, center, gray, catalog,
|
- **American English.** analyze, behavior, color, center, gray, catalog,
|
||||||
license, judgment, program, artifact, percent, toward, among, while,
|
license, judgment, program, artifact, percent, toward, among, while,
|
||||||
learned. The style lint in `forgefirm-docs` rejects the British forms.
|
learned. The style lint in `forgefirm-docs` rejects the British forms.
|
||||||
- **ASD-STE100 Simplified Technical English.** Short sentences: 20 words in
|
- **ASD-STE100 Simplified Technical English.** Short sentences: 20 words in
|
||||||
a procedure, 25 in a description. One topic per sentence, one instruction
|
a procedure, 25 in a description. One topic per sentence, one instruction
|
||||||
per sentence. Active voice, imperative in procedures, simple present in
|
per sentence. Active voice, imperative in procedures, simple present in
|
||||||
descriptions. "Must" for necessity, "can" for possibility. No "should",
|
descriptions. "Must" for necessity, "can" for possibility. No "should",
|
||||||
"would", "could", "may". Prefer: do, make sure, use, start, show, occur,
|
"would", "could", "may". Prefer: do, make sure, use, start, show, occur,
|
||||||
before, after, because, for example, that is. No "etc.", no "and/or".
|
before, after, because, for example, that is. No "etc.", no "and/or".
|
||||||
Noun clusters of three words at most. Warnings and cautions come before the
|
Noun clusters of three words at most. Warnings and cautions come before the
|
||||||
step they protect. Warm and direct is good. A joke that shades a fact is
|
step they protect. Warm and direct is good. A joke that shades a fact is
|
||||||
not.
|
not.
|
||||||
- **No em dashes.** Never, anywhere. Use a colon, a period, or a comma.
|
- **No em dashes.** Never, anywhere. Use a colon, a period, or a comma.
|
||||||
- **Present tense, present state.** Text describes the code and the machine
|
- **Present tense, present state.** Text describes the code and the machine
|
||||||
as they are. No history narrative, no "the old version did", no "evolved
|
as they are. No history narrative, no "the old version did", no "evolved
|
||||||
from", no story of how the code got here. Upstream copyright and
|
from", no story of how the code got here. Upstream copyright and
|
||||||
derivation attribution to public projects stays: that is license credit,
|
derivation attribution to public projects stays: that is license credit,
|
||||||
not narrative.
|
not narrative.
|
||||||
- **No workstation paths.** Nothing outside a repository appears as a path in
|
- **No workstation paths.** Nothing outside a repository appears as a path in
|
||||||
it: no drive letters, no WSL mounts, no home directories, no sibling-repo
|
it: no drive letters, no WSL mounts, no home directories, no sibling-repo
|
||||||
relative paths, no private reference directories. Name the artifact
|
relative paths, no private reference directories. Name the artifact
|
||||||
instead: "the captured factory pulse files", "that bench session".
|
instead: "the captured factory pulse files", "that bench session".
|
||||||
- **No bench-machine identity.** Never a hostname, a serial number, a fuse
|
- **No bench-machine identity.** Never a hostname, a serial number, a fuse
|
||||||
value, a private IP address, or a login of the bench machine, in any file,
|
value, a private IP address, or a login of the bench machine, in any file,
|
||||||
comment, commit message, sample, or test fixture. Use neutral placeholders
|
comment, commit message, sample, or test fixture. Use neutral placeholders
|
||||||
of the `ABC-123` form. Record the fact of a verification, never the values.
|
of the `ABC-123` form. Record the fact of a verification, never the values.
|
||||||
- **No factory firmware code.** Never cite the factory firmware binary or its
|
- **No factory firmware code.** Never cite the factory firmware binary or its
|
||||||
code: no offsets, no addresses, no quoted or decompiled code. State the
|
code: no offsets, no addresses, no quoted or decompiled code. State the
|
||||||
recovered fact (a formula, a constant, a behavior) and stop. Hardware
|
recovered fact (a formula, a constant, a behavior) and stop. Hardware
|
||||||
addresses (IOMUX pad values, sensor registers, boot offsets) are fine.
|
addresses (IOMUX pad values, sensor registers, boot offsets) are fine.
|
||||||
- **No rationale comments in fork code.** Code destined upstream (for
|
- **No rationale comments in fork code.** Code destined upstream (for
|
||||||
example, the grblHAL core fork) carries the minimum change and no "why we
|
example, the grblHAL core fork) carries the minimum change and no "why we
|
||||||
did this" comments. The reasoning goes in the commit message. Patches
|
did this" comments. The reasoning goes in the commit message. Patches
|
||||||
carried in the Yocto layers are exempt. The `ForgeFIRM:` comment convention
|
carried in the Yocto layers are exempt. The `ForgeFIRM:` comment convention
|
||||||
there is deliberate.
|
there is deliberate.
|
||||||
- **Interface docs describe the lever, not the policy.** A sysfs attribute
|
- **Interface docs describe the lever, not the policy.** A sysfs attribute
|
||||||
doc says what the attribute is, its range, its units, its conversion. How
|
doc says what the attribute is, its range, its units, its conversion. How
|
||||||
the factory firmware drives it does not belong there.
|
the factory firmware drives it does not belong there.
|
||||||
- **No definitive legal or regulatory statements.** The project is not a
|
- **No definitive legal or regulatory statements.** The project is not a
|
||||||
lawyer. The only permitted form: modifying the machine, including
|
lawyer. The only permitted form: modifying the machine, including
|
||||||
replacing its firmware, may have legal and regulatory ramifications, and it
|
replacing its firmware, may have legal and regulatory ramifications, and it
|
||||||
is the end user's responsibility to adhere to the laws, regulations,
|
is the end user's responsibility to adhere to the laws, regulations,
|
||||||
certifications, and insurance terms that apply where they are. Warranty
|
certifications, and insurance terms that apply where they are. Warranty
|
||||||
wording is "may void your warranty", never "voids". Never cite a regulation,
|
wording is "may void your warranty", never "voids". Never cite a regulation,
|
||||||
a standard, or a certification regime as applying or not applying. The
|
a standard, or a certification regime as applying or not applying. The
|
||||||
affiliation disclaimer lives in the site footer only. It is also the user's
|
affiliation disclaimer lives in the site footer only. It is also the user's
|
||||||
responsibility to make sure that they stay within the vendor's terms of
|
responsibility to make sure that they stay within the vendor's terms of
|
||||||
service when they use a feature that calls that vendor's cloud services.
|
service when they use a feature that calls that vendor's cloud services.
|
||||||
- **Copyright.** Copyright in this project belongs to 514 LLC d/b/a
|
- **Copyright.** Copyright in this project belongs to 514 LLC d/b/a
|
||||||
OpenGlow. Every new source file carries two lines in its header, in the
|
OpenGlow. Every new source file carries two lines in its header, in the
|
||||||
comment style of the file: `Copyright <year> 514 LLC d/b/a OpenGlow` and
|
comment style of the file: `Copyright <year> 514 LLC d/b/a OpenGlow` and
|
||||||
`Written by Scott Wiederhold`. Keep the year, or the year range, that
|
`Written by Scott Wiederhold`. Keep the year, or the year range, that
|
||||||
the file already has. The copyright notices of other holders stay
|
the file already has. The copyright notices of other holders stay
|
||||||
unchanged.
|
unchanged.
|
||||||
- **SPDX.** Every new source file carries an `SPDX-License-Identifier` line
|
- **SPDX.** Every new source file carries an `SPDX-License-Identifier` line
|
||||||
under the license of its repository.
|
under the license of its repository.
|
||||||
|
|
||||||
### Where documentation goes
|
### Where documentation goes
|
||||||
|
|
||||||
- **One home.** A fact lives on the documentation site, or it does not exist.
|
- **One home.** A fact lives on the documentation site, or it does not exist.
|
||||||
A repository README says what the repository is, how to build and test it,
|
A repository README says what the repository is, how to build and test it,
|
||||||
and where the documentation is. Nothing else.
|
and where the documentation is. Nothing else.
|
||||||
- **The currency rule.** A change carries a documentation commit when it adds,
|
- **The currency rule.** A change carries a documentation commit when it adds,
|
||||||
removes, or renames an interface (a sysfs attribute, an HTTP route, a
|
removes, or renames an interface (a sysfs attribute, an HTTP route, a
|
||||||
settings key, a G-code or `$` setting), or when it corrects a measured
|
settings key, a G-code or `$` setting), or when it corrects a measured
|
||||||
fact. A measured fact says how it was obtained, and on what: unless the page
|
fact. A measured fact says how it was obtained, and on what: unless the page
|
||||||
says otherwise, a measurement on the site was taken on the bench reference,
|
says otherwise, a measurement on the site was taken on the bench reference,
|
||||||
which the site defines.
|
which the site defines.
|
||||||
- **A moved document is deleted.** No stub and no redirect stays at the old
|
- **A moved document is deleted.** No stub and no redirect stays at the old
|
||||||
path.
|
path.
|
||||||
- **Every diagram is Mermaid.** No ASCII art and no image of a diagram.
|
- **Every diagram is Mermaid.** No ASCII art and no image of a diagram.
|
||||||
- There is no roadmap page. Open items are tracked as GitHub issues once the
|
- There is no roadmap page. Open items are tracked as GitHub issues once the
|
||||||
repositories accept them.
|
repositories accept them.
|
||||||
- Do not add plan files, audit files, working notes, or status files to any
|
- Do not add plan files, audit files, working notes, or status files to any
|
||||||
repository. The project has **no status document and no dated log**: the
|
repository. The project has **no status document and no dated log**: the
|
||||||
site describes the present, and the record of what was done, how it was
|
site describes the present, and the record of what was done, how it was
|
||||||
proven, and what it replaced goes in the commit message that carries the
|
proven, and what it replaced goes in the commit message that carries the
|
||||||
change.
|
change.
|
||||||
|
|
||||||
### Analysis and reporting
|
### Analysis and reporting
|
||||||
|
|
||||||
- Rank engineering options on technical merit only: performance, correctness,
|
- Rank engineering options on technical merit only: performance, correctness,
|
||||||
robustness, verifiability. Process cost (an acceptance campaign, an image
|
robustness, verifiability. Process cost (an acceptance campaign, an image
|
||||||
flash, a new dependency) is a one-line footnote, never a ranking factor.
|
flash, a new dependency) is a one-line footnote, never a ranking factor.
|
||||||
The operator decides the process cost.
|
The operator decides the process cost.
|
||||||
- Never infer or assume a hardware fact. Label every unverified claim as
|
- Never infer or assume a hardware fact. Label every unverified claim as
|
||||||
unverified, and say how to verify it.
|
unverified, and say how to verify it.
|
||||||
- Report only what the observations confirm. Everything else is labeled
|
- Report only what the observations confirm. Everything else is labeled
|
||||||
"unconfirmed" and is not acted on.
|
"unconfirmed" and is not acted on.
|
||||||
|
|
||||||
### General practice for agents
|
### General practice for agents
|
||||||
|
|
||||||
- Read the README of this repository, this file, and the Developers section
|
- Read the README of this repository, this file, and the Developers section
|
||||||
of the site before you change code.
|
of the site before you change code.
|
||||||
- Orient in the code before you edit. If a local knowledge graph
|
- Orient in the code before you edit. If a local knowledge graph
|
||||||
(`graphify-out/`) exists in the working tree or its parent, query it first.
|
(`graphify-out/`) exists in the working tree or its parent, query it first.
|
||||||
It is a local artifact and is never committed.
|
It is a local artifact and is never committed.
|
||||||
- Keep a change minimal and scoped to the request. No drive-by reformatting,
|
- Keep a change minimal and scoped to the request. No drive-by reformatting,
|
||||||
no unrelated cleanups, no renames for taste. Match the style of the
|
no unrelated cleanups, no renames for taste. Match the style of the
|
||||||
surrounding code.
|
surrounding code.
|
||||||
- Do not add a dependency without a stated reason. The target is a
|
- Do not add a dependency without a stated reason. The target is a
|
||||||
single-core machine with a small eMMC, and every package rides the image.
|
single-core machine with a small eMMC, and every package rides the image.
|
||||||
- Extend an existing test or tool instead of adding a parallel one.
|
- Extend an existing test or tool instead of adding a parallel one.
|
||||||
- Never create a file in the repository that the request does not need.
|
- Never create a file in the repository that the request does not need.
|
||||||
- Ask before anything destructive or outward-facing: a push, a force-push, a
|
- Ask before anything destructive or outward-facing: a push, a force-push, a
|
||||||
tag, a release, a history rewrite, or any change to a machine.
|
tag, a release, a history rewrite, or any change to a machine.
|
||||||
- When a fact is unknown, say so and say how to find out. Never fill a gap
|
- When a fact is unknown, say so and say how to find out. Never fill a gap
|
||||||
with a plausible number.
|
with a plausible number.
|
||||||
- Use the exact names of the project: kas, bitbake, pin, SRCREV, campaign,
|
- Use the exact names of the project: kas, bitbake, pin, SRCREV, campaign,
|
||||||
fingerprint, drill, sysfs, the latch, the armed window. Do not invent names.
|
fingerprint, drill, sysfs, the latch, the armed window. Do not invent names.
|
||||||
|
|
||||||
### Before you commit
|
### Before you commit
|
||||||
|
|
||||||
1. The host tests of this repository pass, with `-Werror` where the build
|
1. The host tests of this repository pass, with `-Werror` where the build
|
||||||
uses it.
|
uses it.
|
||||||
2. The change is proven at the highest level available: CI test, bench drill,
|
2. The change is proven at the highest level available: CI test, bench drill,
|
||||||
or documented reasoning.
|
or documented reasoning.
|
||||||
3. For a component that ships in the image: the acceptance catalog covers the
|
3. For a component that ships in the image: the acceptance catalog covers the
|
||||||
changed behavior, or the commit message says why it has no catalog
|
changed behavior, or the commit message says why it has no catalog
|
||||||
consequence.
|
consequence.
|
||||||
4. New files carry the 514 LLC d/b/a OpenGlow copyright, the `Written by`
|
4. New files carry the 514 LLC d/b/a OpenGlow copyright, the `Written by`
|
||||||
line, and an SPDX line. Line endings are LF.
|
line, and an SPDX line. Line endings are LF.
|
||||||
5. No em dashes, no British spellings, no workstation paths, no bench
|
5. No em dashes, no British spellings, no workstation paths, no bench
|
||||||
identity, no factory firmware code, no history narrative, no AI
|
identity, no factory firmware code, no history narrative, no AI
|
||||||
attribution.
|
attribution.
|
||||||
6. Documentation is current: interfaces and measured facts (the currency
|
6. Documentation is current: interfaces and measured facts (the currency
|
||||||
rule).
|
rule).
|
||||||
7. The commit is one settled change, attributed to the human author, and it
|
7. The commit is one settled change, attributed to the human author, and it
|
||||||
is pushed only when the operator asks.
|
is pushed only when the operator asks.
|
||||||
|
|||||||
+677
-677
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user