Close evidence phase and prepare external M1 build
This commit is contained in:
parent
11426e7969
commit
862d5a3cca
17 changed files with 167 additions and 126 deletions
1
.build/.gitkeep
Normal file
1
.build/.gitkeep
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -3,7 +3,8 @@ __pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.venv/
|
.venv/
|
||||||
.uv-cache/
|
.uv-cache/
|
||||||
/.build/
|
/.build/*
|
||||||
|
!/.build/.gitkeep
|
||||||
|
|
||||||
# Sensitive/raw acquisition data belongs in ThePirateRay-PrivateStash.
|
# Sensitive/raw acquisition data belongs in ThePirateRay-PrivateStash.
|
||||||
/raw/
|
/raw/
|
||||||
|
|
|
||||||
24
README.md
24
README.md
|
|
@ -7,7 +7,7 @@
|
||||||
The Pirate Ray is Makerspace Næstved's clean-room effort to build an
|
The Pirate Ray is Makerspace Næstved's clean-room effort to build an
|
||||||
open-source, safe desktop workflow for its laser equipment. The first target
|
open-source, safe desktop workflow for its laser equipment. The first target
|
||||||
is the **JPT 100 W E2/M7 MOPA fiber laser** with a JCZ/EZCAD2-compatible
|
is the **JPT 100 W E2/M7 MOPA fiber laser** with a JCZ/EZCAD2-compatible
|
||||||
controller and the currently assumed 110 x 110 mm lens.
|
controller and the operator-confirmed 110 x 110 mm lens.
|
||||||
|
|
||||||
The destination is the useful core of a LightBurn-like workflow: import or
|
The destination is the useful core of a LightBurn-like workflow: import or
|
||||||
create geometry, assign operations and MOPA parameters, preview and validate
|
create geometry, assign operations and MOPA parameters, preview and validate
|
||||||
|
|
@ -36,8 +36,7 @@ Phase 0 has established a reproducible evidence and research baseline:
|
||||||
- the public tests, provenance checks, leak guard, and clean-clone validation
|
- the public tests, provenance checks, leak guard, and clean-clone validation
|
||||||
pass.
|
pass.
|
||||||
|
|
||||||
Phase 0 remains open while we collect machine photos and operator notes directly
|
Phase 0 is complete as an evidence baseline. The settings and device screenshots, bundle,
|
||||||
from the actual control computer. The settings and device screenshots, bundle,
|
|
||||||
exported preferences, closed-application local settings and three explicitly
|
exported preferences, closed-application local settings and three explicitly
|
||||||
operator-verified projects are preserved and analyzed. The operator confirmed a
|
operator-verified projects are preserved and analyzed. The operator confirmed a
|
||||||
110 mm lens; other local test projects remain unverified. See the
|
110 mm lens; other local test projects remain unverified. See the
|
||||||
|
|
@ -75,23 +74,22 @@ We do not need to begin with a blank-sheet LightBurn clone:
|
||||||
material recipes, simulation, pre-flight checks, packaging, and an addon
|
material recipes, simulation, pre-flight checks, packaging, and an addon
|
||||||
architecture. Its job model already represents frequency and pulse width.
|
architecture. Its job model already represents frequency and pulse width.
|
||||||
|
|
||||||
The leading route is therefore either to use and improve MeerK40t directly or
|
The accepted route is a Rayforge JCZ addon with BalorMK retained as the pinned
|
||||||
to build a Rayforge JCZ/Balor addon using the narrowest practical layer from
|
behavioral oracle and reference boundary. Packaged interaction remains an M1
|
||||||
BalorMK. This remains a proposed decision until the packaged interaction and
|
release gate, not an architecture-decision gate; see
|
||||||
real-project gates in
|
[ADR 0002](docs/adr/0002-reuse-rayforge-and-balormk.md).
|
||||||
[ADR 0002](docs/adr/0002-reuse-rayforge-and-balormk.md) have passed.
|
|
||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
|
|
||||||
The initial offline architecture spikes have passed. The next work remains
|
The initial offline architecture spikes have passed. The next work remains
|
||||||
hardware-free:
|
hardware-free:
|
||||||
|
|
||||||
1. collect exterior labels and startup/interlock notes;
|
1. obtain or produce a reviewed Windows Rayforge build artifact without
|
||||||
2. obtain or produce a reviewed Windows Rayforge build artifact without
|
|
||||||
installing a toolchain through this repository;
|
installing a toolchain through this repository;
|
||||||
3. run and record the packaged no-device desktop interaction checklist;
|
2. run and record the packaged no-device desktop interaction checklist;
|
||||||
4. accept, revise, or reject the proposed reuse architecture from evidence;
|
3. promote only evidence-backed vector MOPA imports through the existing
|
||||||
5. complete and independently review the M3 hardware-protocol template before
|
fail-closed review boundary;
|
||||||
|
4. complete and independently review the M3 hardware-protocol template before
|
||||||
seeking separate approval for any live controller communication.
|
seeking separate approval for any live controller communication.
|
||||||
|
|
||||||
An independent desktop application is the fallback only if both existing
|
An independent desktop application is the fallback only if both existing
|
||||||
|
|
|
||||||
|
|
@ -46,13 +46,13 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "android/mipmap-anydpi-v26/ic_launcher.xml",
|
"path": "android/mipmap-anydpi-v26/ic_launcher.xml",
|
||||||
"sha256": "e071a8516287e0bacccc1a14a62502f3e1eda8360b2aad3c88c390ccbfa77122",
|
"sha256": "32715ff646f6b9fef7c321138e4a14556c4a1f98a87b06070b56f41643dad718",
|
||||||
"bytes": 275
|
"bytes": 270
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "android/mipmap-anydpi-v26/ic_launcher_round.xml",
|
"path": "android/mipmap-anydpi-v26/ic_launcher_round.xml",
|
||||||
"sha256": "e071a8516287e0bacccc1a14a62502f3e1eda8360b2aad3c88c390ccbfa77122",
|
"sha256": "32715ff646f6b9fef7c321138e4a14556c4a1f98a87b06070b56f41643dad718",
|
||||||
"bytes": 275
|
"bytes": 270
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "android/mipmap-hdpi/ic_launcher.png",
|
"path": "android/mipmap-hdpi/ic_launcher.png",
|
||||||
|
|
@ -136,8 +136,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "android/values/ic_launcher_background.xml",
|
"path": "android/values/ic_launcher_background.xml",
|
||||||
"sha256": "1ff64d109f4173e84bf4d6ed9957b6f37f3456b0db3b19bb17d3a3c1de2687e4",
|
"sha256": "b54bc246c11f5e12b46926eef269f08b67cf612cc8e9a9580f86d95820b1a2b1",
|
||||||
"bytes": 125
|
"bytes": 121
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "ios/AppIcon.appiconset/Contents.json",
|
"path": "ios/AppIcon.appiconset/Contents.json",
|
||||||
|
|
@ -980,8 +980,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "web/site.webmanifest",
|
"path": "web/site.webmanifest",
|
||||||
"sha256": "ca7277912f7c8ccb373ca252c88050eecc217c355b05d5d6687517947812a32a",
|
"sha256": "e56c1cff35765833a1f4d8d543fdf117d9c6b1572103122340ff037e1fedbac6",
|
||||||
"bytes": 699
|
"bytes": 666
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "windows/app.ico",
|
"path": "windows/app.ico",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Codex continuation brief
|
# Codex continuation brief
|
||||||
|
|
||||||
- Updated: 2026-10-24
|
- Updated: 2026-10-24
|
||||||
- Current focus: M1 build, packaging and no-device acceptance
|
- Current focus: produce and accept the packaged Windows M1 checkpoint
|
||||||
- Hardware access: prohibited
|
- Hardware access: prohibited
|
||||||
- Automatic toolchain installation: prohibited
|
- Automatic toolchain installation: prohibited
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ The repository now provides:
|
||||||
- pinned upstream contract/license manifests and a drift checker;
|
- pinned upstream contract/license manifests and a drift checker;
|
||||||
- a fail-closed API-23 adapter isolating Rayforge's internal driver registry;
|
- a fail-closed API-23 adapter isolating Rayforge's internal driver registry;
|
||||||
- a proposed MIT project-license decision in ADR 0003; Kaz has not accepted
|
- a proposed MIT project-license decision in ADR 0003; Kaz has not accepted
|
||||||
it, so the repository remains unlicensed.
|
it, so the repository remains unlicensed;
|
||||||
- a fail-closed M3 hardware-research protocol, incomplete public plan template
|
- a fail-closed M3 hardware-research protocol, incomplete public plan template
|
||||||
and validator; validation can reach only `ready_for_review` and never
|
and validator; validation can reach only `ready_for_review` and never
|
||||||
authorizes hardware access.
|
authorizes hardware access.
|
||||||
|
|
@ -66,19 +66,20 @@ physically disconnected. LightBurn Pro 2.1.03 showed the JPT profile as
|
||||||
`Disconnected`, the 110 mm material library, and explicit `Frequency (kHz)` /
|
`Disconnected`, the 110 mm material library, and explicit `Frequency (kHz)` /
|
||||||
`Q-Pulse (ns)` UI labels. The live preferences, newest native backup, all five
|
`Q-Pulse (ns)` UI labels. The live preferences, newest native backup, all five
|
||||||
general Settings tabs and all three JPT Device Settings tabs are hashed in
|
general Settings tabs and all three JPT Device Settings tabs are hashed in
|
||||||
PrivateStash. Exterior hardware photographs and startup/interlock notes remain
|
PrivateStash. Exterior hardware photographs and startup/interlock notes are
|
||||||
open; see `docs/research/lightburn-control-machine-observation-2026-10-24.md`.
|
deferred to M3 hardware readiness and do not block the offline product
|
||||||
|
checkpoint; see
|
||||||
|
`docs/research/lightburn-control-machine-observation-2026-10-24.md`.
|
||||||
|
|
||||||
M1 is not complete. Do not describe the repository as a finished desktop
|
M1 is not yet a packaged desktop checkpoint. Only these two result-oriented
|
||||||
application until both gates below have real evidence:
|
gates remain:
|
||||||
|
|
||||||
1. A Windows artifact for the pinned Rayforge revision must be produced on a
|
1. A Windows artifact for the pinned Rayforge revision must be produced on a
|
||||||
reviewed build runner, verified without execution, and pass the manual
|
reviewed build runner, verified without execution, and pass the manual
|
||||||
no-device desktop checklist.
|
no-device desktop checklist.
|
||||||
2. The known-working private JPT `.lbrn2` serialization evidence gate is met.
|
2. Promote only complete vector MOPA imports after an explicit unit contract,
|
||||||
Offline mapping and disabled-output workflow staging now have synthetic
|
absent-pulse-width policy and exact machine-context validation. The private
|
||||||
tests. Promotion still requires an independently established unit contract,
|
serialization-evidence gate itself is complete.
|
||||||
explicit resolution of absent pulse width and machine-context validation.
|
|
||||||
|
|
||||||
Raw projects, screenshots containing identifiers, machine data and build
|
Raw projects, screenshots containing identifiers, machine data and build
|
||||||
binaries stay out of the public repository.
|
binaries stay out of the public repository.
|
||||||
|
|
@ -105,11 +106,13 @@ order:
|
||||||
`docs/research/m1-no-device-acceptance.md`;
|
`docs/research/m1-no-device-acceptance.md`;
|
||||||
4. `scripts/validate_m1_manual_acceptance.py`.
|
4. `scripts/validate_m1_manual_acceptance.py`.
|
||||||
|
|
||||||
If no artifact is available, do not install a build environment here. The next
|
If no artifact is available, send the external-builder handoff in
|
||||||
offline implementation task is evidence-backed MOPA import mapping with
|
`docs/research/m1-no-device-acceptance.md`; do not start another research
|
||||||
synthetic tests; Kaz's explicit decision on ADR 0003 is also outstanding.
|
branch or install a build environment here. Kaz's explicit decision on ADR
|
||||||
|
0003 is also outstanding.
|
||||||
The M3 protocol can also be reviewed offline, but its
|
The M3 protocol can also be reviewed offline, but its
|
||||||
operation allowlist must stay empty until exact read-only request evidence is
|
operation allowlist must stay empty until exact read-only request evidence is
|
||||||
available. Until the external gates and separate hardware approval arrive,
|
available. ADR 0002 is accepted for the offline architecture. Until the
|
||||||
ADR 0002 remains Proposed and no controller backend, USB endpoint access,
|
external gates and separate hardware approval arrive, no controller backend,
|
||||||
physical framing, galvo motion or laser output is authorized.
|
USB endpoint access, physical framing, galvo motion or laser output is
|
||||||
|
authorized.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
# ADR 0002: Prove reuse of Rayforge and BalorMK before building an app
|
# ADR 0002: Prove reuse of Rayforge and BalorMK before building an app
|
||||||
|
|
||||||
- Status: Proposed
|
- Status: Accepted
|
||||||
- Date: 2026-10-17
|
- Date: 2026-10-17
|
||||||
|
- Accepted: 2026-10-24
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@ Creating another editor, geometry stack and controller implementation would
|
||||||
duplicate large, safety-relevant bodies of work and permanently increase the
|
duplicate large, safety-relevant bodies of work and permanently increase the
|
||||||
maintenance burden.
|
maintenance burden.
|
||||||
|
|
||||||
## Proposed decision
|
## Decision
|
||||||
|
|
||||||
Do not begin independent desktop product implementation. First run three
|
Do not begin independent desktop product implementation. First run three
|
||||||
offline, version-pinned proofs:
|
offline, version-pinned proofs:
|
||||||
|
|
@ -32,12 +33,11 @@ offline, version-pinned proofs:
|
||||||
3. translate one synthetic Rayforge operation stream to JCZ/Balor commands and
|
3. translate one synthetic Rayforge operation stream to JCZ/Balor commands and
|
||||||
compare it with a BalorMK mock trace.
|
compare it with a BalorMK mock trace.
|
||||||
|
|
||||||
If the proofs pass, prefer one of these outcomes in order:
|
The proofs pass at the offline architecture boundary. Build the product as a
|
||||||
|
Rayforge JCZ addon and retain pinned BalorMK behavior as the controller-level
|
||||||
1. use and contribute to MeerK40t if its full application is adequate;
|
oracle. Adapt only the narrowest necessary implementation after licensing and
|
||||||
2. implement and upstream a Rayforge JCZ/Balor addon, adapting the narrowest
|
attribution allow it. Packaged Windows interaction remains an M1 release gate,
|
||||||
practical layer from BalorMK;
|
not a reason to defer the host-architecture decision.
|
||||||
3. extract a small maintained controller library shared by either application.
|
|
||||||
|
|
||||||
An independent desktop application requires a later ADR showing concrete,
|
An independent desktop application requires a later ADR showing concrete,
|
||||||
tested gaps in both existing applications.
|
tested gaps in both existing applications.
|
||||||
|
|
@ -121,14 +121,16 @@ Subsequent offline evidence:
|
||||||
- [M1 no-device acceptance checkpoint](../research/m1-no-device-acceptance.md):
|
- [M1 no-device acceptance checkpoint](../research/m1-no-device-acceptance.md):
|
||||||
the public regression suite and leak guard now form one transport-free gate
|
the public regression suite and leak guard now form one transport-free gate
|
||||||
over addon lifecycle, workflow, layers, recipes, encoding, negative cases,
|
over addon lifecycle, workflow, layers, recipes, encoding, negative cases,
|
||||||
cancellation/recovery and synthetic imports. The packaged Windows GUI and a
|
cancellation/recovery and synthetic imports. Packaged Windows interaction
|
||||||
known-working private project remain external gates.
|
remains a release gate.
|
||||||
- [Upstream contract and license audit](../research/upstream-contract-and-license-audit.md):
|
- [Upstream contract and license audit](../research/upstream-contract-and-license-audit.md):
|
||||||
both pins and license notices are now machine-verifiable; the documented
|
both pins and license notices are now machine-verifiable; the documented
|
||||||
addon lifecycle is usable, but driver registration and cleanup still rely
|
addon lifecycle is usable, but driver registration and cleanup still rely
|
||||||
on an internal registry seam that should be replaced upstream.
|
on an internal registry seam that should be replaced upstream.
|
||||||
|
|
||||||
These results satisfy the current model, buffering and no-device integration
|
Three operator-verified private projects subsequently established the
|
||||||
proofs. They do not yet satisfy the packaged human-interaction or real-project
|
project-level `frequency` and `QPulseWidth` serialization needed to implement
|
||||||
import obligations, so this ADR remains proposed.
|
the disabled-output import seam. Together, the evidence satisfies the host
|
||||||
|
architecture decision. It does not authorize hardware access or claim that the
|
||||||
|
packaged Windows interaction and import-promotion release gates have passed.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,9 @@ The PirateRay-specific work should remain narrow:
|
||||||
|
|
||||||
## Gaps that must not be papered over
|
## Gaps that must not be papered over
|
||||||
|
|
||||||
1. A known-working private galvo `.lbrn2` is still required to establish
|
1. Three known-working private galvo projects establish project-level
|
||||||
project-level `QPulseWidth` serialization and omission/default behavior.
|
`QPulseWidth` serialization. Omission/default behavior still requires an
|
||||||
|
explicit policy before promotion to executable output.
|
||||||
2. The current Windows environment has not launched the pinned Rayforge GTK
|
2. The current Windows environment has not launched the pinned Rayforge GTK
|
||||||
application; the headless UI contract is not a human interaction test.
|
application; the headless UI contract is not a human interaction test.
|
||||||
3. `RequireFrameBeforeStart` is observed in a LightBurn device export and
|
3. `RequireFrameBeforeStart` is observed in a LightBurn device export and
|
||||||
|
|
@ -111,8 +112,9 @@ The PirateRay-specific work should remain narrow:
|
||||||
framing behavior.
|
framing behavior.
|
||||||
4. Machine-specific frequency, pulse-width, timing and correction limits are
|
4. Machine-specific frequency, pulse-width, timing and correction limits are
|
||||||
not established by LightBurn documentation or exported recipe values.
|
not established by LightBurn documentation or exported recipe values.
|
||||||
5. Material recipes lack a proven contract for provenance, approval and
|
5. PirateRay recipe metadata now supplies fail-closed provenance, approval and
|
||||||
machine/lens/correction compatibility.
|
machine/lens/correction compatibility checks; packaged UI interaction is
|
||||||
|
still part of the M1 desktop checklist.
|
||||||
6. The HTML prototype named by the handoff is absent from the active checkout;
|
6. The HTML prototype named by the handoff is absent from the active checkout;
|
||||||
its historical controls must not be treated as implemented capability.
|
its historical controls must not be treated as implemented capability.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,5 @@ test explicit unit conversions, field absence and invalid values. It must not
|
||||||
copy private project geometry into public fixtures or enable hardware access.
|
copy private project geometry into public fixtures or enable hardware access.
|
||||||
|
|
||||||
The reviewed Windows artifact and manual no-device desktop acceptance remain
|
The reviewed Windows artifact and manual no-device desktop acceptance remain
|
||||||
open. ADR 0002 remains Proposed until those gates have also passed.
|
open as M1 release gates. ADR 0002 has accepted the Rayforge-addon architecture
|
||||||
|
independently of those packaging gates.
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,17 @@ runtime is unavailable, it stops and reports the missing prerequisite. Any
|
||||||
toolchain preparation remains a separate, explicitly invoked upstream action
|
toolchain preparation remains a separate, explicitly invoked upstream action
|
||||||
or should happen on a dedicated build runner.
|
or should happen on a dedicated build runner.
|
||||||
|
|
||||||
|
### External builder handoff
|
||||||
|
|
||||||
|
The external builder needs only a clean checkout of this repository, Windows,
|
||||||
|
and a reviewed Rayforge-compatible MSYS2/UCRT64 runtime. No laser or controller
|
||||||
|
may be connected. Run `scripts/build_rayforge_windows_checkpoint.ps1` from the
|
||||||
|
repository root with a clean checkout and an absent or empty artifact path. A
|
||||||
|
successful run leaves one transferable directory,
|
||||||
|
`.build/artifacts/`, containing exactly the portable ZIP, installer, Rayforge
|
||||||
|
license sidecar and `rayforge-windows-checkpoint.json`. Transfer that directory
|
||||||
|
as a unit; the receiving side verifies it before executing either binary.
|
||||||
|
|
||||||
Before staging, the script rejects transport imports in the addon. The build
|
Before staging, the script rejects transport imports in the addon. The build
|
||||||
entry point also rejects tracked Rayforge modifications and any unexpected
|
entry point also rejects tracked Rayforge modifications and any unexpected
|
||||||
untracked source. It removes and recreates only the validated addon staging
|
untracked source. It removes and recreates only the validated addon staging
|
||||||
|
|
@ -150,10 +161,12 @@ hardware, non-isolated app data, changed evidence, malformed review or any
|
||||||
stop condition. Final `passed` requires a non-empty reviewer name and an
|
stop condition. Final `passed` requires a non-empty reviewer name and an
|
||||||
ISO-8601 review timestamp with timezone. No status authorizes hardware access.
|
ISO-8601 review timestamp with timezone. No status authorizes hardware access.
|
||||||
|
|
||||||
## Remaining external gates
|
## Remaining release gates
|
||||||
|
|
||||||
- A known-working private `.lbrn2` is still required before implementing
|
|
||||||
project-level `QPulseWidth` mapping.
|
|
||||||
- Human interaction results from the packaged build must be recorded before
|
- Human interaction results from the packaged build must be recorded before
|
||||||
ADR 0002 can be accepted.
|
M1 can be called a packaged desktop checkpoint.
|
||||||
|
- The three known-working private projects establish serialized MOPA fields.
|
||||||
|
Promotion from disabled staging still requires the explicit unit contract,
|
||||||
|
absent-pulse-width policy and exact machine-context validation already
|
||||||
|
enforced by preflight.
|
||||||
- Physical controller behavior remains outside M1.
|
- Physical controller behavior remains outside M1.
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ optics:
|
||||||
active_field_mm:
|
active_field_mm:
|
||||||
width: 110
|
width: 110
|
||||||
height: 110
|
height: 110
|
||||||
status: assumed-pending-physical-verification
|
status: operator-confirmed-on-control-machine
|
||||||
other_configurations_observed_mm:
|
other_configurations_observed_mm:
|
||||||
- width: 300
|
- width: 300
|
||||||
height: 300
|
height: 300
|
||||||
|
|
@ -63,3 +63,4 @@ notes:
|
||||||
- USB revision 0005 is a descriptor value, not a proven board or firmware version.
|
- USB revision 0005 is a descriptor value, not a proven board or firmware version.
|
||||||
- LightBurn bundle manifests establish version 2.1.03 but do not expose a separate build identifier.
|
- LightBurn bundle manifests establish version 2.1.03 but do not expose a separate build identifier.
|
||||||
- Exported recipe values are observations, not certified hardware limits or safe operating parameters.
|
- Exported recipe values are observations, not certified hardware limits or safe operating parameters.
|
||||||
|
- The operator confirmed the installed 110 mm lens during the disconnected control-machine inspection on 2026-10-24.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Product and research roadmap
|
# Product and research roadmap
|
||||||
|
|
||||||
Last updated: 2026-10-21
|
Last updated: 2026-10-24
|
||||||
|
|
||||||
## Destination
|
## Destination
|
||||||
|
|
||||||
|
|
@ -65,8 +65,7 @@ It does **not** yet establish:
|
||||||
- which values are controller settings versus laser-source settings;
|
- which values are controller settings versus laser-source settings;
|
||||||
- status, interlock, error, abort, and recovery behavior;
|
- status, interlock, error, abort, and recovery behavior;
|
||||||
- whether an apparently harmless query can move a galvo or arm emission;
|
- whether an apparently harmless query can move a galvo or arm emission;
|
||||||
- how a known-working `.lbrn2` project serializes JPT frequency and
|
- the effective pulse-width default for settings that omit `QPulseWidth`.
|
||||||
`QPulseWidth` settings.
|
|
||||||
|
|
||||||
The later LightBurn export collection now establishes version `2.1.03`, a
|
The later LightBurn export collection now establishes version `2.1.03`, a
|
||||||
110 x 110 mm `JCZFiber`/`LibUSB` JPT profile, and the `QPulseWidth` device
|
110 x 110 mm `JCZFiber`/`LibUSB` JPT profile, and the `QPulseWidth` device
|
||||||
|
|
@ -78,7 +77,7 @@ would be premature and would make the safety boundary impossible to audit.
|
||||||
|
|
||||||
## Milestones
|
## Milestones
|
||||||
|
|
||||||
### M0 — Evidence baseline (current)
|
### M0 — Evidence baseline (complete)
|
||||||
|
|
||||||
Preserve and hash the installer snapshot, publish sanitized findings, and keep
|
Preserve and hash the installer snapshot, publish sanitized findings, and keep
|
||||||
public/private provenance verifiable. Complete M0 with one local collection
|
public/private provenance verifiable. Complete M0 with one local collection
|
||||||
|
|
@ -90,7 +89,7 @@ Exit criteria:
|
||||||
|
|
||||||
- exact LightBurn version, bundle, preferences, screenshots, and working
|
- exact LightBurn version, bundle, preferences, screenshots, and working
|
||||||
project examples are present in PrivateStash;
|
project examples are present in PrivateStash;
|
||||||
- mounted lens, startup, interlock, and USB device identity are confirmed;
|
- mounted lens and USB device identity are confirmed;
|
||||||
- sanitized metadata and new analysis are committed publicly;
|
- sanitized metadata and new analysis are committed publicly;
|
||||||
- both repositories pass their clean-clone validation.
|
- both repositories pass their clean-clone validation.
|
||||||
|
|
||||||
|
|
@ -100,7 +99,7 @@ Ecosystem research found that Rayforge already implements most of the desired
|
||||||
application and MeerK40t BalorMK already implements the relevant controller.
|
application and MeerK40t BalorMK already implements the relevant controller.
|
||||||
Validate those assets before defining competing application architecture. See
|
Validate those assets before defining competing application architecture. See
|
||||||
the [open-source landscape](research/open-source-landscape.md) and
|
the [open-source landscape](research/open-source-landscape.md) and
|
||||||
[proposed ADR 0002](adr/0002-reuse-rayforge-and-balormk.md).
|
[accepted ADR 0002](adr/0002-reuse-rayforge-and-balormk.md).
|
||||||
|
|
||||||
The first work is entirely offline:
|
The first work is entirely offline:
|
||||||
|
|
||||||
|
|
@ -150,24 +149,21 @@ width, and unsupported Ops. Hardware-specific upper limits remain unknown and
|
||||||
are deliberately not guessed.
|
are deliberately not guessed.
|
||||||
|
|
||||||
[The transport-free JCZ record spike](research/rayforge-jcz-packet-spike.md)
|
[The transport-free JCZ record spike](research/rayforge-jcz-packet-spike.md)
|
||||||
packs the same operation stream into deterministic little-endian 12-byte
|
now extends the deterministic 12-byte records with fixed-size list buffering
|
||||||
records whose opcodes, values, coordinates and distances match the pinned
|
and explicit state-before-motion ordering. Upload, execution and physical
|
||||||
BalorMK mock evidence. It deliberately omits list buffering and all transport;
|
transport remain outside M1.
|
||||||
controller-safe state ordering remains an explicit evidence gap.
|
|
||||||
|
|
||||||
[The synthetic LightBurn MOPA import spike](research/rayforge-lightburn-mopa-import-spike.md)
|
[The synthetic LightBurn MOPA import spike](research/rayforge-lightburn-mopa-import-spike.md)
|
||||||
confirms that Rayforge preserves geometry, power, speed and passes and retains
|
confirms that Rayforge preserves geometry, power, speed and passes. Three later
|
||||||
an observed LightBurn frequency value in raw source metadata. Frequency is not
|
operator-verified projects establish project-level `frequency` and
|
||||||
mapped into workflow settings. A later real device export identifies
|
`QPulseWidth` fields. The addon now stages complete vector settings into
|
||||||
`QPulseWidth` and its nanosecond UI contract, but project serialization remains
|
disabled Rayforge steps and rejects them at preflight until units, defaults and
|
||||||
unknown, so the job still deliberately fails the JCZ encoding gate. A private
|
machine context are explicitly approved.
|
||||||
known-working `.lbrn2` fixture is required before implementing the missing
|
|
||||||
MOPA mapping.
|
|
||||||
|
|
||||||
The architecture decision remains proposed until the packaged Windows
|
ADR 0002 accepts the Rayforge-addon architecture with BalorMK as the pinned
|
||||||
interaction and known-working private-project gates produce evidence. An
|
behavioral oracle. Packaged Windows interaction is a release gate, not an open
|
||||||
independent app requires a documented gap analysis showing why neither
|
architecture question. An independent app now requires a later ADR with
|
||||||
existing platform can be extended responsibly.
|
concrete evidence that this accepted route cannot meet product needs.
|
||||||
|
|
||||||
Exit criteria: a representative JPT job survives import/planning, MOPA
|
Exit criteria: a representative JPT job survives import/planning, MOPA
|
||||||
parameters and units, validation and deterministic mock encoding; the chosen
|
parameters and units, validation and deterministic mock encoding; the chosen
|
||||||
|
|
@ -266,26 +262,24 @@ Bodor BCL503MU. Each controller family gets its own evidence, protocol,
|
||||||
capability, and hardware-validation track. A successful JPT backend does not
|
capability, and hardware-validation track. A successful JPT backend does not
|
||||||
imply compatible safety or control behavior on either CO2 machine.
|
imply compatible safety or control behavior on either CO2 machine.
|
||||||
|
|
||||||
## Immediate next work package
|
## Current completion track
|
||||||
|
|
||||||
The next work package should be small enough to review in a few commits:
|
The exploratory work package is complete: verified projects, device evidence,
|
||||||
|
profile import, list buffering, cancellation/recovery, workflow modeling and
|
||||||
|
the M3 protocol draft are all present. Work now converges on two deliverables:
|
||||||
|
|
||||||
1. collect two or three known-working `.lbrn2` projects plus the remaining
|
1. produce the pinned Windows Rayforge checkpoint on a reviewed external build
|
||||||
device screenshots, preferences folder, photos and operator notes;
|
runner, verify the transferred artifact set and complete the no-device
|
||||||
2. add a sanitized synthetic JCZ `.lbdev` fixture and characterize the exact
|
desktop interaction checklist;
|
||||||
gaps in Rayforge's device importer;
|
2. promote complete vector MOPA imports only after recording the explicit unit
|
||||||
3. implement and test the smallest evidence-backed JCZ profile-import seam,
|
contract, absent-pulse-width policy and exact machine-context validation.
|
||||||
keeping project `QPulseWidth` mapping gated until a real project confirms
|
|
||||||
its serialization;
|
|
||||||
4. extend the offline JCZ encoder from semantic records to controller-list
|
|
||||||
buffering and explicit safe state ordering, still without transport;
|
|
||||||
5. exercise cancellation/recovery and the graphical workflow against mock
|
|
||||||
backends, then accept, amend or reject ADR 0002;
|
|
||||||
6. complete and independently review the written M3 hardware-research protocol
|
|
||||||
before seeking separate approval for any USB endpoint access or controller
|
|
||||||
command.
|
|
||||||
|
|
||||||
The draft, template, validator and regression tests for item 6 are present.
|
Exterior photographs, additional screenshots and speculative protocol research
|
||||||
|
are not M1 blockers. Hardware work remains separately gated by M3.
|
||||||
|
|
||||||
|
### Completed implementation record
|
||||||
|
|
||||||
|
The M3 draft, template, validator and regression tests are present.
|
||||||
Hardware work still cannot proceed until the exact read-only operation evidence,
|
Hardware work still cannot proceed until the exact read-only operation evidence,
|
||||||
driver/rollback plan, physical controls, distinct assigned roles and separate
|
driver/rollback plan, physical controls, distinct assigned roles and separate
|
||||||
human approval are all in place.
|
human approval are all in place.
|
||||||
|
|
@ -299,8 +293,8 @@ profile model. The fixture and regression test remain transport-free.
|
||||||
Item 3 now has a minimal external-addon seam: it recognizes only the synthetic
|
Item 3 now has a minimal external-addon seam: it recognizes only the synthetic
|
||||||
`JCZFiber` fixture with explicit provenance and frame-before-start, binds it to
|
`JCZFiber` fixture with explicit provenance and frame-before-start, binds it to
|
||||||
the no-device JCZ driver, preserves process values as raw observations with
|
the no-device JCZ driver, preserves process values as raw observations with
|
||||||
unit uncertainty, and keeps encoding disabled until the remaining profile and
|
unit uncertainty, and keeps encoding disabled until the unit/default and exact
|
||||||
project evidence exists.
|
machine-context review passes.
|
||||||
|
|
||||||
Item 4 now covers transport-free fixed-size list buffering and an explicit
|
Item 4 now covers transport-free fixed-size list buffering and an explicit
|
||||||
state-before-motion order derived from pinned BalorMK. Port commands, upload,
|
state-before-motion order derived from pinned BalorMK. Port commands, upload,
|
||||||
|
|
@ -318,7 +312,8 @@ generated settings UI exposes frequency and pulse width with Hz/ns contracts,
|
||||||
the values survive step serialization, and the preview artifact is populated
|
the values survive step serialization, and the preview artifact is populated
|
||||||
without machine code or transport. This is a headless UI-contract and pipeline
|
without machine code or transport. This is a headless UI-contract and pipeline
|
||||||
proof, not a completed human GTK test. Packaged Windows interaction with the
|
proof, not a completed human GTK test. Packaged Windows interaction with the
|
||||||
external addon remains open before item 5 or ADR 0002 can close.
|
external addon remains the final desktop release gate; ADR 0002 has accepted
|
||||||
|
the architecture independently of it.
|
||||||
|
|
||||||
The first Windows launch preflight is recorded separately. It fails closed
|
The first Windows launch preflight is recorded separately. It fails closed
|
||||||
because the available spike venv has no PyGObject `gi` module and this machine
|
because the available spike venv has no PyGObject `gi` module and this machine
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Phase 0 status
|
# Phase 0 status — complete
|
||||||
|
|
||||||
Last updated: 2026-10-24
|
Last updated: 2026-10-24
|
||||||
|
|
||||||
|
|
@ -43,9 +43,10 @@ Last updated: 2026-10-24
|
||||||
and preserved privately. They confirm the 110 x 110 mm field, Q-pulse-width
|
and preserved privately. They confirm the 110 x 110 mm field, Q-pulse-width
|
||||||
enablement, visible 1-4000 kHz range and require-frame-before-start setting.
|
enablement, visible 1-4000 kHz range and require-frame-before-start setting.
|
||||||
|
|
||||||
## Pending external acquisition
|
## Deferred hardware-readiness evidence
|
||||||
|
|
||||||
These items remain pending from the actual control machine:
|
These items are still useful before hardware work, but no longer block the
|
||||||
|
completed Phase 0 evidence baseline or the offline M1 product checkpoint:
|
||||||
|
|
||||||
- safe exterior hardware/label photographs and startup/interlock notes;
|
- safe exterior hardware/label photographs and startup/interlock notes;
|
||||||
- stock-driver identity and version from the actual LightBurn control computer.
|
- stock-driver identity and version from the actual LightBurn control computer.
|
||||||
|
|
@ -58,13 +59,8 @@ Collect them directly into a dated directory under PrivateStash by following
|
||||||
the [LightBurn checklist](../collection/lightburn.md). Do not use Google Drive
|
the [LightBurn checklist](../collection/lightburn.md). Do not use Google Drive
|
||||||
as an intermediate project workspace and do not generate Support Data.
|
as an intermediate project workspace and do not generate Support Data.
|
||||||
|
|
||||||
Phase 0 remains open until the safety- and interoperability-relevant remainder
|
Collect them when preparing an approved M3 hardware session. Do not expand the
|
||||||
is hashed, committed, pushed, and represented by sanitized public evidence.
|
offline product scope merely to keep Phase 0 open.
|
||||||
|
|
||||||
The work that does not depend on this acquisition can proceed in parallel.
|
|
||||||
The [product and research roadmap](../roadmap.md) defines the offline application
|
|
||||||
core, configuration analysis, protocol research, gated hardware experiments,
|
|
||||||
and workshop release as separate milestones.
|
|
||||||
|
|
||||||
## Offline M1 status
|
## Offline M1 status
|
||||||
|
|
||||||
|
|
@ -112,17 +108,20 @@ evidence for:
|
||||||
commit, reviewer, bounded session and explicit safety statements while still
|
commit, reviewer, bounded session and explicit safety statements while still
|
||||||
requiring live preflight and returning no automatic hardware authorization.
|
requiring live preflight and returning no automatic hardware authorization.
|
||||||
|
|
||||||
The remaining M1 gates are deliberately explicit:
|
The remaining M1 release gates are deliberately narrow:
|
||||||
|
|
||||||
- a private known-working `.lbrn2` project is still required before mapping
|
|
||||||
project-level `QPulseWidth` into workflow settings;
|
|
||||||
- packaged Windows/GTK interaction is blocked until a reviewed Rayforge
|
- packaged Windows/GTK interaction is blocked until a reviewed Rayforge
|
||||||
runtime with PyGObject and MSYS2/UCRT64 is available; the repository build
|
runtime with PyGObject and MSYS2/UCRT64 is available; the repository build
|
||||||
entry point fetches pinned source but never installs that runtime;
|
entry point fetches pinned source but never installs that runtime;
|
||||||
- graphical workflow, import, lens correction and controller protocol
|
- three operator-verified projects establish project-level `frequency` and
|
||||||
behavior remain unproven at the physical boundary;
|
`QPulseWidth` serialization, and the offline bridge stages complete vector
|
||||||
- ADR 0002 remains **Proposed** until those gaps are resolved or rejected by
|
settings with output disabled; promotion still requires an explicit unit
|
||||||
evidence.
|
contract, absent-pulse-width policy and exact machine-context validation;
|
||||||
|
- graphical workflow, lens correction and controller behavior remain unproven
|
||||||
|
at the physical boundary and belong to later gated milestones.
|
||||||
|
|
||||||
|
ADR 0002 is accepted for the offline product architecture. These release gates
|
||||||
|
do not reopen that decision.
|
||||||
|
|
||||||
No item in this section authorizes USB access, controller commands or laser
|
No item in this section authorizes USB access, controller commands or laser
|
||||||
output.
|
output.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,22 @@ if (-not $ArtifactRoot) {
|
||||||
$ArtifactRoot = Join-Path $repositoryRoot ".build\artifacts"
|
$ArtifactRoot = Join-Path $repositoryRoot ".build\artifacts"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$repositoryStatus = @(
|
||||||
|
& git -C $repositoryRoot status --porcelain=v1 --untracked-files=all
|
||||||
|
)
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw "Could not inspect The Pirate Ray checkout state"
|
||||||
|
}
|
||||||
|
if ($repositoryStatus.Count -gt 0) {
|
||||||
|
throw "The Pirate Ray checkout must be clean before an external checkpoint build"
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(Test-Path -LiteralPath $ArtifactRoot) -and
|
||||||
|
@(Get-ChildItem -LiteralPath $ArtifactRoot -Force).Count -gt 0
|
||||||
|
) {
|
||||||
|
throw "Artifact root must be absent or empty: $ArtifactRoot"
|
||||||
|
}
|
||||||
|
|
||||||
& (Join-Path $PSScriptRoot "prepare_rayforge_build.ps1") `
|
& (Join-Path $PSScriptRoot "prepare_rayforge_build.ps1") `
|
||||||
-CacheRoot $CacheRoot `
|
-CacheRoot $CacheRoot `
|
||||||
-AllowStagedPirateRayAddon
|
-AllowStagedPirateRayAddon
|
||||||
|
|
@ -87,6 +103,10 @@ if (-not (Test-Path -LiteralPath $installer)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force -Path $ArtifactRoot | Out-Null
|
New-Item -ItemType Directory -Force -Path $ArtifactRoot | Out-Null
|
||||||
|
$artifactInstaller = Join-Path $ArtifactRoot (Split-Path -Leaf $installer)
|
||||||
|
if ($PSCmdlet.ShouldProcess($artifactInstaller, "Copy installer into checkpoint")) {
|
||||||
|
Copy-Item -LiteralPath $installer -Destination $artifactInstaller -Force
|
||||||
|
}
|
||||||
$licenseDirectory = Join-Path $bundleDirectory "THIRD_PARTY_LICENSES"
|
$licenseDirectory = Join-Path $bundleDirectory "THIRD_PARTY_LICENSES"
|
||||||
$rayforgeLicense = Join-Path $checkout "LICENSE"
|
$rayforgeLicense = Join-Path $checkout "LICENSE"
|
||||||
$normalizedLicense = [IO.File]::ReadAllText($rayforgeLicense).Replace("`r`n", "`n").Replace("`r", "`n")
|
$normalizedLicense = [IO.File]::ReadAllText($rayforgeLicense).Replace("`r`n", "`n").Replace("`r", "`n")
|
||||||
|
|
@ -134,9 +154,9 @@ $result = [ordered]@{
|
||||||
bytes = (Get-Item -LiteralPath $archive).Length
|
bytes = (Get-Item -LiteralPath $archive).Length
|
||||||
}
|
}
|
||||||
installer = [ordered]@{
|
installer = [ordered]@{
|
||||||
path = Split-Path -Leaf $installer
|
path = Split-Path -Leaf $artifactInstaller
|
||||||
sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $installer).Hash.ToLowerInvariant()
|
sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $artifactInstaller).Hash.ToLowerInvariant()
|
||||||
bytes = (Get-Item -LiteralPath $installer).Length
|
bytes = (Get-Item -LiteralPath $artifactInstaller).Length
|
||||||
}
|
}
|
||||||
license_files = @(
|
license_files = @(
|
||||||
[ordered]@{
|
[ordered]@{
|
||||||
|
|
@ -152,3 +172,4 @@ $result = [ordered]@{
|
||||||
$manifestPath = Join-Path $ArtifactRoot "rayforge-windows-checkpoint.json"
|
$manifestPath = Join-Path $ArtifactRoot "rayforge-windows-checkpoint.json"
|
||||||
$result | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $manifestPath -Encoding utf8
|
$result | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $manifestPath -Encoding utf8
|
||||||
Write-Output "Checkpoint manifest: $manifestPath"
|
Write-Output "Checkpoint manifest: $manifestPath"
|
||||||
|
Write-Output "Transfer the complete artifact directory: $ArtifactRoot"
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ def run(source: Path) -> dict:
|
||||||
"evidence": evidence,
|
"evidence": evidence,
|
||||||
"remaining_manual_gates": [
|
"remaining_manual_gates": [
|
||||||
"packaged Windows GUI interaction",
|
"packaged Windows GUI interaction",
|
||||||
"known-working private LightBurn project import",
|
"reviewed promotion of imported MOPA settings",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ EXPECTED_TARGET = {
|
||||||
"usb_pid": "9899",
|
"usb_pid": "9899",
|
||||||
"device_description": "USBLMCV4",
|
"device_description": "USBLMCV4",
|
||||||
"lens_field_mm": 110,
|
"lens_field_mm": 110,
|
||||||
"lens_status": "assumed-pending-physical-verification",
|
"lens_status": "operator-confirmed-on-control-machine",
|
||||||
}
|
}
|
||||||
PROHIBITED_CAPABILITIES = {
|
PROHIBITED_CAPABILITIES = {
|
||||||
"persistent_write",
|
"persistent_write",
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
"usb_pid": "9899",
|
"usb_pid": "9899",
|
||||||
"device_description": "USBLMCV4",
|
"device_description": "USBLMCV4",
|
||||||
"lens_field_mm": 110,
|
"lens_field_mm": 110,
|
||||||
"lens_status": "assumed-pending-physical-verification"
|
"lens_status": "operator-confirmed-on-control-machine"
|
||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"milestone": "M3",
|
"milestone": "M3",
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class M1AcceptancePipelineTests(unittest.TestCase):
|
||||||
source = ACCEPTANCE.read_text(encoding="utf-8")
|
source = ACCEPTANCE.read_text(encoding="utf-8")
|
||||||
self.assertIn(manifest["commit"], source)
|
self.assertIn(manifest["commit"], source)
|
||||||
self.assertIn("packaged Windows GUI interaction", source)
|
self.assertIn("packaged Windows GUI interaction", source)
|
||||||
self.assertIn("known-working private LightBurn project import", source)
|
self.assertIn("reviewed promotion of imported MOPA settings", source)
|
||||||
self.assertIn('"-m", "unittest", "discover"', source)
|
self.assertIn('"-m", "unittest", "discover"', source)
|
||||||
self.assertIn("scripts/check_public_repo.py", source)
|
self.assertIn("scripts/check_public_repo.py", source)
|
||||||
self.assertIn("timeout=120", source)
|
self.assertIn("timeout=120", source)
|
||||||
|
|
@ -50,6 +50,10 @@ class M1AcceptancePipelineTests(unittest.TestCase):
|
||||||
self.assertIn("GetFullPath", source)
|
self.assertIn("GetFullPath", source)
|
||||||
self.assertIn("Remove-Item -LiteralPath $resolvedAddonDestination", source)
|
self.assertIn("Remove-Item -LiteralPath $resolvedAddonDestination", source)
|
||||||
self.assertIn("AllowStagedPirateRayAddon", source)
|
self.assertIn("AllowStagedPirateRayAddon", source)
|
||||||
|
self.assertIn("Copy installer into checkpoint", source)
|
||||||
|
self.assertIn("-LiteralPath $artifactInstaller", source)
|
||||||
|
self.assertIn("checkout must be clean", source)
|
||||||
|
self.assertIn("Artifact root must be absent or empty", source)
|
||||||
|
|
||||||
def test_acceptance_has_no_hardware_commands(self):
|
def test_acceptance_has_no_hardware_commands(self):
|
||||||
source = ACCEPTANCE.read_text(encoding="utf-8").lower()
|
source = ACCEPTANCE.read_text(encoding="utf-8").lower()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue