Repository navigation
TCube laser: send the setpoint after enabling, zero it before disabling (0.2.4 safety patch) - #68
Merged
Merged
Conversation
Lab decision 0033: main carries X.Y.Z-DEV between releases. TagOnMerge now skips a -DEV version quietly (exit 0, no tag), and CI's version check accepts X.Y.Z-DEV: against a released base the core must rise, against a -DEV base it may stay or rise, never fall, and the X.Y.Z it names must be untagged. The rules live in .github/scripts/versions.py, shared by both workflows, with a selftest CI runs first. Decision 0009's amendment: a merge or squash makes a commit the record never saw, so TagOnMerge tags only when the merged commit's tree is byte-identical to that of a commit with a passing lab/tests status (the commit itself or the merged pull request's head). Otherwise it does not tag, says why, and fails so the re-record is visible. LidkeLab/.github has no shared tag workflow; the header says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ev/output ignored
Admiral's ruling on the lab/tests refusal, as one separate commit:
test/test_groups.toml declares the whole current suite as the group Core,
and dev/output/ is gitignored (lab decision 0028). Two more things
record_tests.jl needs, found running it:
- It reads the run's result from LAB_TEST_SUMMARY, which this suite never
wrote. test/lab_summary.jl wraps the existing top-level testset (two
lines in runtests.jl) and writes that summary; a failing suite still
fails Pkg.test() exactly as before. No test changes.
- It refuses a tree that changes during the run, and Pkg.test() on Julia
1.13 rewrites DAQmx's [sources] entry to {rev = "main", url = ...} on
every run. Committing that form makes the rewrite a no-op. It names the
branch the bare url already tracked, and [sources] is read only in the
root project, so no dependent sees it.
Full decision 0008 adoption waits for the package-standard pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CHANGELOG [0.2.4] names v0.2.3 and earlier as affected by the TCube ignored-setpoint hazard, gives pinned rigs the call-order workaround, and lists the behaviour changes and the release-process changes. Project.toml 0.2.4; README and mc-system-design install pins v0.2.4. rig-causes gains the symptom row, with the potentiometer control source as the other cause of the same symptom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The TLD001 ignores LD_SetLaserSetPoint while its output is off and enables on its stored setpoint, so setpower then light_on ran at a stale value. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CHANGELOG [0.2.4]: UPGRADE WARNING. 0.2.4 applies setpower values that v0.2.3 never applied, and light_on re-sends drive_current while on; rigs check their setpower values, set max_current to the diode rating and the current-limit pot at or below it, and check on hardware before repinning. The enable-window limitation names the pot as the only hardware bound. - Four places that said every merge to main is tagged (CLAUDE.md, README, mc-extend SKILL.md twice) and the CHANGELOG preamble now describe -DEV skips and the untested-tree refusal. - The TLD001 ignore-while-off fact is stated once, on TCubeLaser; the function docstrings refer to it. - light_off logs a failed zero before the disable, so a failing disable cannot swallow it. - Tests: setpoint then disable both failing (status and throw) leave is_on true on the "may still be ON" path; a failed zero is logged even when the disable then fails. - lab_summary.jl drops the unused selection key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Safety patch, 0.2.3 -> 0.2.4. v0.2.3 and every earlier tag are affected.
The hazard
The Thorlabs TLD001 ignores
LD_SetLaserSetPointwhile its output is disabled and, on the nextLD_EnableOutput, runs on whatever setpoint it had stored. v0.2.3'ssetpowersent the setpoint whenever it was called andlight_ononly enabled the output, so the ordinarysetpower(l, x); light_on(l)ran at the stale stored value. Observed on the 642 nm rig's TLD001 (64849775) on 2026-09-28 and recorded in #66; on 2026-09-29 a script in that order drove the diode for about 13 s at the controller's ~160 mA limit.The fix (
TCubeLaserControl)light_onre-checksdrive_currentagainst the ceiling (nothing is sent if it fails), enables, then sends the setpoint. If that setpoint fails it disables the output again and throws.light_offandshutdownzero the setpoint while the output is still on, then disable, so the next enable starts dark. A failed zero is logged; a failed disable still throws.setpowerstill sends on every call (harmless while off, and it covers an output enabled elsewhere); it now says when the current will be applied atlight_on.light_off/shutdown, but anything up to its limit if other software left it there.Behaviour changes, each in the CHANGELOG:
light_onbefore anysetpowernow enables at setpoint 0 with a warning (it used to run at the stored value, which is the hazard); a failed zeroing inlight_offlogs instead of throwing.Decision 0035: this release changes no public signature and no config type. The
TCubeLaserstruct, its fields and both constructors are unchanged, and so are the signatures ofsetpower,light_on,light_offandshutdown. The one new function,zero_setpoint, is internal and unexported.Release process (same PR, per T16)
TagOnMergeskips a-DEVversion quietly, and CI's version check acceptsX.Y.Z-DEV. The rules and their selftest are in.github/scripts/versions.py, shared by both workflows. The selftest (16 cases) passes; thereadpath was checked on Python 3.12.TagOnMergetags only when the merged commit's tree is byte-identical to that of a commit with a passinglab/tests(the commit itself or the merged PR's head); otherwise it fails and says why. The coverage block was dry-run against real squash merges here (TCube laser: refuse out-of-range currents, keep the caller's ceiling, report the drive current #62, Trim CI to the minimum useful signal; make the local suite the gate #61, PI stage: refuse to finish initialize unreferenced #64): each squash commit's tree equalled its PR head's tree.record_tests.jlrefusal: a minimaltest/test_groups.toml(the whole suite as Core),dev/output/gitignored (decision 0028), plus the two further thingsrecord_tests.jlturned out to need. First,test/lab_summary.jlwrites theLAB_TEST_SUMMARYit reads; it wraps the existing top-level testset in two lines and changes no test. Second, DAQmx's[sources]is committed in therev = "main"formPkg.test()rewrites it to, so a run leaves the tree clean.Tests
test/tcube_output_order.jl(8 cases) against a fake controller that models the ignore-while-off behaviour (test/tcube_fake_sdk.jl, extended). On v0.2.3's driver, cases a to g fail (g only on its log assertion); h is a regression guard that also passes on v0.2.3. On this head: 28/28.shutdowncall order now starts with the zeroing setpoint); no other test changed.xvfb-run -a julia --project -e 'using Pkg; Pkg.test()': 987 pass, 8 broken, 0 fail, 0 error, 122 s wall. The head differs from that tree only in the[sources]line and CHANGELOG text. Thelab/testsrecord on this head follows.Not to be merged without Keith's word.
🤖 Generated with Claude Code