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/
|
||||
.venv/
|
||||
.uv-cache/
|
||||
/.build/
|
||||
/.build/*
|
||||
!/.build/.gitkeep
|
||||
|
||||
# Sensitive/raw acquisition data belongs in ThePirateRay-PrivateStash.
|
||||
/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
|
||||
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
|
||||
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
|
||||
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
|
||||
pass.
|
||||
|
||||
Phase 0 remains open while we collect machine photos and operator notes directly
|
||||
from the actual control computer. The settings and device screenshots, bundle,
|
||||
Phase 0 is complete as an evidence baseline. The settings and device screenshots, bundle,
|
||||
exported preferences, closed-application local settings and three explicitly
|
||||
operator-verified projects are preserved and analyzed. The operator confirmed a
|
||||
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
|
||||
architecture. Its job model already represents frequency and pulse width.
|
||||
|
||||
The leading route is therefore either to use and improve MeerK40t directly or
|
||||
to build a Rayforge JCZ/Balor addon using the narrowest practical layer from
|
||||
BalorMK. This remains a proposed decision until the packaged interaction and
|
||||
real-project gates in
|
||||
[ADR 0002](docs/adr/0002-reuse-rayforge-and-balormk.md) have passed.
|
||||
The accepted route is a Rayforge JCZ addon with BalorMK retained as the pinned
|
||||
behavioral oracle and reference boundary. Packaged interaction remains an M1
|
||||
release gate, not an architecture-decision gate; see
|
||||
[ADR 0002](docs/adr/0002-reuse-rayforge-and-balormk.md).
|
||||
|
||||
## Next steps
|
||||
|
||||
The initial offline architecture spikes have passed. The next work remains
|
||||
hardware-free:
|
||||
|
||||
1. collect exterior labels and startup/interlock notes;
|
||||
2. obtain or produce a reviewed Windows Rayforge build artifact without
|
||||
1. obtain or produce a reviewed Windows Rayforge build artifact without
|
||||
installing a toolchain through this repository;
|
||||
3. run and record the packaged no-device desktop interaction checklist;
|
||||
4. accept, revise, or reject the proposed reuse architecture from evidence;
|
||||
5. complete and independently review the M3 hardware-protocol template before
|
||||
2. run and record the packaged no-device desktop interaction checklist;
|
||||
3. promote only evidence-backed vector MOPA imports through the existing
|
||||
fail-closed review boundary;
|
||||
4. complete and independently review the M3 hardware-protocol template before
|
||||
seeking separate approval for any live controller communication.
|
||||
|
||||
An independent desktop application is the fallback only if both existing
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@
|
|||
},
|
||||
{
|
||||
"path": "android/mipmap-anydpi-v26/ic_launcher.xml",
|
||||
"sha256": "e071a8516287e0bacccc1a14a62502f3e1eda8360b2aad3c88c390ccbfa77122",
|
||||
"bytes": 275
|
||||
"sha256": "32715ff646f6b9fef7c321138e4a14556c4a1f98a87b06070b56f41643dad718",
|
||||
"bytes": 270
|
||||
},
|
||||
{
|
||||
"path": "android/mipmap-anydpi-v26/ic_launcher_round.xml",
|
||||
"sha256": "e071a8516287e0bacccc1a14a62502f3e1eda8360b2aad3c88c390ccbfa77122",
|
||||
"bytes": 275
|
||||
"sha256": "32715ff646f6b9fef7c321138e4a14556c4a1f98a87b06070b56f41643dad718",
|
||||
"bytes": 270
|
||||
},
|
||||
{
|
||||
"path": "android/mipmap-hdpi/ic_launcher.png",
|
||||
|
|
@ -136,8 +136,8 @@
|
|||
},
|
||||
{
|
||||
"path": "android/values/ic_launcher_background.xml",
|
||||
"sha256": "1ff64d109f4173e84bf4d6ed9957b6f37f3456b0db3b19bb17d3a3c1de2687e4",
|
||||
"bytes": 125
|
||||
"sha256": "b54bc246c11f5e12b46926eef269f08b67cf612cc8e9a9580f86d95820b1a2b1",
|
||||
"bytes": 121
|
||||
},
|
||||
{
|
||||
"path": "ios/AppIcon.appiconset/Contents.json",
|
||||
|
|
@ -980,8 +980,8 @@
|
|||
},
|
||||
{
|
||||
"path": "web/site.webmanifest",
|
||||
"sha256": "ca7277912f7c8ccb373ca252c88050eecc217c355b05d5d6687517947812a32a",
|
||||
"bytes": 699
|
||||
"sha256": "e56c1cff35765833a1f4d8d543fdf117d9c6b1572103122340ff037e1fedbac6",
|
||||
"bytes": 666
|
||||
},
|
||||
{
|
||||
"path": "windows/app.ico",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Codex continuation brief
|
||||
|
||||
- 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
|
||||
- Automatic toolchain installation: prohibited
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ The repository now provides:
|
|||
- pinned upstream contract/license manifests and a drift checker;
|
||||
- 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
|
||||
it, so the repository remains unlicensed.
|
||||
it, so the repository remains unlicensed;
|
||||
- a fail-closed M3 hardware-research protocol, incomplete public plan template
|
||||
and validator; validation can reach only `ready_for_review` and never
|
||||
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)` /
|
||||
`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
|
||||
PrivateStash. Exterior hardware photographs and startup/interlock notes remain
|
||||
open; see `docs/research/lightburn-control-machine-observation-2026-10-24.md`.
|
||||
PrivateStash. Exterior hardware photographs and startup/interlock notes are
|
||||
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
|
||||
application until both gates below have real evidence:
|
||||
M1 is not yet a packaged desktop checkpoint. Only these two result-oriented
|
||||
gates remain:
|
||||
|
||||
1. A Windows artifact for the pinned Rayforge revision must be produced on a
|
||||
reviewed build runner, verified without execution, and pass the manual
|
||||
no-device desktop checklist.
|
||||
2. The known-working private JPT `.lbrn2` serialization evidence gate is met.
|
||||
Offline mapping and disabled-output workflow staging now have synthetic
|
||||
tests. Promotion still requires an independently established unit contract,
|
||||
explicit resolution of absent pulse width and machine-context validation.
|
||||
2. Promote only complete vector MOPA imports after an explicit unit contract,
|
||||
absent-pulse-width policy and exact machine-context validation. The private
|
||||
serialization-evidence gate itself is complete.
|
||||
|
||||
Raw projects, screenshots containing identifiers, machine data and build
|
||||
binaries stay out of the public repository.
|
||||
|
|
@ -105,11 +106,13 @@ order:
|
|||
`docs/research/m1-no-device-acceptance.md`;
|
||||
4. `scripts/validate_m1_manual_acceptance.py`.
|
||||
|
||||
If no artifact is available, do not install a build environment here. The next
|
||||
offline implementation task is evidence-backed MOPA import mapping with
|
||||
synthetic tests; Kaz's explicit decision on ADR 0003 is also outstanding.
|
||||
If no artifact is available, send the external-builder handoff in
|
||||
`docs/research/m1-no-device-acceptance.md`; do not start another research
|
||||
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
|
||||
operation allowlist must stay empty until exact read-only request evidence is
|
||||
available. Until the external gates and separate hardware approval arrive,
|
||||
ADR 0002 remains Proposed and no controller backend, USB endpoint access,
|
||||
physical framing, galvo motion or laser output is authorized.
|
||||
available. ADR 0002 is accepted for the offline architecture. Until the
|
||||
external gates and separate hardware approval arrive, no controller backend,
|
||||
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
|
||||
|
||||
- Status: Proposed
|
||||
- Status: Accepted
|
||||
- Date: 2026-10-17
|
||||
- Accepted: 2026-10-24
|
||||
|
||||
## 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
|
||||
maintenance burden.
|
||||
|
||||
## Proposed decision
|
||||
## Decision
|
||||
|
||||
Do not begin independent desktop product implementation. First run three
|
||||
offline, version-pinned proofs:
|
||||
|
|
@ -32,12 +33,11 @@ offline, version-pinned proofs:
|
|||
3. translate one synthetic Rayforge operation stream to JCZ/Balor commands and
|
||||
compare it with a BalorMK mock trace.
|
||||
|
||||
If the proofs pass, prefer one of these outcomes in order:
|
||||
|
||||
1. use and contribute to MeerK40t if its full application is adequate;
|
||||
2. implement and upstream a Rayforge JCZ/Balor addon, adapting the narrowest
|
||||
practical layer from BalorMK;
|
||||
3. extract a small maintained controller library shared by either application.
|
||||
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
|
||||
oracle. Adapt only the narrowest necessary implementation after licensing and
|
||||
attribution allow it. Packaged Windows interaction remains an M1 release gate,
|
||||
not a reason to defer the host-architecture decision.
|
||||
|
||||
An independent desktop application requires a later ADR showing concrete,
|
||||
tested gaps in both existing applications.
|
||||
|
|
@ -121,14 +121,16 @@ Subsequent offline evidence:
|
|||
- [M1 no-device acceptance checkpoint](../research/m1-no-device-acceptance.md):
|
||||
the public regression suite and leak guard now form one transport-free gate
|
||||
over addon lifecycle, workflow, layers, recipes, encoding, negative cases,
|
||||
cancellation/recovery and synthetic imports. The packaged Windows GUI and a
|
||||
known-working private project remain external gates.
|
||||
cancellation/recovery and synthetic imports. Packaged Windows interaction
|
||||
remains a release gate.
|
||||
- [Upstream contract and license audit](../research/upstream-contract-and-license-audit.md):
|
||||
both pins and license notices are now machine-verifiable; the documented
|
||||
addon lifecycle is usable, but driver registration and cleanup still rely
|
||||
on an internal registry seam that should be replaced upstream.
|
||||
|
||||
These results satisfy the current model, buffering and no-device integration
|
||||
proofs. They do not yet satisfy the packaged human-interaction or real-project
|
||||
import obligations, so this ADR remains proposed.
|
||||
Three operator-verified private projects subsequently established the
|
||||
project-level `frequency` and `QPulseWidth` serialization needed to implement
|
||||
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
|
||||
|
||||
1. A known-working private galvo `.lbrn2` is still required to establish
|
||||
project-level `QPulseWidth` serialization and omission/default behavior.
|
||||
1. Three known-working private galvo projects establish project-level
|
||||
`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
|
||||
application; the headless UI contract is not a human interaction test.
|
||||
3. `RequireFrameBeforeStart` is observed in a LightBurn device export and
|
||||
|
|
@ -111,8 +112,9 @@ The PirateRay-specific work should remain narrow:
|
|||
framing behavior.
|
||||
4. Machine-specific frequency, pulse-width, timing and correction limits are
|
||||
not established by LightBurn documentation or exported recipe values.
|
||||
5. Material recipes lack a proven contract for provenance, approval and
|
||||
machine/lens/correction compatibility.
|
||||
5. PirateRay recipe metadata now supplies fail-closed provenance, approval and
|
||||
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;
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
entry point also rejects tracked Rayforge modifications and any unexpected
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ optics:
|
|||
active_field_mm:
|
||||
width: 110
|
||||
height: 110
|
||||
status: assumed-pending-physical-verification
|
||||
status: operator-confirmed-on-control-machine
|
||||
other_configurations_observed_mm:
|
||||
- width: 300
|
||||
height: 300
|
||||
|
|
@ -63,3 +63,4 @@ notes:
|
|||
- 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.
|
||||
- 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
|
||||
|
||||
Last updated: 2026-10-21
|
||||
Last updated: 2026-10-24
|
||||
|
||||
## Destination
|
||||
|
||||
|
|
@ -65,8 +65,7 @@ It does **not** yet establish:
|
|||
- which values are controller settings versus laser-source settings;
|
||||
- status, interlock, error, abort, and recovery behavior;
|
||||
- whether an apparently harmless query can move a galvo or arm emission;
|
||||
- how a known-working `.lbrn2` project serializes JPT frequency and
|
||||
`QPulseWidth` settings.
|
||||
- the effective pulse-width default for settings that omit `QPulseWidth`.
|
||||
|
||||
The later LightBurn export collection now establishes version `2.1.03`, a
|
||||
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
|
||||
|
||||
### M0 — Evidence baseline (current)
|
||||
### M0 — Evidence baseline (complete)
|
||||
|
||||
Preserve and hash the installer snapshot, publish sanitized findings, and keep
|
||||
public/private provenance verifiable. Complete M0 with one local collection
|
||||
|
|
@ -90,7 +89,7 @@ Exit criteria:
|
|||
|
||||
- exact LightBurn version, bundle, preferences, screenshots, and working
|
||||
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;
|
||||
- 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.
|
||||
Validate those assets before defining competing application architecture. See
|
||||
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:
|
||||
|
||||
|
|
@ -150,24 +149,21 @@ width, and unsupported Ops. Hardware-specific upper limits remain unknown and
|
|||
are deliberately not guessed.
|
||||
|
||||
[The transport-free JCZ record spike](research/rayforge-jcz-packet-spike.md)
|
||||
packs the same operation stream into deterministic little-endian 12-byte
|
||||
records whose opcodes, values, coordinates and distances match the pinned
|
||||
BalorMK mock evidence. It deliberately omits list buffering and all transport;
|
||||
controller-safe state ordering remains an explicit evidence gap.
|
||||
now extends the deterministic 12-byte records with fixed-size list buffering
|
||||
and explicit state-before-motion ordering. Upload, execution and physical
|
||||
transport remain outside M1.
|
||||
|
||||
[The synthetic LightBurn MOPA import spike](research/rayforge-lightburn-mopa-import-spike.md)
|
||||
confirms that Rayforge preserves geometry, power, speed and passes and retains
|
||||
an observed LightBurn frequency value in raw source metadata. Frequency is not
|
||||
mapped into workflow settings. A later real device export identifies
|
||||
`QPulseWidth` and its nanosecond UI contract, but project serialization remains
|
||||
unknown, so the job still deliberately fails the JCZ encoding gate. A private
|
||||
known-working `.lbrn2` fixture is required before implementing the missing
|
||||
MOPA mapping.
|
||||
confirms that Rayforge preserves geometry, power, speed and passes. Three later
|
||||
operator-verified projects establish project-level `frequency` and
|
||||
`QPulseWidth` fields. The addon now stages complete vector settings into
|
||||
disabled Rayforge steps and rejects them at preflight until units, defaults and
|
||||
machine context are explicitly approved.
|
||||
|
||||
The architecture decision remains proposed until the packaged Windows
|
||||
interaction and known-working private-project gates produce evidence. An
|
||||
independent app requires a documented gap analysis showing why neither
|
||||
existing platform can be extended responsibly.
|
||||
ADR 0002 accepts the Rayforge-addon architecture with BalorMK as the pinned
|
||||
behavioral oracle. Packaged Windows interaction is a release gate, not an open
|
||||
architecture question. An independent app now requires a later ADR with
|
||||
concrete evidence that this accepted route cannot meet product needs.
|
||||
|
||||
Exit criteria: a representative JPT job survives import/planning, MOPA
|
||||
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
|
||||
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
|
||||
device screenshots, preferences folder, photos and operator notes;
|
||||
2. add a sanitized synthetic JCZ `.lbdev` fixture and characterize the exact
|
||||
gaps in Rayforge's device importer;
|
||||
3. implement and test the smallest evidence-backed JCZ profile-import seam,
|
||||
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.
|
||||
1. produce the pinned Windows Rayforge checkpoint on a reviewed external build
|
||||
runner, verify the transferred artifact set and complete the no-device
|
||||
desktop interaction checklist;
|
||||
2. promote complete vector MOPA imports only after recording the explicit unit
|
||||
contract, absent-pulse-width policy and exact machine-context validation.
|
||||
|
||||
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,
|
||||
driver/rollback plan, physical controls, distinct assigned roles and separate
|
||||
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
|
||||
`JCZFiber` fixture with explicit provenance and frame-before-start, binds it to
|
||||
the no-device JCZ driver, preserves process values as raw observations with
|
||||
unit uncertainty, and keeps encoding disabled until the remaining profile and
|
||||
project evidence exists.
|
||||
unit uncertainty, and keeps encoding disabled until the unit/default and exact
|
||||
machine-context review passes.
|
||||
|
||||
Item 4 now covers transport-free fixed-size list buffering and an explicit
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
|
|
@ -43,9 +43,10 @@ Last updated: 2026-10-24
|
|||
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.
|
||||
|
||||
## 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;
|
||||
- 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
|
||||
as an intermediate project workspace and do not generate Support Data.
|
||||
|
||||
Phase 0 remains open until the safety- and interoperability-relevant remainder
|
||||
is hashed, committed, pushed, and represented by sanitized public evidence.
|
||||
|
||||
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.
|
||||
Collect them when preparing an approved M3 hardware session. Do not expand the
|
||||
offline product scope merely to keep Phase 0 open.
|
||||
|
||||
## Offline M1 status
|
||||
|
||||
|
|
@ -112,17 +108,20 @@ evidence for:
|
|||
commit, reviewer, bounded session and explicit safety statements while still
|
||||
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
|
||||
runtime with PyGObject and MSYS2/UCRT64 is available; the repository build
|
||||
entry point fetches pinned source but never installs that runtime;
|
||||
- graphical workflow, import, lens correction and controller protocol
|
||||
behavior remain unproven at the physical boundary;
|
||||
- ADR 0002 remains **Proposed** until those gaps are resolved or rejected by
|
||||
evidence.
|
||||
- three operator-verified projects establish project-level `frequency` and
|
||||
`QPulseWidth` serialization, and the offline bridge stages complete vector
|
||||
settings with output disabled; promotion still requires an explicit unit
|
||||
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
|
||||
output.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,22 @@ if (-not $ArtifactRoot) {
|
|||
$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") `
|
||||
-CacheRoot $CacheRoot `
|
||||
-AllowStagedPirateRayAddon
|
||||
|
|
@ -87,6 +103,10 @@ if (-not (Test-Path -LiteralPath $installer)) {
|
|||
}
|
||||
|
||||
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"
|
||||
$rayforgeLicense = Join-Path $checkout "LICENSE"
|
||||
$normalizedLicense = [IO.File]::ReadAllText($rayforgeLicense).Replace("`r`n", "`n").Replace("`r", "`n")
|
||||
|
|
@ -134,9 +154,9 @@ $result = [ordered]@{
|
|||
bytes = (Get-Item -LiteralPath $archive).Length
|
||||
}
|
||||
installer = [ordered]@{
|
||||
path = Split-Path -Leaf $installer
|
||||
sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $installer).Hash.ToLowerInvariant()
|
||||
bytes = (Get-Item -LiteralPath $installer).Length
|
||||
path = Split-Path -Leaf $artifactInstaller
|
||||
sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $artifactInstaller).Hash.ToLowerInvariant()
|
||||
bytes = (Get-Item -LiteralPath $artifactInstaller).Length
|
||||
}
|
||||
license_files = @(
|
||||
[ordered]@{
|
||||
|
|
@ -152,3 +172,4 @@ $result = [ordered]@{
|
|||
$manifestPath = Join-Path $ArtifactRoot "rayforge-windows-checkpoint.json"
|
||||
$result | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $manifestPath -Encoding utf8
|
||||
Write-Output "Checkpoint manifest: $manifestPath"
|
||||
Write-Output "Transfer the complete artifact directory: $ArtifactRoot"
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ def run(source: Path) -> dict:
|
|||
"evidence": evidence,
|
||||
"remaining_manual_gates": [
|
||||
"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",
|
||||
"device_description": "USBLMCV4",
|
||||
"lens_field_mm": 110,
|
||||
"lens_status": "assumed-pending-physical-verification",
|
||||
"lens_status": "operator-confirmed-on-control-machine",
|
||||
}
|
||||
PROHIBITED_CAPABILITIES = {
|
||||
"persistent_write",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"usb_pid": "9899",
|
||||
"device_description": "USBLMCV4",
|
||||
"lens_field_mm": 110,
|
||||
"lens_status": "assumed-pending-physical-verification"
|
||||
"lens_status": "operator-confirmed-on-control-machine"
|
||||
},
|
||||
"scope": {
|
||||
"milestone": "M3",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class M1AcceptancePipelineTests(unittest.TestCase):
|
|||
source = ACCEPTANCE.read_text(encoding="utf-8")
|
||||
self.assertIn(manifest["commit"], 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("scripts/check_public_repo.py", source)
|
||||
self.assertIn("timeout=120", source)
|
||||
|
|
@ -50,6 +50,10 @@ class M1AcceptancePipelineTests(unittest.TestCase):
|
|||
self.assertIn("GetFullPath", source)
|
||||
self.assertIn("Remove-Item -LiteralPath $resolvedAddonDestination", 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):
|
||||
source = ACCEPTANCE.read_text(encoding="utf-8").lower()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue