Skip to content

Todos

As of: 2026-10-26 · Generated by: /parselogs. From the daily logs, your notes below, a workspace sweep, the KiCad project, all nine git repos, the FCC public record read four ways, Timeline.md and launch-plan.md §13

Rewritten every run. Progress says what is; this says what has to get done.

Tick boxes freely, and write in Notes: — that's the channel back. Notes are preserved verbatim across every run and read at the start of the next one, so an answer written there reaches the next agent. A block ticked Done gets acted on and then removed.

automatable = an agent can get a good first draft done without you; your decisions and anything physical come after. needs human help = an agent does part, you're in the loop throughout. human only = nothing to automate.

❓ = a question waiting on you. ⚠️ = a problem flagged that nobody has acted on yet.

2026-10-25 — no log, but an overnight agent session fixed the watch's escalation latch and left its spec and notes uncommitted. This run checked them against the code (Kconfig patience 20 s, dwell 60 s, give-up 10 min; IMPULSE_BUZZER_DISABLED defaults to y; make passes 320/320) and committed them. v3 is now v0.22. The overnight block at the top of Soon is that session's handoff: the v5 anchor image can't beep, and the 30-second reflash is the first step. The one-way-escalation ❓ has been answered in code, so it now only needs you to agree. There's a new ⚠️ because the nRF anchor has no clock. nrf_firmware is up to 44 uncommitted paths, and the UUID rename is still open. The zip is still served (200, 110,954,965 bytes, 32 days). AUG-14 is due in 6 days, so a soak started today ends 11-08. Today is the eleventh CAD-FILM Sunday.

2026-10-26 — no log and no Notes:, but a second 10-25 session — the afternoon one, with you at the bench — proved the anchor half and found why the last Sunrise Lock was silent: the anchor's clock was 9 h 03 min slow. It left v3 v0.23, two agent-notes.md entries and the overnight block's steps uncommitted. This run checked them against nrf_firmware (all fourteen §6.5 ring looks match ring_looks[] in main.c; NOT_MINE is a LOG_WRN; the worn: still-clock and IMU-read-failed logs exist; DHCP_RESTART_INTERVAL_MS 5000; csmock block exists; build-anchor-cswifi-buzz-v5 has the buzzer compiled in; make passes 320/320) and committed them, plus two small spec fixes of its own. What's open is now four decisions, not a reflash: the anchor's time source, the IMU-spike rule, the buzzer default, and your sign-off on §1.6.1. One bench read is also owed: why board #2 never went unworn. nrf_firmware is still 44 uncommitted paths with the UUID collision in it. The zip is still served (200, 110,954,965 bytes, 33 days). AUG-14 is due in 5 days; a soak started today ends 11-09.

2026-10-24 — nothing moved. No new log, no box ticked, no Notes: written, and no file changed anywhere in the workspace or KiCad since yesterday's run. Only the dates moved. The zip is still served (200, 110,954,965 bytes, 31 days). AUG-14 is due in 7 days, and a soak started today ends 11-07. Next week's Tue–Thu (10-27/28/29) are October's last three AUG-07 slots. Tomorrow is the eleventh CAD-FILM Sunday. The UUID rename is still the cheapest thing that unblocks the most.

2026-10-23 — no log, but a full engineering session on 10-22 afternoon finished what the WATCH_REMOVED blocks have asked for since September. It ran after yesterday's run and left its spec and notes uncommitted, so this run verified and committed them. On v5, a watch left still for 300 s escalated over WiFi and a real WATCH_REMOVED was decoded on the LAN. An anchor in its §1.6.2 fallback dwell beeped on those bytes and stopped on WATCH_WORN, and the anchor now acknowledges each command, so the "alarm keeps sounding after the watch goes back on" coin flip is closed. Board #2's WiFi works after more solder. Two new blocks: a ⚠️ because the new characteristic reuses the deleted Calibration Control UUID, and a ❓ because the watch's WiFi escalation is one-way. nrf_firmware is now at 35 uncommitted paths (host suite 258/258). The zip is still served (200, 110,954,965 bytes, 30 days). If the AUG-14 soak hasn't started, one started today ends 11-06. Today is a CAD-REVIEW Friday.

2026-10-22 — nothing moved, and the 10-21 run failed silently in a new way. The machine was off at 04:00 on both days. The 10-21 catch-up fired at 11:32 and died after 5 s on a TLS certificate error (UNABLE_TO_VERIFY_LEAF_SIGNATURE), not the OAuth expiry seen before. It's noted on the nightly-run block, and it's the fifth separate cause of a silent failure. No new log, no box ticked, no Notes: written, and no project file changed. nrf_firmware is unchanged at 25 uncommitted paths. The zip is still served (200, 110,954,965 bytes, 29 days exposed). If the AUG-14 soak hasn't started, one started today ends 11-05. Today is the third of October's six AUG-07 slots, and the blog still doesn't exist. Tomorrow is a CAD-REVIEW Friday. The SPI block still meets its done when: tick Done and it drops next run.

2026-10-20 — nothing moved, and there was no 10-19 run (the machine was off Monday 01:58 → 21:36). No new log, no box ticked, no Notes: written, and no project file changed. nrf_firmware is unchanged at 25 uncommitted paths. The zip is still served (200, 110,954,965 bytes at 04:00, 27 days exposed). If the AUG-14 soak hasn't started, one started today ends 11-03, three days past the window. Today is the first of October's six Tue–Thu AUG-07 slots, and it's still blocked on the blog. Sunday 10-18 left no trace of filming, which makes ten. The SPI block still meets its done when: tick Done and it drops next run.

2026-10-18 — nothing moved, and there was no 10-17 run (the machine was off Friday 21:48 → Sunday 00:47). No new log, no box ticked, no Notes: written, and no project file changed. nrf_firmware is unchanged at 25 uncommitted paths. The zip is still served (200, 110,954,965 bytes at 04:00, 25 days exposed). The AUG-14 soak's start-by date, 10-17, has passed with no trace of a soak on this machine. If one is running, write its start date in the soak block's Notes:. If not, a soak started today ends 11-01, a day past the window. The SPI block still meets its done when: tick Done and it drops next run. Today is Sunday, CAD-FILM's tenth.

2026-10-16 — nothing moved, second run running. No new log, no box ticked, no Notes: written, and no project file changed. nrf_firmware is unchanged at 25 uncommitted paths. The zip is still served (200, 110,954,965 bytes at 04:00, 23 days exposed). The AUG-14 soak has to start tomorrow, Saturday 10-17, or the milestone can't close on time. The SPI block still meets its done when: tick Done and it drops next run.

2026-10-15 — nothing moved. No new log, no box ticked, no Notes: written, and no project file changed since yesterday's run. nrf_firmware is unchanged at 25 uncommitted paths. The zip is still served (200, 110,954,965 bytes at 04:00, 22 days exposed). The AUG-14 soak has two days left to start (by 10-17), and both V1s are idle. The SPI block meets its done when: tick Done and it drops next run.

2026-10-13 — no log and no Notes:, but a second session did a full day on v5 yesterday, and it found WiFi and the IMU dead on both boards. The WM02C was hand-soldered onto both v5s, a staged solder probe (wm02c probe) and a two-ended pin tester (.bringup --wifi) were written, and the shared SPI bus reads all-ones for the module and the IMU. MOSI, MISO and CLK are now proven continuous; /SPI-SS and /WIFI_INT measured open, and the next step is probing a via, which is physical. New ⚠️ below the v5 block. The KiCad board was re-saved at 20:52 but is content-identical to the 09-14 backup, so no v6 has started; the enclosure STLs and a ImpulseV5.step were re-exported at midday. nrf_firmware is now 13 paths uncommitted. The zip is still served (200, 110,954,965 bytes, 20 days), and the AUG-14 soak has four days left to start.

2026-10-12 — nothing moved. No new log, no box ticked, no Notes: written, and no project file changed since yesterday's run; last night's run worked. The zip is still served (200, 110,954,965 bytes at 04:00, 19 days exposed), the v5 work in nrf_firmware is still uncommitted, and the AUG-14 soak has five days left to start. Sunday 10-11 left no trace of filming, which makes nine.

2026-10-11 — nothing moved, and the nightly run was dead for three nights. The 10-08, 10-09 and 10-10 runs failed on an expired OAuth credential and said nothing, the same failure as 09-06 → 09-09; the ❓ about what an unattended run may do is the place to also decide how it reports failure. No new log, no box ticked, no Notes: written, and no project file changed since 10-07. The zip is still served (200, 110,954,965 bytes at 04:00, 18 days exposed), the v5 work in nrf_firmware is still uncommitted, and the AUG-14 soak has six days left to start. Today is the ninth CAD-FILM Sunday.

2026-10-07 — nothing moved. No new log, no box ticked, no Notes: written, and no file changed anywhere in the workspace or KiCad since yesterday's run. Only the dates moved. The zip is still served (200, 110,954,965 bytes at 04:00), and the v5 work in nrf_firmware is still uncommitted. The three blocks at the top of Soon from 10-06 still stand.

2026-10-06 — the respin is built and it works, and again no log says so. On 10-05 two v5 boards — the board drawn 09-14 — were brought up, given their own board definition, and ranged against each other: 604 s linked, 0 disconnects, 99.9% of procedures good, at 0 dBm, against V1's drop every 25–60 s. The antenna move recovered ~18 dB per board, and the CS link-drop block below is mostly answered by it. Found in agent-notes.md (an uncommitted entry, committed by this run) and verified against the netlist, the new devicetree and the capture. Three things now need you: a new ❓ at the top of Soon asks whether v5 is the board that gets certified, since it carries none of the power-tree fixes; a new ⚠️ lists what v5 broke that nobody has fixed; and the v5 work in nrf_firmware is uncommitted, in the one repo here with a remote. The zip is still served.

2026-09-10 — two working evenings happened, nothing recorded them, and the thing that was supposed to was dead. The nightly run failed silently on 09-06, 09-07 and 09-09 — exit 1 in under a second, an expired OAuth credential — so this is the first run in five days and the ❓ block below about failure notifications has been answered by events rather than by you. In that gap: 2026-09-08, 19:05→19:50, a KiCad board session that generated a JLCPCB fab package and exported two board STEPs, one of which was copied to ~/Downloads; and 2026-09-09, 23:37→23:43, a re-export of all ten enclosure STLs, every one different from print-ready/v2. One of those needs you today and it is not a milestone: the board was never saved — Impulse.kicad_pcb is still dated 08-09 and the only newer copy is a 2.3 MB autosave, with KiCad closed and its lock files stale. Open it, take the recovery, save. New at the top of Soon: that recovery, a ❓ asking whether 09-08 was OCT-10 starting, and a ⚠️ on CAD-FILM, which has now missed four consecutive Sundays — double the threshold Timeline.md set, and past the point where the honest choice is between restarting it and rewriting the rate. Elsewhere: SEP-10, AUG-02 and SEP-12 are ten days overdue, AUG-05 and SEP-11 went overdue on 09-07, and the BM20C grant was checked an eleventh time and still has not issued — so the exposure-category email is still free to send, twenty-nine days on. Progress.md also dropped its machine-uptime and boot-record rows this run; inferring effort from suspend times was disproportionate and it produced one withdrawn escalation already.

2026-09-05 — Friday evening went to KiCad, and this file's sweep could not see it. The PCB project was opened at 18:49, three minutes after the machine came back, and is still open nine hours later — schematic and board both. Nothing was saved, so no block below changes on it, but the finding matters twice over: it is the first project activity in three days, and it happened in ~/Documents/KiCad, which CLAUDE.md deliberately keeps outside ~/Impulse and which this sweep had never covered. Three runs reported "nothing changed" using an instrument that could not see the hardware work. Fixed from now on. A new ❓ at the top of Soon asks what the session was, because an unsaved KiCad session is exactly as perishable as the battery endurance test that got reflashed away. Two corrections travel with it: Friday suspended at 04:54 and did not return until 18:46, so it was not a working day with the machine on, and yesterday's "two consecutive working days" escalation is withdrawn — the honest count is Wednesday and Thursday. SEP-10, AUG-02 and SEP-12 are five days overdue, still under an hour between all three, and the BM20C grant was checked a tenth time and still has not issued (same 36 X8W authorisations, newest still 2026-03-20), so the exposure-category email is still free to send twenty-four days on. One thing genuinely needs deciding today: AUG-05 and SEP-11 are due 09-07, and the only two days left are a CAD-OFF Saturday and a CAD-FILM Sunday. Three commitments, two days. Yesterday's fifth CAD-REVIEW passed without a number, which makes five. The two questions at the top of Soon — how many hours a week this gets, and may I prune this file — are both still waiting on you.

2026-08-31 — the port exists, it runs on the board, and channel sounding is measured. Yesterday was the largest single day of engineering in this workspace's recorded history and, like the day before it, none of it is in a daily log — it was found by sweeping the filesystem. An NCS application was written overnight, booted on Board V1 during the day, and by evening phone_sim was driving its GATT surface unmodified in both roles, a schedule was surviving a reboot, and the §9 gate was quarantining a real loosening over a real wire. Then a channel-sounding campaign: three occlusion walks and a ground-truth line-of-sight sweep that settles the question the whole pivot rests on — ifft is correctly scaled (slope 0.993) and accurate to ±0.20 m after one constant offset. The premise is validated. Spec bumped to v0.11 and six §0.4 rows moved. Two things did not move. The claims fence is still where it was: motor and buzzer now run together, but the pairing §10 cares about is motor and ring, and under Zephyr nobody has yet watched the LEDs light at all — so the gap is one test plus one look. And the power-tree soak still has not started, which now has a new complication: the only working V1 is also the development board. Three new blocks in Soon cover the CS work that is left, and the battery-endurance block below has been rewritten — that number is gone, the board was reflashed. One good outcome: the port's warning that the ESP32 build might share its §9.3 fail-open was checked against the code and disproved — no ESP32 change is needed, no todo opened, reasoning in agent-notes.md. SEP-10, AUG-02 and SEP-12 are due today; the grant was re-checked this morning and still has not issued.

2026-08-30 — Board V1 was brought up last night and it works. Between 19:52 and 01:03 the BM20C ran code for the first time, four module pads were found never to have been soldered, and after rework the LED ring, the vibration motor and the buzzer each work. A battery endurance test is running on the board right now. None of this is in a daily log — it is in ~/Impulse/.bringup/ and an uncommitted agent-notes.md entry, and this run found it by sweeping the filesystem. Three new blocks at the top of Soon, and the first is the important one: AUG-14, BLK-03 and launch-plan.md §10 all turn on the word simultaneously, and nothing has yet driven the ring and the motor at once — so the claims fence has not moved, and it is now one small test away rather than one board order away. The other two are the power-tree soak, which is the reason ten weeks were bought for AUG-14 and which has not started, and the perishable number the battery test is producing as you read this. The SWD block below is ticked closed: an nRF54L15-DK and a TC2030-NL are demonstrably in hand and working, after fourteen runs of "four modules in transit and nothing to flash them with." Tomorrow still carries SEP-10, AUG-02 and SEP-12; the grant was re-checked this morning and still has not issued. CAD-FILM is not raised again — today is the third Sunday, and last night is a real answer to where Saturday went.

2026-08-29 — no new log for eight days, nothing in the workspace changed since yesterday, and this run is the timer rather than you. It fired at 16:42 against an 04:00 trigger, on resume from an overnight suspend. Monday 08-31 is two days out and still carries SEP-10, AUG-02 and SEP-12. The grant was checked a third time and has not issued — but one thing three runs have blurred is now stated properly, here and in agent-notes.md: Monday is SEP-12's due date, not the day the free window shuts. The window shuts when the grant issues, which is a different event, on nobody's calendar, with no notice. Send because it is cheap, not because Monday is a cliff. Tomorrow is the Sunday that decides CAD-FILM. Two other things this run found, both about the machinery rather than the plan: there was no run at all on 08-27 — the laptop was suspended for 48 hours and Persistent= catches up once rather than replaying — and the 08-23 run failed outright and told nobody. Both are in the nightly-run block below. And a flag about this file itself is at the bottom of Soon: these dated per-run notes are now most of why it is 1,500 lines, so this run stopped adding new ones and edited the existing ones in place instead.

2026-08-28 — still no new log, and nothing in this workspace has changed since Wednesday. Seven days now since 08-21, the longest gap since the habit began. The one thing worth a second look was re-checked and hasn't moved: the BM20C grant still has not issued — same 36 authorisations under X8W, and fccid.io/X8WBM20C returns 404 — so the free window SEP-12 depends on is still open, with three days left in the month Fanstel named and the draft sixteen days unsent. Monday 08-31 carries three due dates — SEP-10 (analytics), AUG-02 (the UTM test) and SEP-12 (the Fanstel email) — and together they are under an hour. Today is Friday, so it is a CAD-REVIEW day, and this is the fourth to pass with no subscriber count ever logged. CAD-FILM is not raised again: 08-30 is Sunday, two days out, and it is the date that decides whether two unrecorded Sundays are a fortnight or a trend.

2026-08-26 — no new log, nothing in the workspace changed, and the machine was off for all of Tuesday. This is the 04:00 timer, fired at 11:07 — four seconds after a cold boot. So nothing below moved on evidence from you. What is new came from outside this workspace: the BM20C's FCC grant was checked against the public record for the first time in the project's life, and it has not issued — no grant for a BM20C exists from any grantee. Read the right way round that is good news, because it is exactly the condition drafts/fanstel-exposure-category.md says its own value depends on: the free window is open, verified, with five days left in the month Fanstel named. Two smaller things fell out of the same check: your Aug-8th note was right — the BM15C really is certified (X8WBM15C, granted 2025-01-07), and Fanstel has not put a new authorisation of any kind on the record since 2026-03-20, five months, against a 2025 cadence of one every six to eight weeks. CAD-FILM's flag was raised Monday and is not raised again here — no Sunday has passed since; 08-30 is the next one.**

2026-08-24 — no new log since 08-21, nothing in the workspace changed, and two dates passed. This is the 04:00 timer run, fired at 10:04 on resume. Nothing below moved on new evidence; what moved is the calendar. CAD-FILM's flag Sunday came and went — 08-16 and 08-23 are both unrecorded, so that block is now the flag Timeline.md asked for rather than a question about it. It is not a verdict on your weekend, and it says so: filming leaves no trace here. What changed is that the excuse did — the machine was awake about six hours on Sunday, where 08-16 fell inside a four-day power-off. AUG-06 opened today into 0 edited clips and no channel recorded anywhere. And AUG-13's "ask the lab within 2 weeks" expired yesterday, with the Steve draft unsent and twelve days old. Seven days left on SEP-10 and SEP-12 — and SEP-12's week belongs to Fanstel, not to you.

2026-08-22 — the plan change is filed, committed, and this file is now dated against it. Thursday night's rewrite of Timeline.md and five marketing documents was never committed; it has been, along with the 2026-08-21 log itself. Progress.md is rewritten against the new plan rather than carrying a warning about it. Nothing in this file is overdue any more — every August window moved into September, and the block titles that said "closes tomorrow" or "overdue" have been corrected rather than left to read as stale panic. Two new blocks at the top of Soon, and they are the same argument from two directions: GATE-TRAJECTORY wants 600 emails by 30 November and nothing is measuring anything, and the cadence rates in the new plan were derived from "reduced hours" without anyone knowing what that number is. CAD-FILM's flag Sunday is tomorrow.

2026-08-21, evening — the timeline moved four months, by decision. The Kickstarter goes from early November 2026 to 1 March 2027 and the ship date from March to September 2027 (communicated as October), because school started and the day job ramped up. Timeline.md is rewritten and carries the reasoning, the old→new milestone ID mapping, the revised cadence rates, and a new $2–5k advertising budget (BUD-ADS). This changes the deadline on most blocks below and the substance of a few — the ones it changes are annotated with a 2026-08-21 (timeline change) note in place. Three headlines: AUG-07's Tuesday panic is gone (Show HN moves to October, and the blog is now a September milestone rather than a four-day scramble); the deposit mechanism got a new problem (a December deposit against a September 2027 ship is a nine-month hold); and two Fanstel items got more urgent, not less, because they are somebody else's calendar and are explicitly carved out of the "certify after the campaign" decision.

2026-08-21 — this machine was off from Monday morning until nine minutes ago, which is most of why there has been no log since 08-12. It suspended Monday at 09:31 and came back tonight as a cold boot — four and a half days, a new boot ID. Across the whole of Week 2 it has been awake for about an hour. So nothing below moved on new evidence, and the three Week-2 milestones closing tomorrow are untouched because the machine they live on was off, not because they were avoided. What this run added is the block at the top of Soon: AUG-07 opens Sunday, its posting slot is Tuesday, and there is no blog to post to. The nightly-run block is corrected too — WakeSystem=true would not have fired a single run across this gap.

2026-08-11 — four blocks answered and dropped: the regulator, Kit's double opt-in, the WiFi decision, and the 9pm edit. All four are filed; see Progress.md's Changes filed elsewhere. Two of the four left something behind, and both are now blocks of their own at the top of Soon — the battery arithmetic still doesn't reach 5:30pm, and the regulator's three diagnostic questions were closed by the repair rather than answered (agent-notes.md, 2026-08-11).

2026-08-12, 04:00 — this file was rebuilt by the nightly timer, not by you. First successful unattended run after four failed nights. No new log since 2026-08-11, so nothing below changed on the strength of new information; what the run added was a verification pass that found the V1 motor pin still wrong in WatchFIrmware/README.md and launch-plan.md §13 (both corrected — see Progress.md). The /parselogs block below flips from "it's broken" to a question about what a 4am agent may touch. One new block: the website's only copy is your working tree.

2026-08-17 — Week 1 is closed, Week 2 opened yesterday, and no log has been written for five days. Nothing in the workspace has changed since the 08-14 run either, so nothing below moved on new evidence. What this run did was check the footage, and the answer is the new block at the top of Soon: no video file exists anywhere on this machine, and no edit has been started — no project file of any format, and Shotcut's config untouched since 2026-07-12. The audio has sat finished since 2026-08-09. So AUG-01's takes exist in one copy on a camera, and AUG-04 is inside its window with nothing begun. AUG-03's window closed on Saturday; its block below is rewritten for that. CAD-FILM's first Sunday has passed unrecorded — 2026-08-23 is the one that trips the two-week flag.**

2026-08-14 — no log since 2026-08-12, and nothing in the workspace has changed since yesterday's run. Not a file, not a repo, not a note here. So nothing below moved on new evidence; what this run did instead was check two things about Sunday, which is when AUG-04, AUG-05 and AUG-06 all open and three cadences start at once. Both checks became new blocks at the top of Soon: nothing written down records a social account or a Hackaday.io project page, and the live site has no traffic analytics at all. A third new block is the writing half of AUG-05 — the most automatable thing on this list. AUG-03 closes tomorrow; the first CAD-REVIEW is today.

2026-08-13 — an unattended run, and it fired at 13:04 rather than 04:00 (see the /parselogs block). The 2026-08-12 log lists goals only — studio, location and action shots — and no log records whether they happened, so nothing below moved on new evidence. What this run added is verification: the launch video's closing CTA sends people to a pre-order that no longer exists (folded into the ship-date block, which turns out to be the same line), the "can't snooze" claim is already live on the website in two places nobody had counted, and donningGraceS has no device-side bound at all — the spec says so in as many words. Because the question of what an unattended run may touch is still unanswered below, this run edited nothing outside vault/.

2026-08-12 — the week-1 filming block is gone: AUG-01 is done. Five vertical and two landscape Sunrise Lock takes plus four Phone Dock takes, from the 2026-08-11 log. What was left of that block is now AUG-03 alone, below. You answered your own ❓ overnight by pulling the X8WBC15 exhibits — that question is closed inside the grant block and the answer is mostly good. Two new blocks: the wornness argument you asked for, and three assets carrying three different ship dates.

2026-10-05 — Phase 1 closed on 3 of 13, Phase 2 is five days old, and nothing has moved since 09-30. :8080/vaultFrozen.zip still answered 200 with the full 110,954,965 bytes this morning, which makes about ten days on the LAN. There's no log (45 days), no commit (22), no KiCad save (21), no tick and no Notes: reply, and the live site still ships index-fqOs4KOK.js. Both nightly runs since 09-30 failed (10-01 and 10-03, exit 1 on network errors reaching the API), so this is the first run in five days. Yesterday was CAD-FILM's eighth missed Sunday and Friday the tenth CAD-REVIEW without a number. AUG-07's first Tue–Thu slots are tomorrow through Thursday, and there's still no blog to post from.

2026-09-30 — Phase 1 closes today, and nothing has moved since Monday. :8080/vaultFrozen.zip still answered 200 with the full 110,954,965 bytes at 10:14, so it has now been served for about five days. No log (40 days), no commit (17), no KiCad save (16), no tick and no Notes: reply, and the live site still ships index-fqOs4KOK.js. SEP-13, AUG-12 and AUG-03 are all due today. Tomorrow Phase 2 opens and AUG-07, the first Show HN, comes into its month with no blog to link from.

2026-09-28 — still nothing, and the archive is still on the LAN. :8080/vaultFrozen.zip answered 200 with the full 110,954,965 bytes at 10:52. It has been served for about 70 hours since this file first saw it. No log (38 days), no commit (15), no KiCad save (14), no tick and no Notes: reply. The site is still undeployed, and yesterday went by with no footage on disk, so that is CAD-FILM's seventh missed Sunday. Phase 1 closes Wednesday, two days out, and both remaining days are weekdays. That means the IRS online EIN service is open for SEP-13's prerequisite today.

2026-09-26 — nothing changed, and the archive is still on the LAN. :8080/vaultFrozen.zip answered 200 with the full 110,954,965 bytes at 15:52. No log (36 days), no commit (13), no KiCad save (12), no tick and no Notes: reply, and the site is still undeployed. Phase 1 closes Wednesday, four days out. Today is a CAD-OFF Saturday and tomorrow is CAD-FILM's seventh Sunday.

2026-09-25 — the archive is on the LAN now. vault-site restarted at login today, 12:37:25, rebuilt its link farm, and linked vaultFrozen.zip with it. http://10.201.162.201:8080/vaultFrozen.zip answered 200 and 110,954,965 bytes to this run. The server listens on 0.0.0.0, and the archive holds .obsidian/plugins/calendar/data.json along with the rest of .obsidian/. Yesterday's block predicted exactly this. It is retitled and still at the top of Soon, and it is still one mv. This run didn't move your file or stop your service. Nothing else changed in the 32 hours since the last run. There is no log (35 days), no firmware commit (12), no KiCad save (11), no tick and no Notes: reply, and the site is still undeployed (live bundle index-fqOs4KOK.js). Phase 1 closes in five days. Today is Friday, the ninth CAD-REVIEW, and Sunday is CAD-FILM's seventh.

2026-09-24 — you formed a company last night, and nothing records it but a receipt. Impulse Gear LLC was organised in Virginia effective 2026-09-23; within the hour the five legal pages were rewritten to name it and the site was rebuilt — but not deployed, so impulsestore.net still names the seller as "IMPULSE HARDWARE DAVID ALLAN MACPHERSON." Two new blocks at the top of Soon: the LLC's follow-through (deploy, EIN, and putting the FCC grantee code and the trademark in the company's name), and a vaultFrozen.zip in the vault root — a 111 MB full archive including .obsidian/'s OAuth tokens, which tonight's git add -A would have committed. This run gitignored it; it still needs to leave the vault before vault-site next restarts and serves it on the LAN. Still no log (34 days), no firmware commit (11), no box ticked and no Notes: reply.

2026-09-22 — AUG-04 passed its date on Sunday with the question unanswered, so it is recorded as missed rather than moved. Timeline.md permits a date change when it is a decision and forbids one that hides slippage; after the date, only the second reading is available. The block below is retitled to say so, and the residual is unchanged and still minutes: get the eleven takes off the camera. Nothing in this workspace has changed in eight days (last write Monday 09-14 22:52), no log in 32, no commit in 9, no box ticked and no Notes: reply in two. Phase 1 closes in eight days with three of thirteen done and four of the six overdue items under an hour each — the analytics snippet, the UTM test, the Hackaday.io page and the blog route close four of them. Sunday was CAD-FILM's sixth consecutive miss, triple Timeline.md's failure threshold. The one thing that moved is a reading, and it is good news: the BM20C's grant note was pulled verbatim and it carries "except in accordance with FCC multi-transmitter product procedures", so the watch breaks one condition on each of two modules, not two conditions on each — the exposure category is the whole of it, and co-location of the two radios on one board is permitted under both grants. That is the difference between a narrow permissive change and a scope a lab prices at §12.5's $35k. Filed to launch-plan.md §5, Timeline.md BLK-15 and Concepts/Module Grant Conditions.md §0/§6. Two things came with it and are new steps on the grant block: the grant's MPE report and model difference letter are downloadable and are the first two documents AUG-12's labs will ask for, and Fanstel's own page now states "Availability: Production 09/2026" — a vendor line, not a confirmed ship date, but the first plausible answer BLK-15's remaining half has had, and far easier to ask them to confirm than to request from scratch. The primary source is still unreachable: apps.fcc.gov and fccid.io returned 403 again, by two independent network paths.

2026-09-20 — the BM20C's FCC grant issued on 2026-09-11, and it issued mobile. Nine days ago, while the email that existed to prevent exactly this sat unsent in drafts/. SEP-12 is therefore expired, not overdue: scoping an open filing cost Fanstel a paragraph, and the same question now costs a Class II permissive change only they can file. Two corrections travel with it. The grant half of BLK-15 is discharged — X8WBM20C exists, which is real good news and was MAR-05's precondition. And the watch now breaks a 20 cm grant condition on both modules, so SEP-13 is a two-module negotiation and "the BLE-only fallback is SAR-excluded by calculation" must from now on name its module — true of the BC15C, false of the BM20C. Why it went nine days unseen matters as much as the finding: the eleven grantee-code checks since 08-26 all used fccid.io, which now returns 403 to this machine, as does the FCC's own search — the instrument stopped working at about the moment the event happened. New block at the top of Soon; full record in docs/agent-notes.md. AUG-04 is due today and nothing has changed since Monday 09-14 22:52 — no log (30 days), no tick, no note, no commit, no KiCad save; today is also CAD-FILM's sixth Sunday. One thing was done rather than flagged for an eighth time: crash_ram_20260912.bin is now copied into files/nrf-crash/, so a pristine build can no longer destroy it.

2026-09-19 — AUG-04 is due tomorrow, and today is the last day on which cutting it is still arithmetically possible. Nothing has changed since Monday 09-14 22:52: no log (29 days), no Notes: reply, no tick, no commit, no KiCad save. This run added no new block — yesterday's ❓ is exactly the live question, so it was updated in place instead, and a sixth unread question would be noise. What changed is only the calendar: offload → audio edit → timeline does not fit into Sunday alone, so option 1 starts today or not at all, while option 2 — writing a date you believe into a log — stays available and costs one line. Today is a CAD-OFF Saturday and tomorrow is CAD-FILM's sixth Sunday, so the weekend carries three commitments and can hold one; saying which one doesn't happen is the whole ask. One thing re-verified and worth a single command: crash_ram_20260912.bin is still the only copy and still inside build-watch-cs-buzz/, where a pristine build destroys it. SEP-10, AUG-02 and SEP-12 are nineteen days overdue, AUG-05 and SEP-11 twelve; AUG-03 and SEP-13 both close in eleven.

2026-09-18 — four days now with no change of any kind, and AUG-04 is due the day after tomorrow. Nothing in ~/Impulse has been written since Monday 09-14 22:52 except the last run's own output. No log (28 days), no Notes: reply, no tick, no commit, no KiCad save. The three questions from 09-15 are still open and so are the two from before them. One new block at the top of Soon, and it is the only thing this run added: AUG-04 cannot be hit from where the assets are, so the choice is now between cutting something this weekend and moving the date on purpose — and it has to be made before Sunday rather than discovered on it. That block is a ❓ because it is your call and nobody else's. Sunday also carries CAD-FILM's sixth Sunday; today, Friday, is the seventh CAD-REVIEW to pass without a number. SEP-10, AUG-02 and SEP-12 are eighteen days overdue, AUG-05 and SEP-11 eleven; AUG-03 and SEP-13 both close in twelve.

2026-09-16 — nothing in this workspace has changed since Monday 22:52, and no block below is new. No log, no note, no commit, no KiCad save. Yesterday's three questions are all still unanswered — is the same-edge placement deliberate, are the power-tree fixes still coming in this spin, was anything ordered on 09-14 — and each is one line in a Notes: box. Re-asking them in new blocks would just be noise, so this run added none. The one thing the calendar changed is AUG-04: four days, and the footage is still not on this machine (eighth verification, in the block below). Sunday carries both that deadline and CAD-FILM's sixth Sunday, which is a collision worth deciding on Thursday rather than Sunday morning. SEP-10, AUG-02 and SEP-12 are sixteen days overdue; AUG-05 and SEP-11 nine.

2026-09-15 — no new log and no new notes, but Monday brought a 13-hour respin session and an evening rewrite of the product overview, neither of them logged. The board: V1 archived as ImpulseNRFV4, outline cut to 34.4 × 42 mm, BM20C moved, six signals re-pinned, saved, fab package regenerated. OCT-10 has started eleven weeks early. It puts both modules on the same edge, where FCC Respin.md asked for opposite edges, and the power-tree fixes aren't in it yet. The overview: mostly sound framing, committed as written. But §3.2 now says phone-distance fails closed, which contradicts both firmwares, the app spec and the live site FAQ. Two new blocks at the top of Soon. SEP-10, AUG-02 and SEP-12 are fifteen days overdue, and AUG-04 is due Sunday.

2026-09-14 — no new log and no new note, but two days of engineering landed, and one of them took back a claim this file and CLAUDE.md both repeated. Across 09-12 and 09-13 the port ran real Sunrise Locks, including one pushed from the real phone app, and fixed eight defects to get there. The watch was verified enforcing a getAway end to end at 01:25–01:45 on 09-13 while you walked in and out. The correction: BLE and WiFi do not coexist. With both radios on, both died within 5–13 minutes, repeatedly, so testing now runs BLE-only builds. That leaves WATCH_REMOVED without a transport that works alongside ranging. Spec v3 is now v0.18 and CLAUDE.md is corrected. You also made a threat-model decision: a lost ranging link is AWAY after 10 s, which accepts shielding as a getAway bypass. It is recorded in the spec as yours, and nothing here reopens it. Four new blocks at the top of Soon. The coexistence problem comes first. Second is a SoftDevice Controller assert that needs a Nordic case, and its only RAM snapshot sits in a build directory that a pristine build deletes. CAD-FILM's fifth Sunday went to that testing. SEP-10, AUG-02 and SEP-12 are now fourteen days overdue, and AUG-04, the founder video, is due Sunday with nothing edited.

2026-09-12 — the product loop closed, and two things this file worried about were already fixed. Two Board V1s range against each other (ifft sd 0.02–0.04 m, and 172 estimates in 60 s driving a real cond_met), WiFi is up on both boards, and the WATCH_REMOVED path is built and decoded off the wire. Four blocks are gone as done: the KiCad board was saved at 22:46 last night, nrf_firmware/ is a git repo with a remote and a pushed commit, the reflector has been ranged against, and the second Board V1 exists and works. Two corrections are owed and are in Progress.md: yesterday's run reported "0 board-to-board procedures" and "1 working board" when cs_tuning_plan.md — which it cited — had already said otherwise. The practical consequence is one line: the power-tree soak has no hardware excuse left, because the soak board and the development board no longer have to be the same board. Three new blocks in Soon: the initiator ranges the wrong anchor (a bypass, not a tuning error), the V1 anchor has no cell fitted so §7's holdover is unmet rather than unmeasured, and the CS calibration rests on a single point. SEP-10, AUG-02 and SEP-12 are twelve days overdue, AUG-05 and SEP-11 five, and tomorrow is CAD-FILM's fifth Sunday.**

2026-09-11 — the claims fence moved. The ring and the motor were driven at once on 2026-09-10 with a human watching, which was the stated condition for BLK-03 and for launch-plan.md §10. That block is gone from this file because it is done and filed — §10, §12.2, §13, Timeline.md, CLAUDE.md and the spec all moved with it. The same session found seven defects, two of which composed into a remote bypass of enforcement, and brought the anchor's reflector up. Three new blocks: nothing has ranged against that reflector, charger_detect is dead on this board, and the nRF firmware is still versioned nowhere. AUG-14's remaining half is the power-tree soak, which has still not started.*


Soon

❓ 2026-10-25: the anchor beeped and the whole chain ran — now four decisions and one RTT read

needs human help · raised 2026-10-25 · v3 v0.22 §1.6.1, §4.5 · from the overnight agent run (report in the chat; reasoning in docs/agent-notes.md 2026-10-25)

What changed overnight. The escalation latch, the cold-open-can't-use-BLE bug, the getAway self-blinding bypass (abstain_run=6 failsafe=1 cond_met=1 beside the anchor), the watch holding WiFi all window, and a 27 s DHCP are fixed in nrf_firmware (uncommitted, like everything else there). WiFi now refuses to associate while BLE is on the air. A --no-motor build option exists because the motor shakes the SWD wire off. Host suite 258 → 320 checks.

⚠️ The likeliest reasons you heard nothing on the last Sunrise Lock are on the anchor, not the watch. (1) The anchor image cannot beep: build-anchor-cswifi-v5 has CONFIG_IMPULSE_BUZZER_DISABLED=y (that option defaults to y), there is no -buzz v5 anchor build in the tree, and agent-notes.md 2026-10-24 records board #3 running anchor-cswifi. (2) The anchor has no clock source. No SNTP, no time characteristic, so it checks windows against whatever RTT impulse time last set. Today, with a real schedule accepted, it never acted as if the window was open. The watch side of the real-anchor seam did run on hardware today: a real schedule naming 75b2aeb2…, window opens unworn, WATCH_REMOVED delivered over BLE 1.9 s later.

2026-10-26 — the 30-second step was done that afternoon, and the whole chain was heard. With a real schedule on both boards, the watch went unworn and sent WATCH_REMOVED over BLE. The anchor beeped. The watch went worn, sent WATCH_WORN, and the beep stopped (v3 v0.23). That reads as this block's done when, with one caveat: the worn edges came from the wornset bench override, not the IMU. So Done is yours to tick. What's left below is four ❓s and one bench read. The clock question is the one that matters: until it's answered, every anchor reboot puts back the failure you heard as silence.

Steps - [x] Done 2026-10-25 14:45, with you listening. The anchor clock was 9 h 03 min slow: that was the silent Sunrise Lock. Board #3 now runs anchor-cswifi-buzz with its clock set. Fed a real WATCH_REMOVED over UDP during its own fallback dwell, it ACKed 00, beeped, and stopped on WATCH_WORN. Original step, kept for reference: When the SWD wire is on the anchor (board #3, FFE2F93F D56E79CE): first ./shell.sh "impulse status" and read the clock: line. If it is wrong, that was the silent Sunrise Lock. Then cd ~/Impulse/ImpulseFirmware/nrf_firmware && ./build.sh anchor --cs --wifi --buzzer --board v5 && ./flash.sh anchor-cswifi-buzz --board v5, then ./shell.sh "impulse time $(date -u +%s) -240", then ./impulse-phone anchor identify from phone_sim. It should beep. - [ ] ❓ How should the anchor learn the time? Options: (a) an anchor Time characteristic in the watch's §8.11 format, pushed by the app alongside every schedule push. That's the cheapest, but it adds one characteristic to the four-way GATT contract. (b) SNTP during WiFi. That's circular, because the anchor only goes to WiFi inside a window, which needs the clock. (c) Take time from the watch over the ranging link (the watch is already the root of trust for time). I'd take (a), with (c) as a later hardening. Nothing is built; it changes the app contract, so it's your call. - [x] Whole chain heard, 15:13–15:15: watch unworn → REMOVED over BLE → anchor beeped → watch worn → WORN → beep stopped (worn driven by the bench override). - [ ] ❓ The cause of the item below has been found: isolated one-sample IMU spikes (421–1072 mm/s², threshold 400) every few minutes on a still desk, on both boards. Each one restarts the 300 s clock. Pick: (a) a restart needs two over-threshold samples in a row. A real pickup counts as worn ≤1 s later; the risk is a sleeping wrist that only twitches once in a while reading unworn. (b) Raise IMPULSE_WORN_IMU_MOTION_MMS2 (e.g. 800). I'd take (a). - [ ] ⚠️ New: board #2 (the watch) never went unworn on its own. It sat untouched for 7+ min and still read worn=1, while the anchor on the same desk went unworn at 300 s. So the real 14:22 window ran as "worn, near, alarming", silently, and no REMOVED was ever sent. Next step with the wire on the watch: ./rtt.sh 60 and read worn_motion= on the alive lines. Above the threshold means a noisy IMU or threshold; no alive worn updates or an IMU error means the read is failing. - [ ] Then restore the watch's motor and buzzer (it is on a silent, still overnight image): wire back on board #2 (FECC0772 A9478432), ./build.sh watch --cs --wifi --buzzer --board v5 && ./flash.sh watch-cswifi-buzz --board v5 - [ ] ❓ Decide whether IMPULSE_BUZZER_DISABLED should keep defaulting to y. It is the reason a v5 anchor has never been able to beep, and nothing at runtime says so except one boot banner nobody reads over BLE. Options: (a) keep y and make build.sh anchor refuse without --buzzer or --silent; (b) default n like the motor. I'd take (a). - [ ] Commit nrf_firmware when you're happy (I don't commit there).

  • In Progress
  • Done

Done when: an anchor built with the buzzer beeps on a real WATCH_REMOVED from a real schedule, and stops on WATCH_WORN, with a human listening.

Notes:

⚠️ The nRF anchor has no clock — it was 9 h slow, and that was the silent Sunrise Lock

needs human help · raised 2026-10-25 · v3 §0.4 chunk F · §4.6.1 NOT_MINE · from the overnight session's spec edit, verified against the code

The anchor accepts a WATCH_REMOVED only if its own schedule has that event open right now. To know what "right now" is, it needs a clock. The nRF anchor has no SNTP (nothing in src/ or any .conf) and no time characteristic in ble_anchor.c. Its wall clock is whatever impulse time last set over RTT, plus drift. So an anchor that has been unplugged, or has drifted out of the window, answers NOT_MINE to a real removal and stays silent. That's fail-open on the one path that's meant to make leaving the watch behind cost something. The ESP32 anchor got its time over WiFi. Here, nothing replaces that.

This is now one of two things between the watch and a real anchor beep, and neither is watch firmware. The other is the buzzer build in the block above.

2026-10-26 — proven, not inferred. With SWD on the anchor on 10-25, impulse status read restored_from_flash=1 and a clock 9 h 03 min slow. The restore uses the last saved value, so every minute unpowered becomes clock error. With the clock set by hand it beeped (v3 v0.23, agent-notes.md 2026-10-25). The decision is the ❓ step in the block above, which has three options and a recommendation, (a) an app-pushed time characteristic. Answer it there and this block becomes buildable. It's relabelled needs human help because (a) changes the four-way GATT contract.

Steps - [ ] Decide the source: SNTP when the anchor is on WiFi, a time write from the app or watch over BLE, or both - [ ] Specify it in v3 (§4 anchor), then build it

  • In Progress
  • Done

Done when: an anchor that has been power-cycled with no RTT attached accepts a real WATCH_REMOVED inside its window.

Notes:

⚠️ vaultFrozen.zip is being served on the LAN right now — move it out of the vault

human only · raised 2026-09-24 · escalated 2026-09-25 · still served 2026-10-06 · from the vault's git status and a request to :8080

  • In Progress
  • Done

2026-09-25: this is no longer hypothetical. The impulse-vault service restarted at 12:37:25 today, sync-farm.sh linked vault-site/docs/vaultFrozen.zip, and GET :8080/vaultFrozen.zip returned 200, the full 110,954,965 bytes. MkDocs listens on 0.0.0.0, so anyone on this network can download it until it moves. Once the zip leaves vault/, the link dangles and the download stops working. No restart is needed, though restarting also removes the stale link. This run didn't touch the file or the service, because the file is yours and stopping the service takes the specs off your phone too. systemctl --user stop impulse-vault is the stopgap if you can't move the zip yet.

A 111 MB archive of the whole vault appeared in vault/ at 2026-09-23 21:25, and it contains 705 files under .obsidian/ — including the Google Calendar OAuth tokens that CLAUDE.md and vault/.gitignore both exist to exclude — plus the vault's own .git/. Presumably a deliberate snapshot; a sensible thing to have, in the wrong place. Two things would have published it without anyone choosing to:

  • The nightly commit. /parselogs ends with git add -A, which would have committed the archive — tokens and all — into the vault's history, from which removing it is a history rewrite. This run added vaultFrozen.zip to vault/.gitignore, so that one is closed.
  • vault-site, on its next start. sync-farm.sh symlinks every top-level vault entry into the served tree, and it last ran at 20:49 — 36 minutes before the zip existed, which is the only reason it isn't on the LAN now. The next login or service restart links it, and MkDocs serves non-markdown files as downloads: http://<this machine>:8080/vaultFrozen.zip. This run did not edit sync-farm.sh — it is outside the vault and it is code.

Steps - [ ] Move the zip outside ~/Impulse (or anywhere outside vault/) — e.g. mv ~/Impulse/vault/vaultFrozen.zip ~/ - [ ] Optionally remove the vaultFrozen.zip line from vault/.gitignore afterwards — harmless either way - [ ] Optionally have sync-farm.sh skip anything that isn't a directory or .md, so the next archive can't reach the LAN either

Done when: no file containing .obsidian/ sits anywhere sync-farm.sh or git add -A can reach.

Notes:

❓ Is v5 the board that gets certified, or is there a v6? — it carries none of the power-tree fixes

human only · raised 2026-10-06 · OCT-10 AUG-14 SHIP-03 BLK-03 · from agent-notes.md 2026-10-05 and the 09-14 netlist diff

v5 is built, it works, and its radio numbers are the best this project has measured. But Timeline.md defines OCT-10 as "the board that gets certified", carrying the antenna keepout and the power tree, and launch-plan.md §12.6 calls certifying the wrong revision a fatal mistake. On v5:

  • Antennas: both overhang, ~18 dB per board recovered. Both are on the same edge, ~13.5 mm apart in body, where FCC Respin.md asked for opposite edges and ~30 mm.
  • Power tree: not in it. No servo-rail switch or fuse, and no VBUS input capacitor or Schottky. That is the failure behind three of five dead prototypes, and the one that flattened a pack on 2026-08-10.

Two readings, and they lead to different plans. (a) v5 is a radio respin and v6 carries the power tree and is the certified board. Then OCT-10 stays open until v6 is ordered, and its 11-30 date is tight but real. (b) v5 is the certified board and the power tree is accepted or deferred. Then that acceptance needs writing down, because §12.6 and BLK-03's second clause both say otherwise.

What I'll do without an answer: report OCT-10 as ordered and built, with done when not met. I won't mark it done or move any date.

2026-10-14 — the SPI fault adds nothing to this. It was solder, not a via (agent-notes.md, 10-13), so there's no fab defect pushing toward a v6. But v0.20 adds an input in the other direction. v5's IR worn sensor is abandoned in firmware because the receiver moved and the enclosure reflects 75–90 mV against a 200 mV threshold. If the certified board should detect a wrist rather than a still watch (§6.4 says it should), the optics fix is a v6 item alongside the power tree.

Steps - [ ] One line in Notes:: (a) or (b) - [ ] If (a): the power-tree items and the separation question go into a v6 drawing - [ ] If (b): one sentence on why the power tree can wait, so BLK-03 can say so

  • In Progress
  • Done

Done when: the notes say which board is certified, and OCT-10's status follows from it.

Notes:

⚠️ v5 arrived and three things haven't caught up — and the v5 port work isn't committed

needs human help · raised 2026-10-06 · v3 §2, chunks B, G, §5.5.1 · AUG-14 · from agent-notes.md 2026-10-05, verified against the netlist and nrf_firmware

Board v5 has its own board definition and the pin map checks out. I re-exported the netlist and read every moved pad on U7, and all six agree with impulse_v5's devicetree and .bringup/README.md. v3 §2 now carries the delta (v0.19). What isn't fixed:

  1. The SAADC channels are V1's. CONFIG_IMPULSE_ADC_CH_BATTERY and _IR (AIN0/AIN1) read unrelated pins on v5. Battery is report-only, so the cost there is a wrong percentage. The IR one means worn never asserts and WATCH_REMOVED can't fire. The fix is one impulse adc sweep on a v5 and two Kconfig values.
  2. The CS distance offset doesn't transfer. v5 reads 0.25–0.55 m long. See the calibration block; its sweep is now blocking.
  3. The firmware still defaults to --board v1. That's deliberate while the V1s run the product firmware, but it means a bare ./build.sh watch flashed to a v5 is inert on six signals. flash.sh now refuses an unregistered die, which covers it.
  4. None of this is committed. nrf_firmware has six modified files (build.sh, flash.sh, four HAL sources) and two untracked paths (boards/impulse/impulse_v5/, boards/dies.tsv), and the last commit is d78517c from 09-13. It's the only repo in this workspace with a remote, so this is also the only work here that could be pushed off this machine, and it hasn't been. I don't commit outside the vault.

Steps - [ ] Commit and push the v5 board definition and the flash.sh die guard in nrf_firmware - [ ] Sweep impulse adc on a v5; set the two channel indices (per-board, if V1 must keep its own) - [ ] Run the CS LOS sweep on v5 (calibration block below) - [ ] Decide when the default board becomes v5, and rewrite v3 §2 for it at the same time

  • In Progress
  • Done

2026-10-23 — item 4 is now 35 paths (26 modified, 9 untracked), 40 days after d78517c. The 10-22 session added the §4.6.1 ack, alarm masking for the worn detector, impulse wipe and ANCHOR_LAST_IP. The host suite passes 258/258, so it's committable. Fix the UUID collision in the block below first, because pushing it publishes a reused UUID.

2026-10-14 — item 1 is half superseded. On v5 the IR pair is abandoned, and worn detect is now IMU stillness (v3 §6.4, built 10-13, verified in Kconfig). So WATCH_REMOVED can fire on v5 again, but see the wornness-gate block for what that costs. The battery channel is still V1's. Item 4 grew again: 25 uncommitted paths (16 modified, 9 untracked), now including the radio-arbitration policy and both worn detectors. The host suite passes 248/248 on that tree, so it's in a committable state.

2026-10-13 — item 4 grew. The 10-12 WiFi bring-up added src/hal/wifi_bringup.c, wifi_only.conf and edits to CMakeLists.txt, Kconfig, bringup_shell.c and HARDWARE_TEST_PLAN.md, so it's 13 uncommitted paths, a month after the last commit. And a fifth thing hasn't caught up: the SPI bus, in its own block below.

Done when: the v5 work is committed, worn detect asserts on a v5 board, and the CS offset is fitted from more than one v5 point.

Notes:

✅ Resolved (tick Done to drop) — the dead v5 SPI bus was solder, and board #3 works

human only · raised 2026-10-13 · v3 chunks I, G · §5.5.1 · from agent-notes.md 2026-10-12 (three entries), .bringup/README.md, nrf_firmware/HARDWARE_TEST_PLAN.md

The first product firmware to touch SPI on v5 found the bus mute. lis2dh: Invalid chip ID: ff and RPU comms test ... got 0xffffffff, on both boards. The WM02C and the IMU share CLK, MOSI and MISO, so both failing points at a shared fault rather than at either part. Channel sounding is internal to the BM20C, so the 10-05 ranging results stand. What this blocks is everything that needs WiFi or motion on v5: WATCH_REMOVED's transport, and the IMU.

Where the diagnosis stood at 21:12 on 10-12, per the agent's own notes:

  • Proven good: MOSI, MISO and CLK continuous to the WM02C footprint, all seven WiFi pins correct in the generated devicetree, and the IMU powered with pin 7 sound.
  • Measured open: pads 5 (/SPI-SS) and 15 (/WIFI_INT) read 0 V while driven. Both nets cross to B.Cu and back, so it's either the BM20C joint or a via. A via fault would be a fab defect, and that explains both boards failing identically better than two identical hand-solder failures.
  • The BM20C was resoldered after that, and nothing records a re-test.

That diagnosis is the agent's, not yours, and no log confirms it. The one thing worth knowing before you pick up a probe: on this bus a single-ended reading proves nothing. Five tests got it wrong in one day, and the notes explain why. Use .bringup --wifi or --wifi-touch, which are two-ended.

Steps - [ ] Re-run ./bringup-test.sh --wifi on the resoldered board - [ ] If pads 5/15 still read open, probe the vias: /SPI-SS at (93.016, 116.694) mm, /WIFI_INT at (91.756, 119.509) mm - [ ] Then wm02c probe from a --wifi-only --board v5 image, and write which stage it reaches in a log

  • In Progress
  • Done

2026-10-14 — resolved, by an agent session rather than a log. A third v5 board, with the BM20C and WM02C reflowed onto a fresh PCB on 10-13 (die FFE2F93F D56E79CE, now in dies.tsv), brought up both the IMU (five live samples) and the nRF7002 (23-AP scan, DHCP, ICMP) with no firmware change. It was solder on the shared bus at the BM20C end, not a via, so it isn't a fab defect and says nothing about v5 vs v6. Boards #1 and #2 were only partly recovered by hand-rework. agent-notes.md, 2026-10-13. Nothing left to do here unless you want #1/#2 working too.

2026-10-23 — board #2 works too, and the 10-14 diagnosis was only half the story. You added solder to board #2's WM02C SPI pins on 10-22, and its nRF7002 now scans 17+ APs, associates and takes DHCP. Your account, in agent-notes.md 10-22, is that v5's WiFi had two independent faults: the BM20C's BGA grid, reworked over the week, and the WM02C's SPI pins. So a working IMU doesn't clear the bus. For any future v5, reflow the BM20C first. This block still meets its done when.

Done when: wm02c probe passes stage 3 on a v5, or the fault is located to a named joint or via. If it's a via on both boards, that's a fab defect and it belongs in the v5/v6 ❓ above.

Notes:

⚠️ The new ANCHOR_LAST_IP characteristic reuses the deleted Calibration Control UUID, …4a0f001c

automatable · raised 2026-10-23 · v3 §4.4.1, §4.8 · GATT four-way declaration · from verifying the 10-22 spec edit against the code

The 10-22 session added ANCHOR_LAST_IP at …4a0f001c, and that UUID is already taken. It's the watch's Calibration Control characteristic, which v3 §4.8 deletes. The old meaning is still declared in impulse_app/lib/utils/ble_constants.dart:39, phone_sim/impulse_phone/constants.py:45, the ESP32 WatchFIrmware/src/main.cpp:284 and v2 §4.10.7. nrf_firmware/src/ble/ble_uuids.h itself says, eight lines below the new define: "0x4a0f001c — Calibration Control — is DELETED … Do not re-add it." The v0.21 spec entry also said "no wire-format change" and that the app "does not know about" the UUID. Both are wrong, and this run corrected the spec.

Nothing breaks today. The two meanings live in different services (anchor vs watch), which GATT allows, and no watch reads the new one yet. But phone_sim's watch.py:460 addresses the characteristic by UUID alone, the ESP32 watch still serves the old meaning, and a contract declared in four places now has one UUID with two meanings. It is cheapest to fix before it's committed and pushed. Once the app learns the UUID, changing it is a lockstep change.

Steps - [ ] Move IMPULSE_UUID_ANCHOR_LAST_IP to an unused value (…4a0f001d is free in ble_uuids.h) and update v3 §4.4.1 to match - [ ] Re-flash board #2's anchor and confirm the read still returns [uuid][ipv4]

  • In Progress
  • Done

Done when: no 128-bit UUID in ble_uuids.h means anything other than what the other three declarations say it means.

Notes:

❓ The watch's WiFi escalation was one-way — the overnight session duty-cycled it (option a). Agree?

human only · raised 2026-10-23 · answered in code 2026-10-25 · v3 §1.6.1 (v0.22) · IMPULSE_ESCALATION_BLE_PATIENCE_S IMPULSE_ESCALATION_WIFI_DWELL_S

Done in code on 2026-10-25, without your answer in Notes:. This block asked whether the watch should duty-cycle its radios the way §1.6.2 makes the anchor do. The overnight session found the problem was worse than "one-way for 10 minutes". It was a latch: every re-assertion re-tested a link the previous call had just switched off. A window that opened unworn could never take the BLE path at all. The session implemented (a). The watch now waits 20 s of BLE before it concludes there's no link, stays on WiFi for at most 60 s (less if the anchor ACKs), and then gives BLE back. It also stops counting the silence it causes itself as evidence, which closed a real getAway bypass. v3 §1.6.1 and §4.5 say this (v0.22). This run checked the constants in Kconfig and ran the suite: 320/320 host checks pass. None of this has run on hardware with both boards yet.

2026-10-26 — now run on hardware with both boards (v3 v0.22's verification list, the 10-25 afternoon session). Real schedule naming the real anchor: cold-open unworn → WATCH_REMOVED over BLE in 1.9 s, no WiFi. Ranging blocked → seven 60 s dwell / 20 s re-listen cycles; released mid-dwell → BLE back, link in 1.1 s, REMOVED over BLE 2 s later. The latch is gone on hardware, not just in the suite. The sign-off is still yours.

What's left is your sign-off. If (a) is what you wanted, tick Done and the block drops. If you'd rather have (b) or (c), say so in Notes:. The constants are Kconfig, so changing them is cheap.

  • In Progress
  • Done

Done when: you've accepted (a), or Notes: names a different option and v3 §1.6.1 is changed to match.

Notes:

needs human help · raised 2026-09-24 · SEP-13 BLK-13 AUG-02 · from TaxReturns/registration/ and the website working tree

  • In Progress
  • Done

Organised in Virginia effective 2026-09-23 (SCC ID 12081863, $100 filing). No log mentions it; the receipt and the website's file timestamps do. Three things now have a right answer that they didn't have on Tuesday, and one of them is on SEP-13's clock:

  • The site still sells under the old name. All five legal pages were rewritten to "Impulse Gear LLC" at 21:15 and dist/ rebuilt — then not deployed. The live bundle still names "IMPULSE HARDWARE DAVID ALLAN MACPHERSON" 29 times, including as the EULA licensor. The site is collecting emails under terms that name a sole proprietor. Filed to website_issues.md.
  • The FCC grantee code should be the LLC's. Module Grant Conditions.md §5.1 step 1 — start the grantee code now — has been open since August. Every FCC ID filed under a grantee code carries its holder's name permanently, so register the FRN to the company. A business FRN wants the entity's tax ID, so the EIN comes first — free, online, usually same-day. SEP-13 (the change-of-ID conversation with Fanstel) is due 2026-09-30, and the letter Fanstel writes names the party taking over the ID, so the company should exist in that conversation from the first email.
  • The trademark should be filed by the LLC when it is filed (BLK-13, $350, your note says post-launch). Filing personally and assigning later works; filing as the company avoids the assignment.

Steps - [ ] npx firebase deploy from website/ — read git status first; the deploy ships a build of the uncommitted working tree - [ ] Get an EIN for Impulse Gear LLC (IRS online) - [ ] Register an FCC FRN in CORES to the LLC, then apply for the grantee code - [ ] Decide whether anything else is in your name that should move — Kickstarter creator account, Stripe, Kit, the domain — and note it here

Done when: the live site names Impulse Gear LLC, and the FRN exists in the company's name.

Notes:

⚠️ Phase 1 closed on 3 of 13 — four of its overdue items are under an hour each, and Phase 2 reads from them

needs human help · raised 2026-09-22 · SEP-10 AUG-02 AUG-05 SEP-11 AUG-07 · from Timeline.md Phase 1

  • In Progress
  • Done

Phase 1 ran 21 Aug → 30 Sep and closed on three of thirteen. Of the rest, nine carried into Phase 2 as overdue (counting AUG-03, SEP-13 and AUG-12, all due 09-30) and one expired. (2026-10-05: day counts below updated; nothing in the table has moved.) This block is not a seventh flag on those items — each already has its own block below. It is the thing none of them can say individually: four of the six close for well under an hour of work, and they are the four that everything in Phase 2 reads from.

Item Overdue The work
SEP-10 analytics 35 days Paste one snippet. Every number in Timeline.md is unmeasurable until it exists
AUG-02 UTM test 35 days Send yourself a tagged link, check it lands. The capture form is already live
AUG-05 Hackaday.io 28 days Create the page. The first build log is drafted and automatable below
SEP-11 blog 28 days One route on a site that already has eight. It gates all four BUD-HN posts

Why now rather than "soon". AUG-07, the Show HN and 1 of only 4 submissions in the whole plan, is an October item and has been open since 10-01. Its slots are Tue–Thu 8–10am ET, so October has about a dozen left, and its done when requires posting your own blog's URL. AUG-09 (review analytics, 2026-10-31) has no instrument without SEP-10. Phase 2 was designed to be the phase where the engineering becomes the content, and the two channels it publishes through are the two that don't exist.

The other two overdue items are not on this list on purpose. AUG-04 is missed and can't be un-missed; AUG-06's posting needs the card offloaded first. Both have their own blocks.

Done when: SEP-10, AUG-02, AUG-05 and SEP-11 are each either done or deliberately dropped — a dropped one said out loud is a fine answer and a better one than a fifth week of overdue.

Notes:

⚠️ The BM20C granted mobile on 2026-09-11 — SEP-12 expired, and the 20 cm clause is now broken on both modules

needs human help · raised 2026-09-20 · SEP-12 SEP-13 BLK-15 SHIP-05 AUG-13 · from the public FCC record

  • In Progress
  • Done

X8WBM20C was granted to Fanstel on 2026-09-11. Original equipment, DTS, 2402–2480 MHz, ≈8.4 dBm conducted / 15.4 dBm EIRP, ten model variants. The grant note reads: "The antenna(s) used for this transmitter must be installed to provide a separation distance of at least 20 cm from all persons." That is the same clause X8WWM02C carries — the one Washington Labs flagged on 2026-08-11 and that a wrist breaks at 5 mm.

This is good news and bad news, and they are separable.

✅ The good: BLK-15's certification half is discharged. The BM20C is certified, the grant number exists to put in front of a lab, and the nRF54LM20A is no longer a part that nobody has a grant for. The silicon ship date is the half that remains open.

⛔ The bad, and it was predicted in writing: launch-plan.md §5 said on 2026-08-11 that if Fanstel filed mobile-only, "the BLE-only fallback is not SAR-excluded by calculation alone either." They did. Two things follow:

  1. SEP-12 is expired rather than overdue. drafts/fanstel-exposure-category.md was written 2026-08-12 and never sent. Scoping an open filing cost a paragraph; the same question now costs a Class II permissive change only Fanstel may file. The draft isn't wasted — question 2 needs rewriting, and it becomes the opening of the permissive-change conversation instead.
  2. SEP-13 doubles in scope and gets more important, not less. It was the WM02C change-of-ID. It is now both modules on one thread, with the same third-party latency and the same SHIP-05-by-May deadline. And wornness-gating cannot rescue this one — that argument works because WiFi is off the wrist by construction, whereas the watch transmits BLE while worn, because that is the enforcement channel.

One phrase is now unsafe wherever it appears unqualified. "BLE-only is SAR-excluded by calculation" is true of the BC15C (X8WBC15, evaluated portable under §2.1093, 2.82 vs 3.0 at 5 mm) and false of the BM20C. Concepts/FCC Certification.md §5 and BLK-15's old text both use it bare. The fallback module is still the only part in this project authorised against a body today — which widens the gap between fallback and primary rather than closing it.

The most favourable number available: ≈8.4 dBm conducted, well under the WM02C's declared 0.17 W (+22.3 dBm). That is what a permissive change argues from.

⚠️ Confirm before spending money on it. This came off fccid.co, read twice. fccid.io and the FCC's own apps.fcc.gov search both returned 403 — which is also why eleven consecutive grantee-code checks missed the event for nine days. Treat a 403 as no data, never as no grant.

✅ 2026-09-22 — the grant note read in full, and one thing this block overstated is now corrected

The quote above stops at "20 cm from all persons" because that is as far as the source went. The complete note:

"Single Modular Approval. Power output listed is conducted. The antenna(s) used for this transmitter must be installed to provide a separation distance of at least 20 cm from all persons and must not be co-located or operating in conjunction with any other transmitter, except in accordance with FCC multi-transmitter product procedures. Grantee must provide integration instructions to host manufacturers. OEM integrators and end-users must be provided with transmitter operating conditions for satisfying RF exposure compliance."

So the BM20C's grant has the same shape as the WM02C's, clause for clause: the 20 cm exposure category is the unqualified half, and co-location is permitted via KDB 447498 D01 §4.4. The correction you forced on 2026-08-12 now holds for both modules on evidence rather than by analogy, and the title of this block has been narrowed to match — one condition broken on each of two modules, not two conditions on each. Say it that way to a lab: the difference is a narrow permissive change against a scope §12.5 prices at $35k. Nothing here reopens a decision and nothing gets easier about the 20 cm clause, which is still unconditional on BLE.

Worth knowing how close this went the other way. The first read of that page asked for the grant details in prose and got the co-location sentence back ending at "any other transmitter." — no exception. Taken at face value it says the BM20C is stricter than the WM02C, which would have reinstated the exact finding you struck five weeks ago. Only asking for the note verbatim produced the clause. That makes four times this clause has been dropped by a reader of it in this project. Rule from here: a grant condition gets quoted verbatim or not at all.

Steps - [ ] Confirm the grant and its exposure category from the FCC database or from Fanstel directly, and get the number in writing on the thread — still not done; apps.fcc.gov and fccid.io returned 403 again on 09-22 by two independent network paths, so this needs a browser, a phone call, or Fanstel - [ ] Pull the grant's MPE report and model difference letter from the exhibit list — the first is where "this is a Mobile device" comes from, the second says what the ten BM20* variants share. They are the two documents AUG-12's labs will ask for first, and both are downloadable now - [ ] Rewrite question 2 of drafts/fanstel-exposure-category.md as a permissive-change / change-of-ID ask covering both modules, and send it with SEP-13 - [ ] Add one line to that thread asking Fanstel to confirm "Availability: Production 09/2026" from their own BM20C page — it is the first plausible date BLK-15's ship-date half has ever had, and confirming a published date is a much smaller ask than requesting one - [ ] Ask Steve the KDB 178919 question again with a real case: the BM20C was represented mobile-only and has now granted — is mobile → portable a Class II here, or a new certification? It was the largest dollar figure open when the filing was hypothetical; it is now concrete - [ ] Qualify the bare "BLE-only is excluded by calculation" phrase in Concepts/FCC Certification.md §5 with the module it is true of — declined by /parselogs three runs running: it is a worked argument in a reasoning document, and rewriting it on a web read is what skill rule 7 says to flag instead. Say the word and it gets done

Done when: the grant is confirmed from a primary source, and the route to a legal wrist-worn BM20C is chosen rather than assumed — the same question SEP-13 asks of the WM02C, now asked of both.

Notes:

⚠️ AUG-04 is missed — the date passed on Sunday and can no longer be moved. The card offload is still owed

human only · raised 2026-09-18 · AUG-04 AUG-01 CAD-FILM · from the filesystem, twelfth verification

  • In Progress
  • Done

The founder video is due 2026-09-20 and none of its three prerequisite steps has started. The footage is still on a camera, no editor project of any format exists on this machine, and the 821 MB audio bed has not been touched since the night you recorded it — forty days. This is arithmetic, not a judgement about the week: a landscape long-form cut needs offload → audio edit → timeline, in that order, and Sunday is the day after tomorrow.

Sunday is also CAD-FILM's sixth Sunday, which Timeline.md calls the one mechanic that keeps the plan alive past week five. Two commitments, one day, and the honest reading is that they cannot both happen well.

Three answers, and each is fine if it's chosen rather than defaulted into:

  1. Cut it this weekend. Offload tonight, audio Saturday, timeline Sunday. CAD-FILM gives up its sixth Sunday, and that is a seventh consecutive lapse rather than a sixth.
  2. Move AUG-04 deliberately. Pick a date you believe, and say so — Timeline.md permits exactly this when it is a decision, and forbids it when it is slippage being hidden. The four-month delay bought the room; using it on purpose costs nothing.
  3. Protect Sunday for CAD-FILM and cut the video across the following week. Which is really option 2 with a specific date attached.

One thing is worth doing under all three: offload the card. Eleven takes in one copy is a risk the deadline has nothing to do with, and it takes minutes.

2026-09-19 — option 1 now starts today or not at all. Tenth verification, all three unchanged: no video file anywhere on this machine, no editor project of any format, audio still stamped 2026-08-09 — 41 days. A day and a half of work does not fit into Sunday, so "cut it this weekend" means beginning the offload today. Options 2 and 3 have not expired and do not cost a weekend — they cost one written line. Today is also a CAD-OFF Saturday, which is the third claim on the same two days.

2026-09-20 — option 1 is gone; the question is now only which of 2 or 3. Eleventh verification, all three still unchanged — no footage on this machine, no editor project of any format, audio stamped 2026-08-09 and 42 days idle. A landscape long-form cut cannot start and finish today, so the milestone is missed on the evidence unless a date is written. That is not a failure worth much — the four-month delay exists precisely to absorb it, and Timeline.md permits the move outright when it is a decision. It costs one line. What it cannot be is silent, which is the only outcome this block is trying to prevent. Today is also CAD-FILM's sixth Sunday; a batch today serves the b-roll either way, and the card offload is still minutes and still owed under every option.

2026-09-22 — the sentence below was the deal, and it is now what happened. Twelfth verification: no video file anywhere on this machine, no editor project of any format, audio still stamped 2026-08-09 — 44 days. AUG-04 is recorded in Progress.md as 🔴 missed, 2 days, and it stays at 2026-09-20. Moving it now is not available: Timeline.md permits a date change when it is a decision, and after the date has passed, the same edit is the slippage-hiding it exists to prevent. This is not a large failure — the four-month delay was taken precisely to absorb things like it — but it is the one that was avoidable at the cost of one line, five days running.

What is still worth doing, and is not about the deadline at all: offload the card. Eleven takes exist in one copy, on one SD card, and no removable media has been mounted on this machine since they were shot. That risk has nothing to do with AUG-04 and it does not go away with it. It also unblocks AUG-06, which has been open 30 days against 2 posts/week with nothing posted — the clips are the only content the plan has that already exists.

The useful remaining question is narrower than the one this block asked: when does the founder video get cut? Not to rescue a date that has gone, but because NOV-03 (second YouTube long-form) assumes a first one exists, and AUG-03's pre-launch page — due in eight days — is materially better with it than without it.

Steps - [ ] Offload the card. Minutes, owed regardless, and it unblocks AUG-06 - [ ] Say when the video gets cut — a date for the cut, not a replacement for AUG-04

Done when: the footage exists in more than one place, and a date for the cut is written down in a log or in Notes: below.

Notes:

❓ Does phone-distance now fail closed? impulse_overview.md says yes; the code, the specs and the live site say no

human only · raised 2026-09-15 · AUG-02 BLK-05 · from an uncommitted rewrite of impulse_overview.md, saved 2026-09-14 19:52

  • In Progress
  • Done

Yesterday evening impulse_overview.md was rewritten (+140/−50 lines, revision note dated 2026-09-14), and no log mentions it. Most of it is framing that belongs in that document: no competitor-attack ads (§5.2), "market to the audience, never about the condition" (§6), pre-launch principles, manufacturing gates, safety and single-user pairing (§8–§10). That was committed as written.

One change isn't framing. §3.2 now says phone-distance fails closed and calls the old fail-open text "wrong". It adds a three-condition agreement (app installed, app open, link strong) with timestamped in-app consent, and breaking any one of them sounds enforcement.

Everything else still says fail-open:

  • ESP32: firmware_spec_v2.md §5.4.1 step 3 says "must never fire a phone-distance alarm on an uncertain connection"
  • nRF: nrf_firmware/src/enforcement/enforcement.c:184 says "FAIL OPEN, unlike every other criterion"; ble_anchor.c:204 does the same for the dock read
  • App: MOBILE_APP_SPEC.md §0 parity row and lines 411, 601; DockSessionService "fail-open on drops"
  • Public copy: the live site FAQ (FaqSection.vue:25, "It fails quiet, not loud"), kickstarter-page.md:219, the recorded launch-video VO (launch_video_draft.md:170), marketing_strategy.md:83,154, and content-push.md, which plans a build log titled "how we landed on fail-open"

The options:

  1. Fail-closed is decided. Then it's a lockstep change: v2 §5.4.1, v3 §4, both firmwares, the app (the consent screen and its record are new work), MOBILE_APP_SPEC.md, and every piece of copy above, including a VO re-record. The overview itself names the cost: false alarms become a product category.
  2. The overview is wrong on this point. §3.2 and its §11 caveat go back to fail-open, and the rest stays.
  3. Not decided yet. Fine, but the overview and the live site contradict each other until it is.

If there's no answer, nothing normative moves. No spec, code or copy changes, and the overview stays as written.

Two smaller things the same rewrite carries, noted and not edited: §2.1 and §11 still say the motor and ring share a pin "until validated", but launch-plan.md §10 discharged that on 2026-09-10. And §9 says "pre-certified FCC modules for both devices", but the BM20C has no grant and the WM02C's grant is mobile-only (SEP-13).

Done when: a note or a log says 1, 2 or 3, and the documents on the losing side are brought into line.

Notes:

⚠️ Monday's respin puts both modules on the same edge, ~13.5 mm apart — FCC Respin.md says opposite edges, ~30 mm

needs human help · raised 2026-09-15 · OCT-10 BLK-15 SEP-12 · from diffing the saved board against Impulse-2026-08-30_021956.zip

  • In Progress
  • Done

2026-09-14, 09:57 → 22:52. V1 was first archived as ImpulseNRFV4.kicad_pcb (identical outline and placement to the 08-30 backup). Then Impulse.kicad_pcb was changed and saved, and the JLCPCB package was regenerated at 22:36. Measured from the files:

V1 Saved 09-14
Outline 40.0 × 42.0 mm 34.4 × 42.0 mm, west edge moved in 5.6 mm
WM02C (U8) ~0.6 mm short of the west edge unmoved; footprint now 5.0 mm past the west edge
BM20C (U7) west edge, y 102.7–112.7 12.4 mm south, y 115.1–125.1, 5.1 mm past the same west edge
Body gap between modules ~1 mm ~13.5 mm

Both antennas now overhang, which is the Best case for each on its own. But they overhang the same edge. FCC Respin.md §1.2 put them on opposite edges because both datasheets ask for ~30 mm, and one edge of this board gives at most 20. 13.5 mm is the body gap; the antenna-to-antenna distance was not measured. The outline landed at 34.4 mm, not the 32.6 predicted.

This may be deliberate. Maybe a Fanstel figure exists that isn't in any draft or email here, or the trade was taken knowingly. Then one line settles it. If not, it is far cheaper to catch before an order than after. The separation question is item 6 of the unsent Fanstel draft (SEP-12).

Six signals also moved pins (schematic netlist, 08-30 vs 09-14):

Signal V1 Saved 09-14
Vibration motor P3.03 / A7 P1.18 / F9
Buzzer P3.07 / C9 P3.09 / K7
Servo P1.02 / A8 P1.26 / J9
IR worn receiver P1.29 / F7 P1.16 / E9
Battery divider P1.00 / J7 P2.04 / B5
IMU interrupt P1.14 / F3 P1.19 / G9

Also: VCC merged into VBAT (motor supply, C17, C18, D3), and R36 (0 Ω to GND) removed, 103 → 102 parts. No servo-rail switch or fuse, and no VBUS input capacitor or Schottky, appears in the diff. Those are the power-tree items FCC Respin.md treats as independent of every antenna question.

firmware_spec_v3_nrf.md §2 is deliberately unchanged. It describes Board V1, which exists and runs the firmware. When the respin is ordered, the port needs a second board definition and §2 a second table; overwriting V1's would be wrong.

2026-10-06 — this board was ordered and built. Two v5 boards ran on 10-05, and both of the things this paragraph predicted now exist: boards/impulse/impulse_v5/, and a v5 delta table in v3 §2 (v0.19). The same-edge placement measured well for range: ~12 dB excess loss per board against V1's ~30, at 49 cm. That says nothing about the 30 mm module-to-module separation, which is a coexistence and grant question rather than a link-budget one, so the first step below still stands. Correction to the pin table above: V1's IMU interrupt is P1.14 / F3, not P1.08 / G8 (V1 devicetree and v3 §2).

Steps - [ ] One line in Notes:: is the same-edge placement deliberate? - [ ] One line: are the power-tree items still coming in this spin? - [ ] One line: was anything ordered on 09-14? - [ ] Before ordering: DRC, re-export the netlist, and give v3 §2 a respin table

Done when: the placement is either justified in writing or moved, and the power-tree items are either on the board or explicitly deferred.

Notes:

⚠️ BLE and WiFi can't run together — time division is now built; it needs its soak and the lab's answer

needs human help · raised 2026-09-14 · firmware_spec_v3_nrf.md chunk I, §5.5.1 · SEP-13 · from agent-notes.md 2026-09-12

On 2026-09-11 this file, the spec and CLAUDE.md all recorded "BLE and WiFi coexist." That rested on 224 CS procedures completing with WiFi associated. The next day's longer runs disproved it: with both radios active, both went silent within 5–13 minutes, repeatedly, while the application kept running. The same anchor rebuilt BLE-only ran 27+ minutes clean. The four coex wires are routed but CONFIG_NRF70_SR_COEX is off, so nothing arbitrates the band. Every enforcement test since has used a BLE-only build.

Why this matters more than a bug: WiFi was kept on the board (2026-08-11) for one job, WATCH_REMOVED beyond BLE range. §5.5.1 specifies it as UDP over WiFi, which cannot currently share a board with the ranging that decides compliance. Your stated direction is mutually exclusive in time, not PTA: carry WATCH_REMOVED over the CS link the watch already holds, and use WiFi only when that link is gone. That is a direction and not yet a design, so §5.5.1 was left as it is.

It touches the FCC plan too. The "mutually exclusive" position assumes the grant will require it. Steve's co-location answer and the wornness-gated-WiFi argument both depend on how the two radios are scheduled, which makes this a regulatory input as well as a firmware one.

Steps - [ ] Decide the scheme: which radio owns the air when, and what the watch does when the CS link drops during a window - [ ] Rewrite §5.5.1 for it, in both specs, with a §0.2 change-log entry - [ ] Before building it, confirm with the lab that time-exclusive radios are what the grant expects (the same question as Steve's co-location item) - [ ] Soak test: hours, not minutes, with both roles on the new scheme

  • In Progress
  • Done

2026-10-14 — steps 1 and 2 were done by an agent on 10-13, from your stated direction. v3 §1.6 (spec v0.20) is the scheme, and the code matches it (src/net/radio_policy.c, the !g_wifi_on_air gate at main.c:1621). The watch associates only after a BLE write to the anchor has failed. The anchor goes to WiFi only inside an open window after 90 s of BLE silence, then duty-cycles 120 s WiFi / 30 s BLE so a returning watch can still reach it. §5.5.1 itself wasn't rewritten; §1.6 sits beside it. The coexistence failure also reproduced on a known-good v5 board (4 m 40 s, then silence), so it isn't a solder artefact. I haven't ticked the steps because no log says it. Tick them if you agree with the design. Steps 3 (the lab) and 4 (the soak) are untouched, and the anchor has never received a WATCH_REMOVED that arrived because of the fallback.

2026-10-23 — the fallback is now proven on hardware, and the received-removal gap above is closed. On 10-22 the anchor (board #2) entered its dwell after 90 s of BLE silence, took DHCP 3.2 s later, beeped on a WATCH_REMOVED and stopped on WATCH_WORN. The dwell measured 120.02 s / 30.01 s and resumed advertising every cycle, even with a dead RPU. Steps 3 (the lab) and 4 (an hours-long soak) are still untouched. The watch side has a gap of its own, now a separate ❓ in Soon.

Done when: a watch and an anchor with WiFi fitted run a full enforcement window with both radios in the build, and neither radio dies.

Notes:

⚠️ Open a Nordic case for SoftDevice Controller assert 23, 587, and save the snapshot before a pristine build deletes it

needs human help · raised 2026-09-14 · v3 chunk G · from agent-notes.md 2026-09-12

This assert is the main obstacle to a reliable Sunrise Lock, ahead of range and ahead of the criteria logic. It fired twice in one afternoon, both times within minutes of channel sounding starting. The first time it halted the CPU with the motor latched on. Since then it costs a reboot instead, because the fatal handler and watchdog are built and proven. 23, 587 is not documented in NCS v3.4.0. The closest fix, DRGN-29669 (an assert when a link with active CS procedures disconnects), is on nrfxlib main and not in any release. There is no application-side fix to write. The firmware now disables procedures before disconnecting, but a link that is lost rather than closed still depends on Nordic.

The evidence is perishable. The RAM snapshot with the assert text is nrf_firmware/build-watch-cs-buzz/crash_ram_20260912.bin, inside an untracked build directory. The next -p always build of that variant deletes it.

2026-09-19 — re-verified: still 262 KB, still there, and still the only copy anywhere under ~/Impulse. Seven days on, the first step below is one cp and it is the only step here that nothing else depends on.

2026-09-20 — done, rather than flagged an eighth time. The snapshot is copied to files/nrf-crash/ with a README recording what it is and where its context lives; md5 matches and the original is untouched. The perishability is gone; the case is not — steps 2–4 still need you, and step 2 is the one an agent can draft in full.

Steps - [x] Copy crash_ram_20260912.bin somewhere outside build-*/ today ✅ 2026-09-20 — copied by /parselogs to files/nrf-crash/, md5 verified, original left in place. It is in the vault, so it is now versioned as well as safe from a pristine build - [ ] Draft the DevZone case: NCS v3.4.0, nRF54LM20A initiator-only, main mode 2 / sub-mode 1, the two backtraces, the 1.3 s of dropped subevent results before the first, and the DRGN-29669 question (an agent can write this; you submit it) - [ ] Submit it from your Nordic account - [ ] Watch for the nrfxlib release carrying DRGN-29669, and retest when it ships

  • In Progress
  • Done

Done when: a case number exists and the snapshot is stored somewhere a build can't delete it.

Notes:

automatable · raised 2026-09-14 · v3 chunk G · AUG-14 · from agent-notes.md 2026-09-13 and nrf_cs_test/

This is now the most visible defect in the product. Next to the anchor the link hits its supervision timeout every ~25–60 s. The lost-link rule turns each drop into a silenced grace, then an AWAY at 10 s, then a re-alarm after reconnecting, so the user sees a brief green on every drop. On top of that, BM20C↔BM20C ranging yields about 4× less than the DK walks: 2.2–2.4 good estimates/s, 72–74 % of procedures aborted, and a burst every 3.6 s median. The procedure parameters are still the NCS sample's, and nobody has walked the BM20C pair, so its real range is unmeasured.

2026-10-06 — on v5 this defect is gone, and the cause was the antenna. 604 s linked with 0 disconnects, 6034 procedures at 99.9% good, the full 10/s rate, at 0 dBm, two v5 boards at 49 cm (nrf_cs_test/v5-product-run1.rtt). The V1 runs were analysed in the same session: 64% / 44% good and 9–25 disconnects in a few minutes. So the steps below are largely discharged by agent-notes.md 2026-10-05, and the TX-power A/B is retired. What is still unmeasured is range: every v5 figure is from one geometry. That is the last step, and it now runs on v5.

A rig built to answer exactly this was run, and nobody has read the results. nrf_cs_test/README-limits.md says it was "never run on hardware", yet run1–run3 were captured on 09-13 between 12:52 and 13:39, and run3.csv (38,404 lines) was rewritten at 00:22 today. Its last stats line (prof=max, 1,226 s): 25 attempts, 18 ok, 7 dropped with 7 read errors, 4 connects and 3 disconnects. run1 (prof=product, 225 s) shows 9 connects, 9 disconnects and zero procedures. run2 has no stats line. All three *_plot_stdout.txt files are empty, so the plot step never produced output.

Steps - [ ] Analyse run1–run3: drops per minute, abort rate, and product profile against max - [ ] Correct README-limits.md's "never run" status, and record what each run was (distance, which board roamed) - [ ] If max holds the link where product doesn't, name the parameter that differs - [ ] One BM20C↔BM20C walk, so this pair's range is measured rather than assumed

  • In Progress
  • Done

Done when: the drop rate and abort rate each have a measured cause or a measured parameter that moves them, recorded in cs_tuning_plan.md.

Notes:

⚠️ Hardware checks still owed from the 09-12/13 sessions, each "built, not verified"

needs human help · raised 2026-09-14 · v3 chunks F, G · from agent-notes.md 2026-09-12/13

The sessions were unusually honest about what they did not get to. Each of these is either a fix that exists and has never been exercised, or a failure with no explanation:

Steps - [ ] Flash the anchor with the conn-leak fix (dcfeaaa). It was built and not flashed, and ble_anchor.c had the same leak with two peripheral links - [ ] Forced-disconnect test of the RRSP deadlock fix on the anchor. It was flashed, and the one test that proves it was not run - [ ] The anchor's ~01:02 reboot on 09-13: read the reboot-reason record that is now retained - [ ] The watch's bus fault in SEGGER_RTT_WriteSkipNoLock: unexplained. Crash record v2 now stores CFSR/BFAR, so the next one will say more - [ ] Audit every k_sem_take(..., K_FOREVER) in the CS engine. One of them ended ranging for a whole boot. (automatable) - [ ] Which anchor peripheral link gets notifications is still first-come (a TODO in ble_anchor.c) - [ ] Push phone_sim b5005c8. It fixes a once-event dated by the wrong day, and it exists only on a local branch with no upstream

  • In Progress
  • Done

Done when: every box above is ticked, or has a note saying why it was dropped.

Notes:

❓ Was Monday the OCT-10 respin starting? — and what was Tuesday's enclosure export?

human only · raised 2026-09-10 · OCT-10 BLK-03 · found by an mtime sweep, not by a log

Two evenings of real work happened this week and neither is described anywhere. What the filesystem can say:

  • 2026-09-08, 19:05→19:50. Board opened. production/ written at 19:19 — bom.csv, designators.csv, positions.csv, netlist.ipc, Impulse.zip — which is the fabrication-toolkit JLCPCB output and the step immediately before ordering. Then ImpulseBoardExtendable.step (19:20) and ImpulseBoardNRF.step (19:35), and a copy of the latter into ~/Downloads at 19:50.
  • 2026-09-09, 23:37→23:43. All ten working enclosure STLs rewritten. Every one differs from print-ready/v2 — verified by byte comparison, not by timestamp. The FreeCAD masters were not touched, so whatever produced them is not in this workspace.

Why it matters that nobody knows which of these it was. OCT-10 — draw and order the board respin — is a Phase 2 milestone due 2026-11-30, and it is the board that gets certified: it carries the WM02C antenna keepout violation, the BM20C footprint question, the servo rail protection and whatever V1's power tree turns out to be. If Monday was that starting, a milestone is running eleven weeks early and Progress.md should say so. If it was a keepout check, a BOM re-cost, or a render for the enclosure, that is worth knowing too — and if a fab package was actually ordered, that changes AUG-14, BLK-03 and the second-board question all at once.

Three specific things one line each would settle: what changed on the board; whether anything was ordered; and where the enclosure master lives — because if it is in a browser tool, it is outside every backup this project has, including the vault.

2026-09-15 — Monday answers half of this. A 13-hour session (09:57–22:52) archived V1 as ImpulseNRFV4, re-cut the outline, moved the BM20C, re-pinned six signals, saved, and regenerated the fab package. That is the respin being drawn, so Progress.md now reports OCT-10 as 🟡 on file evidence. Still unknown: whether anything was ordered, whether 09-08 was the same work, and where the enclosure master lives. The outline just shrank 5.6 mm, so the enclosure question matters. The layout questions have their own block at the top of Soon.

2026-10-06 — the board half is answered by the hardware itself. The 09-14 drawing was ordered and two v5 boards were running on 10-05, so OCT-10's "draw and order" happened and Progress.md now says so. Still unknown: the 09-08 session, and where the enclosure master lives — which matters more now that a 34.4 mm board needs a case.

What I'll do without an answer: nothing normative. No spec, no pin map and no milestone status moves on inference. models/README.md has been updated to record only what is verifiable — that the two STL trees have diverged, that no print-ready/v3 exists, and that the source is not in the folder.

Steps - [ ] One line: what the 09-08 board session changed, and whether anything was ordered - [ ] One line: what the 09-09 enclosure export was for, and where its source file lives - [ ] If it is OCT-10, say so — it is a Phase 2 milestone and it should be tracked as one

  • In Progress
  • Done

Done when: a daily log or the notes below describe both sessions well enough that OCT-10's status is a fact rather than a guess.

Notes:

⚠️ CAD-FILM has nine Sundays with nothing recorded — restart it, or rewrite the rate

human only · raised 2026-09-10 · CAD-FILM AUG-06 CAD-POST · from Timeline.md's own threshold, doubled

  • In Progress
  • Done

08-16, 08-23, 08-30, 09-06. Timeline.md sets the threshold at two consecutive lapses — "the earliest reliable signal the plan is failing" — and this is four. The flag itself was raised once, on 08-24, and correctly not repeated since; this block is not the flag again. It is the thing that comes after a flag that nobody could act on.

The rate was already cut for exactly this reason and has not run once since. On 2026-08-21 every cadence in the plan was reduced because school and the day job had taken the hours; CAD-FILM went from 12–15 clips to 8–10 and was the one rate Timeline.md refused to relax in kind, because it is the mechanic that turns three hours on a Sunday into a week of posting that costs nothing further. Three of the four missed Sundays have a visible alternative use — the bring-up, the Zephyr port, the ranging sweep, all genuinely valuable. 09-06 has nothing at all.

2026-09-14: the fifth Sunday went to hardware too. On 2026-09-13 a Sunrise Lock window ran 11:20–12:20, commits landed until 12:18, and the CS limits rig ran 12:52–13:39. No video file dated since 09-12 exists anywhere on this machine. Filming leaves no trace here, though, so this counts as no evidence of filming, not proof there was none. AUG-04, the founder video, is due next Sunday, 09-20. A batch that day serves both.

So there are two honest options and continuing to score zero against the current number is not one of them:

2026-09-12 — the hardware objection is now spent. Three of the four missed Sundays had a genuinely valuable alternative use, and every one of them was engineering. That engineering finished this week: two boards now range against each other and drive a real enforcement verdict, so the thing worth filming exists — the first footage in this project that shows a product rather than a prototype. Today is a CAD-OFF Saturday, which makes this a decision for today rather than something to notice on Monday.

  1. Restart it tomorrow, protected, at 8–10 clips. It unblocks AUG-06 (open 18 days, nothing posted) and CAD-POST (0/week) at once, and it is the only route to the founder video's b-roll that doesn't need another shoot day.
  2. Rewrite the rate to one you will actually hit — a fortnightly batch, or four clips instead of eight. Timeline.md says in its own words that "a rate you hit for six months beats a rate you abandon in month three." A smaller number that runs is worth more than this one.

This needs you, and it is why the hours question below has been open for nineteen days. /parselogs will not move a cadence on inference — Timeline.md may only change when a log states the decision. Say which, and it changes. Your objection from 2026-08-10 still stands and is worth restating rather than overridden: "give me time to get in my rhythm." Four weeks is time; the question now is which rhythm.

Steps - [ ] Pick option 1 or option 2, in Notes: or a log - [ ] If 1: put 2026-09-20 in the calendar and say afterwards how many clips - [ ] If 2: state the new rate as a decision, and Timeline.md gets rewritten to match

2026-09-22 — six consecutive: 08-16, 08-23, 08-30, 09-06, 09-13, 09-20. Triple the threshold Timeline.md calls the plan's earliest reliable failure signal, against a rate that was already cut on 2026-08-21 to be survivable at reduced hours — and it has not been hit once since the cut. Sunday 09-20 has no visible alternative use on any instrument: nothing in this workspace was written that day, or in the eight days around it. That removes the last version of the hardware objection. The two options below are unchanged and still cost one line each. Next Sunday is 09-27, inside Phase 1's final week; the week after that, Phase 2 opens and CAD-POST is still at 0/week with AUG-06 30 days open.

2026-09-28 — seven: 09-27 passed too. Nothing was written anywhere in ~/Impulse or ~/Documents/KiCad over the weekend, and no video file exists on disk. Phase 2 opens Thursday with CAD-POST at 0/week and AUG-06 open 35 days. The two options are unchanged, and the next Sunday, 10-04, is the first one in Phase 2.

2026-10-12 — nine: 10-04 and 10-11 passed with nothing recorded. The two options are unchanged.

Done when: either a Sunday batch is recorded, or Timeline.md carries a cadence you've committed to.

Notes:

⚠️ charger_detect is dead on this board — check the netlist before the respin, not after

needs human help · raised 2026-09-11 · OCT-10 · from the 2026-09-10 hardware session

The pin never asserts. Across a real USB-C plug event the battery climbed 94% → 97% — so the TP4057 was charging — while charger_detect sat at its pull-up level throughout, identical to unplugged. Not a polarity error; the line simply does not move. Your decision on the night was not to chase it, and that is right: charge state can be inferred from the battery-voltage derivative, which is what v2 §6.3 did before Board V1 added this input.

Two things that decision does not cover.

First, the inference is not written, so charge state is currently unavailable rather than degraded — and the power-tree soak is the one job that most wants to tell charging from discharging.

Second, and this is the one with a deadline: the suspected cause is an unwetted BM20C pad, on a board that already had four on 2026-08-29. If that is right, it is one bad joint and it does not repeat. If it is wrong, it is a design error that gets copied into OCT-10's respin — and P1.03 is still marked [from schematic] in the pin map, never once driven or verified. One netlist export settles which it is, and kicad-cli can do it without opening the GUI.

Steps - [ ] kicad-cli sch export netlist --format kicadsexpr and confirm what P1.03 is actually tied to - [ ] If the netlist is right, reflow that pad and retest — one joint - [ ] If the netlist is wrong, it is an OCT-10 fix and it is cheap now and expensive after the respin - [ ] Either way, write the battery-derivative inference, because it is the fallback in both branches

  • In Progress
  • Done

Done when: P1.03 is confirmed against the netlist and the answer is recorded in firmware_spec_v3_nrf.md §2 as measured rather than [from schematic].

Notes:

⚠️ Start the V1 power-tree soak — it is the reason AUG-14 was given ten weeks

human only · raised 2026-08-30 · AUG-14 BLK-03 · from Timeline.md Phase 2 and agent-notes.md 2026-08-10

Three of five recent ESP32 prototypes died with the 3.3 V regulator holding the rail low, and Board V1 carries an identical power tree. The anchor that failed on 2026-08-10 had been sitting plugged in and unused for five days — it worked, it was left alone, and it was dead when picked up. Timeline.md says this in as many words: "whatever that failure is, it takes days to appear — a demonstration that runs once proves nothing."

The old plan gave AUG-14 three weeks. It now has 58 days, and the whole argument for buying that window was that "leave it powered for a fortnight and see" becomes schedulable. The board now exists, so it is schedulable. It has not been started.

2026-09-12 — the last excuse is gone. For four runs the stated reason was that the only working V1 was also the development board. There are two working boards — the second runs the anchor role, associates on WiFi at −65 dBm and has been ranged against — and there have been for at least two days. Nothing about this now competes with development.

2026-10-25 — soak with the debugger detached. On 10-24 v5 board #3 was found wedged, with its PC in the vector table. Its reset cause showed the watchdog had been firing, so it had been crashing, not sitting up for hours. The watchdog pauses while a probe halts the CPU, so a soak watched over RTT hides the failure it's looking for (agent-notes.md 10-24). That anchor has no cell and runs on external power, and power is the leading suspect. That's the soak's question exactly, on the v5 board rather than V1.

This is not the battery endurance test that is running now — that one is measuring the cell against a beep-and-sleep duty cycle and will end when the cell does. The soak is the opposite: keep it on external power, leave it, and check the 3.3 V rail every few days. Cheap in effort, impossible to compress, and the only thing that separates "it worked on the bench once" from a board you would certify.

Steps - [ ] Leave a V1 on external power, undisturbed, and note the date it started - [ ] Measure the 3.3 V rail at the start — a healthy board read 3.25 V and the dead ones 2.5/2.8/3.0 V - [ ] Re-measure every few days for at least a fortnight, and write each reading in a log - [ ] If the rail sags, that is the answer OCT-10's respin needs — and it is worth more than a board that survives

2026-10-24 — still no trace of a soak, with 7 days to 10-31. One started today ends 11-07. If not, closing late or moving the milestone is your call; the date won't move without it.

2026-10-23 — still no trace of a soak. One started today ends 11-06, six days past 10-31. The 10-22 session used v5 boards #2 and #3, so the V1s are still free. If one is running, its start date and first rail reading go in Notes:.

2026-10-20 — still no trace of a soak. If one is running, its start date and first rail reading go in Notes:. If not, one started today ends 11-03, three days past AUG-14's 10-31. Moving the milestone is your decision.

2026-10-18 — the start-by date has passed. 10-17 was the last day a 14-day soak could start and still finish by 10-31, and this machine was off all day. Because battery-test.sh runs untethered, a soak could have started without leaving a trace here, so this is unknown rather than missed. If one is running, put its start date and first rail reading in Notes:. If not, starting today ends 11-01, one day late. Moving AUG-14 is your decision, and nothing here will move it for you.

2026-10-13 — four days left. A fortnight's soak has to start by 2026-10-17 to finish by AUG-14's 10-31. The V1s aren't the boards being worked on now, since yesterday's session was all v5, so one of them is free to go on a shelf today.

2026-10-06 — v5 changes which board this should run on, and the answer is yours. v5 has the same power tree (none of the protection parts went in), so a V1 soak still tests v5's regulator path. But if v5 is the board that gets certified, the soak belongs on v5, and only two exist. There are now four boards, so a V1 left on a shelf for a fortnight costs development nothing. See the new ❓ at the top of Soon.

2026-08-31 — this now collides with something, and the collision is worth naming rather than letting it quietly defer the soak again. The only V1 that works is also the only development board, and yesterday it was flashed repeatedly, driven by phone_sim, and used as a channel-sounding initiator. A soak wants a board left undisturbed on external power for a fortnight; development wants the same board on a bench with a debugger on it. Those are not compatible, and the soak is the one that cannot be compressed — 62 days of window sounds like a lot until you notice it is fourteen days of not touching the board. This is the strongest argument yet for assembling the second V1** (block below), and it is the argument that has nothing to do with channel sounding.

  • In Progress
  • Done

Done when: a V1 has been continuously powered for ≥14 days with the 3.3 V rail logged and stable — or has failed, which is equally a result.

Notes:

⚠️ Two days of major engineering are in no log — and the battery number is already gone

human only · raised 2026-08-30 · CAD-REVIEW BLK-04 · from the workspace, not from a log

Twelve days without a diary entry, across the two most productive days this project has had. 2026-08-29 brought the board up; 2026-08-30 wrote a Zephyr port, booted it, and measured channel sounding against ground truth. Both were found by sweeping the filesystem. The technical record is genuinely excellent — .bringup/README.md, two agent-notes.md entries, nrf_firmware/HARDWARE_TEST_PLAN.md, nrf_cs_test/RESULTS.md, and now docs/hardware-notes/cs_tuning_plan.md — so this block is not asking you to duplicate any of it. It asks for the things no artefact can hold.

2026-08-31 — the perishable one perished, exactly as flagged. The battery endurance test started at 01:03:40 on 08-30 and .battery-test-state still holds only its start time. The board was reflashed for the Zephyr session a few hours later, so the endurance figure was never read and no longer exists.** It was the least valuable of the four items here — a beep/WFI duty cycle is not the product's and never answered BLK-04 — so the cost is small and the lesson is not: a number that lives only on a running board has a deadline measured in hours. Dropped from the steps below rather than carried as a reproach.

2026-10-23 — the last log is still 2026-08-21, 63 days ago. The 10-22 session (both ends of WATCH_REMOVED, board #2's resolder) is another full day known only from agent-notes.md and the owner's account quoted in it. Its technical record is good. What's missing is the same as before: what you trust, and what's next.

What is still only in your head:

  1. Do you trust the rework? Four pads on a hand-placed 100-pad LGA, reflowed after a first attempt with added paste that changed nothing. Is this board a demo unit or a measurement platform? Everything measured yesterday — including the ±0.20 m CS figure — sits on that answer.
  2. Was the second board assembled, or does one V1 exist? This now blocks three separate things; see the block below.
  3. The servo pad reading that is still unexplained. agent-notes.md records a hard-low reading on A8 attributed to a solder bridge, and the real fault turned out to be unsoldered pads elsewhere. Its own note says to re-run --scan before treating it as real. Still unrun, and U1 is unpopulated so the servo driver has never moved anything.
  4. What the CS captures actually were. walk1/2/3.csv mixed body, cushion and whole-house occlusion with no labels, and RESULTS.md says so itself — every per-file conclusion in it is provisional for that reason alone. If you remember which was which, one line recovers 10,047 samples of otherwise-unusable data.

Steps - [ ] One log entry covering 08-29 and 08-30: what you did, what you trust, and how many boards exist - [ ] Label the three walk captures if you can still remember them — one line each, in RESULTS.md or in Notes: - [ ] Re-run bringup-test.sh --scan and settle the A8 servo reading

  • In Progress
  • Done

Done when: a daily log covering 08-29/08-30 exists, and the three CS captures are labelled or written off.

Notes:

⚠️ The CS calibration rests on a single point — one sweep settles it

needs human help · raised 2026-09-12 · AUG-14 v3 chunk G · from docs/hardware-notes/cs_tuning_plan.md P0

IMPULSE_CS_IFFT_OFFSET_CM moved 97 → 72 on the strength of ONE line-of-sight station at ~61 cm. That was the right call — the old value came from the DK pair and errs in the unsafe direction — but one point cannot separate slope from offset, and the slope in the firmware (0.993) is still the DK's. Every NEAR/AWAY threshold in the product rests on that fit.

A second number says the same thing louder. phase_slope − ifft is +0.30 to +0.48 m on a clean line-of-sight bench with no occlusion at all. The whole design treats that divergence as the occlusion/multipath quality signal, so a baseline this large means CS_QUALITY_MIN cannot keep its DK-derived value either — and unlike the offset, nobody has adjusted it.

2026-10-06 — v5 makes this blocking. At a known 49 cm, v5 ifft read 1.46 m and 1.76 m median in two captures, so the current offset of 72 places the boards 0.25–0.55 m further apart than they are. Solving for the offset gives 96 and 126; that spread is the finding, and the constant was rightly not moved on it. Reading long errs toward under-enforcement: a getAway is satisfied early, and NEAR really needs ~145–175 cm. The sweep below should be run on v5.

One good outcome worth not losing: BM20C↔BM20C precision looks materially better than the DK pair — ifft sd of 0.02–0.04 m against 0.20 m rmse. If that holds across distance, the burst size (N=10) and possibly the 1.5 m NEAR/AWAY band are more generous than they need to be, and a shorter burst is an energy saving, not just tidiness.

Steps - [ ] Stations at roughly 0.5 / 1 / 2 / 4 / 7 m LOS, ./cs_sample.sh 25 "<distance>" at each, then fit — expect far stations to need longer captures (sampling drops from ~10 Hz at contact to under 2 Hz past 5 m) - [ ] Re-derive the slope and offset from the fit, and replace the DK-derived slope - [ ] Measure the LOS divergence baseline across distance first, then re-measure occluded, and reset CS_QUALITY_MIN - [ ] Revisit burst size and the NEAR/AWAY band if the precision holds

  • In Progress
  • Done

Done when: cs_tuning_plan.md's P0 list is closed and no constant in the CS path traces back to a dev kit.

Notes:

⚠️ WATCH_REMOVED beeps a real anchor from a real schedule — what's left is the trigger, a natural unworn

needs human help · raised 2026-09-12 · firmware_spec_v3_nrf.md chunk F, §5.5.1 · from agent-notes.md 2026-09-12

The watch half is proven on the wire — real 33-byte datagrams decoded on the LAN, unicast to the right host, re-asserted every enforcement poll as §5.5.1 requires. The anchor receiver is written and has never been exercised, because that board was mid-rework when the path was built.

And the thing that fires the whole path is still blind. The trigger is worn detection, and the IR window sits behind the enclosure, so the sensor cannot cross its threshold on a real wrist. The transport can be complete and the feature still never fire in the field — which is precisely the failure the ESP32 anchor-escalation bug had, and why §5.5.1 re-asserts rather than announcing once.

2026-10-06 — on v5 it is blinder still. CONFIG_IMPULSE_ADC_CH_IR (AIN1) was found by a sweep on V1; the IR receiver moved to P1.16 on v5, so the channel reads an unrelated pin and worn stays false from boot. There is no worn→not-worn edge, so WATCH_REMOVED cannot fire on a v5 build at all. Any v5 test of this path tests nothing until impulse adc is swept on v5.

2026-10-14 — both halves moved on 10-13. On v5 the trigger exists again: worn detect is now IMU stillness (v3 §6.4), so a watch left still for 300 s produces a worn→not-worn edge. And the anchor's §4.6 receiver has been exercised for the first time, on v5 board #3. A host on the LAN sent real 33-byte datagrams, the anchor dispatched WATCH_WORN and rejected a wrong-length packet, and it re-associated from NVS credentials after a reset. Still never run: a real watch sending 0x01 to a real anchor, and the beep starting. Steps 3 and 4 below are IR-only now and apply to V1, not v5.

2026-10-23 — steps 1 and 2 were done by an agent session on 10-22, not by a log, so they aren't ticked. Anchor (board #2, in its WiFi dwell): beep start (profile 1) on 0x01, then cmd: WATCH_WORN — stopping alarm / beep stop. The bytes matched what v5 board #3's watch had emitted that day, replayed from a host. The guard works: an unknown event gets NOT_MINE, and junk gets no reply. Watch (board #3): 300 s still → worn -> 0 → WiFi → 0x01 on the wire every 60 s. The anchor now acknowledges every command (v3 §4.6.1) and the watch retries up to 3×. Broadcast loses about half its datagrams on this LAN, so WATCH_WORN used to be a coin flip. Still not run: a real watch whose schedule names this anchor, since both demos use synthetic beepAnchors UUIDs. That needs a schedule push from the app or phone_sim. Steps 3–4 are IR and V1-only. The done when is on a wrist, with the enclosure, so it isn't met.

2026-10-26 — the seam named in this title ran on 10-25, with you listening. A real schedule naming the real anchor 75b2aeb2… was on both boards. The watch went unworn, WATCH_REMOVED went over BLE, and the anchor (now anchor-cswifi-buzz, clock set by hand) beeped. Worn → WATCH_WORN → the beep stopped. That covers steps 1 and 2 in substance, and they stay unticked because an agent session did them, not a log. What it didn't cover is the trigger. Both worn edges came from wornset, and board #2 never reached unworn on its own. The done when (a wrist, the enclosure, a natural edge) is still unmet. Steps 3–4 are IR and V1-only. On v5 the equivalent is the IMU-spike ❓ at the top of Soon.

There is a bench override (impulse wornset <0|1|auto>) that makes the rest testable. It is shell-only and deliberately unreachable over BLE, because a forced worn state is a way to make the watch believe a commitment is being honoured — exactly what the app must never be able to assert. Keep it that way.

Steps - [ ] Run the anchor receiver against the watch — confirm the beep starts on 0x01 and stops on 0x02 - [ ] Confirm the anchor's own guards reject a packet for an event it isn't in beepAnchors for - [ ] Get a real wrist reading — needs the IR window clear of the enclosure, or an enclosure change - [ ] Set the worn threshold from the wrist side, not the no-wrist side (it is 200 mV / 140 mV release, estimated)

  • In Progress
  • Done

Done when: taking the watch off a wrist, with the enclosure on, makes a real anchor beep.

Notes:

⚠️ The watch ranges the WRONG ANCHOR — the loop closed, and this is what was behind it

needs human help · raised 2026-08-31 · AUG-14 v3 chunk G · from docs/hardware-notes/cs_tuning_plan.md P0

CS is proven on the silicon and it is not proven in the product. Yesterday's rig ran nrf_cs_test/ — a pair of Nordic sample derivatives — between Board V1 and the DK. The product firmware now carries its own backend behind CONFIG_IMPULSE_CS_BACKEND, adapted from ras_initiator, plus a host-tested fusion layer. All three unknowns below are now answered and the product loop closes — see the dated note under the list. What is left is not one of them; it is the correctness bug they were hiding. Three things stood between here and a working product loop, and cs_tuning_plan.md calls them P0 because none of them is a tuning question:

  1. Does the engine start and range from inside the product image? Build with cs.conf, flash V1, put a reflector on the DK, watch RTT for CS backend: nrf-cs-ras and burst results.
  2. Does a real burst drive a real verdict? impulse demo 1 4 with a live reflector should flip cond_met 0→1 as the reflector crosses NEAR_ENTER_CM, and fire the motor when it leaves. That single test is the whole product, and nothing else on this list is worth much until it passes.
  3. Two BLE roles at once. CS holds a central connection while the app needs the watch to be a peripheral. CONFIG_BT_MAX_CONN is 2 and the combined image builds, but peripheral+central has never been exercised together — and this is exactly what broke the ESP32 build (firmware_spec_v2.md §10.1: ble_hs_timer_exp panic, reproduced on both IDF 4.4.7 and 5.5.5). Zephyr's host has its own version of the hazard. Test this early: if it fails, the enforcement design changes shape rather than just its constants.

2026-09-12 — all three passed, and the loop shut. Two Board V1s range against each other: ifft median 1.32–1.36 m at 0.02–0.04 m sd over 150+ samples, and a live enforcement window produced 172 estimates in 60 s driving a real cond_met — which is test 2, the one this block called "the whole product". The BM20C pair's offset is not the DK's, so IMPULSE_CS_IFFT_OFFSET_CM moved 97 → 72; the old constant errs in the unsafe direction, reading the watch ~25 cm closer than it is. Filed into firmware_spec_v3_nrf.md v0.13 and HARDWARE_TEST_PLAN.md. This block is retitled rather than closed, because one item on it never depended on the others:**

The backend ranges against whatever matches the iBeacon manufacturer prefix, not against event.anchorId — and with the loop now closed, this is the most serious thing left in the port. It is not a tuning error and no threshold fixes it. With one anchor in the room it is invisible. With two anchors in a house, a stayNear commitment can be satisfied by standing next to an anchor the commitment never named — the watch holds and measures the wrong one, reports compliance, and logs nothing unusual. That is a bypass of the root of trust, in the same family as the sys_reboot() disconnect found on 2026-09-10, and it is reachable by anyone who owns two anchors rather than by an attacker.

It is cheap to fix and it will not get cheaper. The anchor UUID is already in event.anchorId and the identity derivation is already shared between roles (src/identity.c, added 2026-09-11), so the filter has everything it needs.

Steps - [x] Test 3 first — concurrency is the one that can invalidate the design rather than delay it ✅ 2026-09-10 — PASSES. Full GATT surface read at MTU 498 while the CS engine holds a scan. Not yet tested during an actual ranging procedure, which needs a reflector to range against - [x] Test 1 — the engine starts and runs from inside the product image ✅ 2026-09-10, after a fix (it was calling bt_enable() twice and aborting with -120) - [x] Test 2 — a real burst driving a real verdict ✅ 2026-09-11 — 172 estimates in 60 s in a live enforcement window, driving cond_met. The whole product, and it works - [x] Wire the anchor's CS reflector ✅ 2026-09-10 — written and running (cs_reflector_nrf.c); ranged against successfully 2026-09-11 2026-09-14: still open, verified against the source: cs_backend_nrf.c:1705, TODO(hw): anchor_id is ignored. Since 09-13 the exposure is larger. The watch now reconnects on its own about 18 s after every drop, and each reconnect goes through the same prefix match, so every link drop is another chance to latch onto the wrong anchor.

2026-10-23 — still open, now at cs_backend_nrf.c:1725. Two related things from 10-22. Test 3's caveat is partly discharged: a GATT discovery and write on the ranging link left CS clean (rej_*=0, bursts every 2–3 s). And the §4.6.1 ack and ANCHOR_LAST_IP both carry the anchor's own UUID because of this bug, so an address can't be filed under the wrong anchor. That protects the WiFi path. It doesn't fix ranging.

  • Fix anchor targeting to filter on event.anchorId ← the only thing left on this block
  • Re-test with two anchors powered at once, one of them not named by the commitment — that is the case that currently passes when it should fail

  • In Progress

  • Done

Done when: with two anchors powered, a stayNear commitment naming only one of them reports non-compliant while the watch sits beside the other.

Notes:

⚠️ GATE-TRAJECTORY wants 600 emails by 30 November, and nothing is measuring anything

needs human help · raised 2026-08-22 · GATE-TRAJECTORY SEP-10 SEP-11 AUG-06 NOV-05 · from the revised Timeline.md

The new plan added a gate that fires long before the go/no-go, and it is the one that is actually near. GATE-TRAJECTORY — 600 emails by 2026-11-30, 87 days out. It exists because a single go/no-go at the end of a twenty-seven-week runway tells you in February what you needed to know in November, and its stated remedy is deliberately not "post more": miss it and the answer is to change the hook.

That remedy only works if something measured which hook. Four separate blocks in this file are each a piece of the same instrument, and all four are open at once:

Piece Block Due
Site analytics — the denominator The site has no analytics SEP-10, 2026-08-31
A channel that posts, written down Nothing records where any of it posts AUG-06 opened 2026-08-24
A blog — every HN post needs one There is no blog SEP-11, 2026-09-07
Edited clips to post at all The footage exists in one copy ongoing

Read together they are not four chores, they are one measurement that either exists by late September or doesn't. The list has been at zero for the twenty-four days the site has been live, and no traffic number exists for any of them. AUG-09 on 31 October is "review analytics; double down on the best hook" — that review is the rehearsal for this gate, and it is unanswerable without SEP-10.

The honest scale of the ask: 600 from zero over 87 days is ~48/week, against a Timeline.md conversion table that puts one Hackaday feature at 3–8% of its traffic and one HN front page at 1,000–3,000 emails on its own. This is not a volume problem. It is a "nothing has shipped to a channel yet" problem, and the first thing to ship is the instrument.

Steps - [ ] Install analytics — it is also the only spend BUD-ADS permits before December, so the money question is answered - [ ] Name the channel you will actually post to, in one line, anywhere an agent can read it - [ ] Get one thing published somewhere with a link back, and watch it arrive

2026-08-24 — one of the four came due today. AUG-06 opened; the other three are 7, 14 and ongoing days out. Nothing in the table has moved in the two days since it was written, which is the finding rather than the absence of one — this is one instrument, and it is still four pieces short of existing.**

2026-09-04 — 87 days, the table is unchanged in every row for the tenth run running, and the first two rows are four days overdue. SEP-10 and AUG-02 passed on 08-31 unmet; SEP-11 is 3 days out; AUG-06 has been open twelve days with nothing posted. Four CAD-REVIEW Fridays have passed without the one number this table cannot fill, and the fifth is today — it is a login, and it is the only row here that today can still turn green. The engineering has moved further in two days than the instrument has in three weeks** — which is not a criticism of the engineering, but it is the shape of the risk: GATE-TRAJECTORY does not care how good the hardware is.

2026-08-26 — 96 days, and the table is unchanged in every row. SEP-10 and the Fanstel email are both 5 days out; SEP-11 is 12; AUG-06 has been open three days with nothing posted. Nothing here has moved in four days, which is the whole report: the instrument is still four pieces short of existing**, and the first piece is still ten minutes of work.

Done when: a visit from a post you made shows up as a pageview, and if it converts, as a subscriber carrying its source.

  • In Progress
  • Done

Notes:

❓ How many hours a week does this actually get? — every new cadence rate is a guess at that number

human only · raised 2026-08-22 · CAD-POST CAD-FILM CAD-LOG CAD-CREATOR · from the 2026-08-21 log

The plan moved four months because the hours aren't there, and then the rates were re-derived without anyone knowing what "there" is. Your log says it plainly — "school has started and my job has ramped up. i don't have the hours the august–november plan assumed" — and gives dates, a budget, and a sequencing decision. It does not give an hours figure. So Timeline.md's new rates were set by argument rather than measurement: 2 posts/week (was 3), 8–10 clips (was 12–15), 1 build log a fortnight (was weekly), 10 creator emails (was 20).

Those cuts are defensible and they may still be wrong in the same direction as the old ones. The failure mode launch-plan.md §12.32 names is not "the rate was too high by 30%" — it is a cadence quietly stopping in week five. Halving a number you couldn't sustain does not fix that if the real budget is a third of what was assumed. Twenty-seven weeks makes this worse, not better: the old plan could be brute-forced through on a few good weekends; this one cannot.

One number answers it. Roughly how many hours a week does Impulse get during term — total, honestly, including filming and email? Then:

  • ≥ 10 h/week — the rates in Timeline.md are about right, and CAD-FILM's Sunday is the load-bearing three hours of it.
  • 5–10 h/week — CAD-POST and CAD-CREATOR are still too high. Cut them, keep CAD-FILM intact, and protect the two technical posts (AUG-07, NOV-02) since they carry most of the expected emails anyway.
  • < 5 h/week — the rates are decoration and the plan is one Sunday plus whatever else lands. Worth knowing now, because it argues for spending the runway on the nRF build and the two HN posts rather than on a daily-content pretence.

If there's no answer, the next run keeps scoring against Timeline.md's current rates and flags CAD-FILM on the two-week rule, which is the one thing all three readings agree on.

2026-09-10 — nineteen days open, and it now has a concrete bill attached. CAD-FILM has missed four consecutive Sundays against a rate that was cut in August specifically because these hours had shrunk — so the number this block asks for is no longer background context, it is the input that decides whether that cadence gets restarted or rewritten. One number closes both. Hours per week, term-time, honest rather than aspirational; a small figure is a useful answer and an aspirational one is worse than none, because every rate in Timeline.md would then be re-derived from it. *2026-09-14: a timesheet screenshot appeared, and it answers a neighbouring question, not this one. ~/Pictures/hours.png (saved 09-13 13:58) shows day-job timesheets of 22:05 h for 31 Aug–5 Sep and 35:59 h* for 6–12 Sep. That is a real measure of what the job takes, up 63 % in a week, and nothing was inferred from it. It does not say what Impulse gets, and the week the job took 36 h was also the heaviest engineering week this project has had.

Steps - [ ] One number in Notes: or a log — hours per week, term-time, honest rather than aspirational

Done when: the number is written down, and the cadence table either survives it or gets cut again.

  • In Progress
  • Done

Notes:

⚠️ There is no blog, and every HN post in the plan requires one

needs human help · raised 2026-08-21 · SEP-11 AUG-07 BUD-HN GATE-EMAILS AUG-05 · verified against src/router.ts

2026-08-21 (timeline change) — the emergency is off; the dependency is not. AUG-07 moved from this Tuesday to October 2026, and standing up the blog is now its own Phase 1 milestone, SEP-11, due 2026-09-07. Everything below still holds and none of it is less true — BUD-HN is 4 posts across Aug 2026 – Mar 2027, still 0 spent, and not one of them can be submitted until this exists. What changed is that you have six weeks instead of four days, and the Show HN can now be written against a blog that has something else on it rather than a blog created that morning. Read the rest of this block as a dependency with a date, not a fire.

2026-08-22 — SEP-11 is 16 days out, and it gates more than one post now. AUG-07 (October), NOV-02 (November) and JAN-01 (January) are three of the four BUD-HN submissions and none can be made without it. Re-checked today: src/router.ts still declares eight routes and none is a blog.

Timeline.md specifies AUG-07 down to the URL it posts: "Done when: posted Tue–Thu 8–10am ET, on your own blog's URL, and you were in the comments for four straight hours." content-push.md §11 assumes the same in passing — "everything else you want to write goes on Hackaday.io and your own blog, where volume is free."

The Tue–Thu 8–10am ET slot and the four-hours-in-the-comments rule apply whenever it goes; what changed is when. AUG-07 is an October post now, so the binding date is SEP-11 — 2026-09-07, 4 days — because nothing in BUD-HN can be submitted before the blog exists.

This run checked, and the site has no blog. src/router.ts declares eight routes — /, /order (a redirect to the signup), and six legal/contact pages. No /blog, no /writing, no posts directory, and no reference to Substack, Medium or dev.to anywhere in the source. Nothing in this vault names a blog hosted elsewhere either. That is missing evidence, not evidence of absence — the same shape as the social-handles block below, and the same one-line fix if you have one.

Why this outranks the milestone it sits in. BUD-HN is 4 posts across the entire Aug 2026 – Mar 2027 period and none is spent. Show HN is once per project, not once per milestone. And the payoff is the most non-linear number in the plan: Timeline.md's own table puts an HN front page at 5–10% of 10–40k visits — 1,000–3,000 emails — against a gate of 2,500, where a flat outcome is ≈800 and means don't launch. This is the closest thing to a single-day route to the gate, and it is a ticket you can only buy four times.

Two things would need to be true by Tuesday, and one of them is already queued.

  • A URL you own with the post on it. AUG-05's Hackaday.io project page is that, in the sense that matters — and its build logs are the same material the Show HN post needs: why the enforcer can't live on the device being policed, the watch as root of trust, tightenings instant and loosenings quarantined. The automatable block two down from here now feeds two milestones instead of one.
  • Analytics on the domain. See the analytics block below. Without it an HN spike arrives and leaves with no number attached, which is the one traffic event in the plan you cannot afford to have unmeasured.

If there's no answer, the next run scores AUG-07 against a blog that nothing records, and reads SEP-11's 2026-09-07 as the operative date rather than October's posting slot — because the dependency closes a month before the post does.

Steps - [ ] Say where you'd post it — an existing blog, a new page on impulsestore.net, or the Hackaday.io project page - [ ] Decide where it lives before SEP-11 closes on 2026-09-07 — a page on impulsestore.net, or an existing blog; the Show HN date is October and no longer forces this - [ ] Install analytics before it goes up, not after (the block below; ten minutes) - [ ] Block out four hours after posting — the milestone says in the comments, and that part is not delegable

2026-08-24 — SEP-11 is 14 days out. Re-checked: src/router.ts still declares eight routes and none is a blog.

2026-08-26 — 12 days. Re-checked a sixth time: eight routes, none a blog.

2026-08-29 — 9 days. Eighth check, same eight routes.

2026-09-05 — 2 days, and they are a CAD-OFF Saturday and a CAD-FILM Sunday. Tenth check: eight routes, none a blog. This is the collision worth deciding rather than discovering — SEP-11 gates all four BUD-HN posts, so of the three commitments landing on these two days it is the one whose slip costs the most later.

Done when: the Show HN post has a URL to point at, or AUG-07 is deliberately rescheduled in a log.

  • In Progress
  • Done

Notes:

⚠️ The footage exists in one copy, on a camera — and nothing has been edited

human only · raised 2026-08-17 · AUG-01 AUG-04 AUG-06 CAD-POST · verified against the filesystem

There is no video file anywhere in /home/ironon. Not the five vertical Sunrise Lock takes, not the two Phone Dock takes, not the four landscape takes, not 2026-08-12's studio and location shots. Searched .mp4, .mov, .mkv, .avi, .insv, .braw across the entire home directory. The only media on this machine are the four .wav files in Impulse/audio/ — 821 MB, and not modified since 2026-08-09 20:21, the night you recorded them.

No edit has been started either, and that is three separate checks agreeing: no project file of any format exists (.mlt, .kdenlive, .drp, .prproj, .aup, .veg, .osp), and Shotcut's config has not been written since 2026-07-12 — a month before you shot anything. It has not been opened since.

Two things follow and the first one is the urgent one.

1. AUG-01 is the only completed milestone in Phase 1 and it lives in exactly one place. A camera or its card. These are not casually reproducible takes — a 6am wake-up with an alarm clock and lighting set, first-person walk-outs, and a bed-continuity montage you plan to cut between progressively more disheveled beds. A card that fails or gets formatted takes Week 1 with it. Copying it costs minutes, and this workspace already carries the same flag about the live website's source.

2. AUG-04 is inside its window as of yesterday and the cut has not begun. The audio bed has been finished and waiting since 2026-08-09; your own 2026-08-10 plan put the audio edit first and then the cut, and neither has happened. The window closes 2026-08-22.

One caveat stated honestly, because this is an inference about your week rather than a measurement of it: short-form is routinely cut on a phone, so AUG-06's vertical clips may be moving somewhere this machine cannot see. That caveat does not reach the founder video — it is a landscape long-form cut over a 511 MB audio bed that lives here, on a machine where no editor has been opened.

2026-08-21 — re-checked, and everything above still holds four days later. No video file in /home/ironon, no project file of any format, no removable media mounted tonight, and the four .wav files are still stamped 2026-08-09 20:21 — twelve days idle. The machine was off from Monday morning until tonight, so this is not four days of the card sitting un-offloaded at a desk; it is four days of there being no desk. The first step is still minutes and it is still the highest value-per-minute item in this file — AUG-04 and AUG-06 both close tomorrow, and both start with a file copy.

Steps - [ ] Offload the card to this machine — before anything else on this list - [ ] Put a second copy somewhere that isn't this machine either - [ ] Say in a log where the footage lives, so this doesn't have to be inferred again - [ ] Edit the audio (first item on your own 08-10 plan, still first) - [ ] Cut AUG-04 — and fix the script's line 153 before you cut it, not after

2026-08-22 — re-verified a third time, and this is the one item the four-month delay did not help at all. No video file anywhere in /home/ironon, no editor project file of any format, no removable media mounted, and the four .wav files are still stamped 2026-08-09 20:21 — thirteen days idle. AUG-04 now has until 20 September and AUG-06 starts Monday, so the deadline pressure is genuinely off. The card is not on a deadline; it is on a coin flip.** Everything else in this file gets safer when the dates move. A single copy of eleven takes does not, and it is still minutes of work.

2026-08-24 — fourth verification, unchanged, and the milestone that needs these files is now open rather than approaching. No video file anywhere in /home/ironon, no editor project file of any format, no removable media mounted; the four .wav files are still stamped 2026-08-09 20:21 — fifteen days idle. AUG-06 began today and AUG-04 has until 20 September, so the deadline pressure remains genuinely off. The card is still not on a deadline; it is on a coin flip**, and copying it is still the highest value-per-minute item in this file.

2026-08-29 — sixth verification, unchanged. No video file anywhere in /home/ironon, no editor project file of any format, no removable media mounted; the four .wav files are still stamped 2026-08-09 20:21 — twenty days idle. Nothing new to argue: AUG-04 has until 20 September and AUG-06 is open. The card is still on a coin flip rather than a deadline**, and it is still minutes of work.

2026-09-16 — eighth verification, unchanged, and the argument has changed shape. No video file anywhere in /home/ironon belonging to this project, no editor project file of any format, no removable media mounted; the four .wav files are still stamped 2026-08-09 20:21 — thirty-eight days idle. For the last month this block's own line has been "the card is not on a deadline; it is on a coin flip." It is now on both. AUG-04 is due Sunday 20 September, and a landscape long-form cut over a 511 MB audio bed needs three things to happen in order: offload, audio edit, timeline. None has started. On present evidence the milestone cannot be hit — which makes this a choice between starting the copy this week and moving the date deliberately, and Timeline.md only permits the second when it is a decision rather than slippage being hidden. The copy is still minutes of work and still the highest value-per-minute item in this file.**

2026-09-18 — ninth verification, unchanged, and there are two days left. No video file anywhere in /home/ironon belonging to this project, no editor project file of any format, no removable media mounted; the four .wav files are still stamped 2026-08-09 20:21 — forty days idle. Nothing has been argued here that wasn't argued on Tuesday, so this is a date stamp rather than a new case. What changed is only that the decision moved from the week to the weekend, and it now has its own ❓ at the top of Soon. The card copy is still minutes of work, and it is still worth doing even if the date moves** — a single copy of eleven takes is a risk the calendar has nothing to do with.

Done when: the footage is in two places, and the founder video's timeline exists.

  • In Progress
  • Done

Notes:

⚠️ Both Sundays are unrecorded — this is CAD-FILM's two-week flag

human only · raised 2026-08-17 · flag raised 2026-08-24 · CAD-FILM AUG-10 · from Timeline.md's cadence rule

2026-08-16 was CAD-FILM's first honest test and nothing records the outcome. content-push.md §11: "Sunday, 3 hours: batch-film 12–15 clips. Non-negotiable. This is the single mechanic that keeps the plan alive past week five." Timeline.md says to flag it loudly after two consecutive lapses, because that is the earliest reliable signal the plan is failing.

This is not that flag, and it deliberately isn't. One unrecorded Sunday is missing evidence, not a miss — filming leaves no trace on a laptop, and this one was suspended all weekend. The Sunday that would trip the rule is 2026-08-23, six days out.

The reason it's worth a block rather than a line: the distinction the cadence tests is batch versus shoot, and Week 1 shot on five of six days. That is a different discipline — good days of filming, but not the one that makes the next week's posting free. If Sunday was a batch, this closes. If it wasn't, next Sunday is worth protecting deliberately rather than discovering.

If there's no answer, the next run notes 08-30 as a third unrecorded Sunday and leaves it at that. The flag is raised once. Repeating it louder each week would be noise, not information — the rule exists to tell you something you didn't know, and after this run you know it.

2026-08-21 — the flag Sunday is the day after tomorrow. Still nothing records 08-16 either way, and this run will not score it as a miss for the same reason as last time: the machine was suspended through it and filming leaves no trace here. But 08-23 is now two days out, and it is carrying three other things at once — AUG-07 and AUG-08 open, CAD-CREATOR starts at 20 emails/week, and AUG-13's "ask the lab within 2 weeks" expires. A batch-film is the one of the four that protects the following week**, which is exactly the argument for putting it in the calendar now rather than discovering Sunday evening that the other three ate it.

Steps - [ ] Answer in Notes:, or in a log — one line: did you batch-film on 2026-08-16, and roughly how many clips?

2026-08-22 — the flag Sunday is tomorrow, and the plan change made this cadence matter more rather than less. CAD-FILM was cut in volume (12–15 clips → 8–10) and not in kind — it is the one rate Timeline.md refused to relax, because it is the mechanic that turns three hours on a Sunday into a week of posting that costs nothing further. The dates moved precisely because the hours aren't there, which is the same condition that makes a batch-film lapse. Over twelve weeks you could brute-force around it; over twenty-seven you cannot. 08-16 is still unrecorded and this run still won't score it as a miss for the same reason as the last two. If tomorrow also passes unrecorded, the next run flags it loudly**, which is what Timeline.md asks for and is not a judgement about the weekend — it is the earliest reliable signal the plan is failing.

2026-08-24 — 08-23 passed unrecorded, so this is the flag. Timeline.md: "If it lapses for two consecutive weeks, that is the earliest reliable signal the plan is failing — flag it loudly." Two Sundays, 08-16 and 08-23, neither recorded. Three things are worth being exact about, because the exactness is the whole value of the flag.**

  • This is not a proven miss. Filming leaves no trace on this machine and never will. What is proven is only that nothing recorded it.
  • The reason the last three runs held back has expired. 08-16 fell inside a four-and-a-half-day power-off; 08-23 did not. The machine resumed at 13:31 Sunday and was awake in five separate windows through 01:10 Monday — roughly six hours — and nothing was written in any of them.
  • Your objection from 2026-08-10 stands, and is worth restating rather than quietly overriding: "im not sure i agree that just because i did things out of order, it means im failing the plan. give me time to get in my rhythm." That was fair then and it is fair now. This is not a judgement about two weekends. It is the one thing Timeline.md explicitly asked to be told about, said once, on the date it came due.

One line closes it permanently and gives the cadence table its first real number — including the line "yes, both, ~10 clips each," which would turn the loudest item in this file into the quietest.

2026-09-10 — 08-30 and 09-06 both passed unrecorded, which makes four. This block asked one question about 08-16 and it is still the question; it is not re-raised here. What comes after four consecutive lapses is a decision rather than a flag, and it has its own block at the top of Soon — CAD-FILM has missed four consecutive Sundays — restart it, or rewrite the rate. Answer either block and both close.**

2026-08-29 — still not raised again, and it resolves tomorrow. 08-30 is Sunday.* If it is batched, one line closes this block permanently; if it isn't, three consecutive Sundays is a different conversation from two, and that is the run that will have to have it. Nothing further from this run.

2026-08-26 — not raised again, by design. No Sunday has passed since Monday, so there is nothing new to say and saying it louder would be noise — this block's own rule, four paragraphs up: "the flag is raised once." 08-30 is four days out**, and it is the date that decides whether two unrecorded Sundays become a fortnight or a trend. One line still closes it in either direction.

Done when: the answer is written down, here or in a log.

  • In Progress
  • Done

Notes:

⚠️ AUG-06 opened today, and nothing records where any of it posts

human only · raised 2026-08-14 · still open 2026-08-24 · AUG-04 AUG-05 AUG-06 CAD-POST CAD-LOG · from searching the vault and the live site

2026-08-22 (timeline change) — the window stopped closing and the question got no easier. AUG-06 now begins Monday 2026-08-24 at CAD-POST's revised rate of 2/week, and AUG-04 and AUG-05 have until 20 and 7 September. Nothing below is late any more. Everything below is still unanswered, and it is now the cheapest input to GATE-TRAJECTORY — a channel nobody has written down cannot be reviewed on 31 October or counted on 30 November. One line.

Week 2 opened on 2026-08-16 and it opened all at once: AUG-04 founder video published, AUG-05 Hackaday.io project page plus the first two build logs, AUG-06 begin posting 3×/week. All three close 2026-08-22. content-push.md §11 puts the Monday step at "schedule the week's posts, write the Hackaday log" — that Monday is today, and both channels are assumed live for it.

This run searched for them and found nothing. No TikTok, Instagram, YouTube or Hackaday.io handle or URL appears in any markdown file in this vault, and the live site links to no social profile at all — not in the footer, not in the nav.

Read that correctly: it is missing evidence, not evidence of absence. You may have had these accounts for years and simply never written them down, which is the likeliest explanation and costs nothing to correct. What is certain is only that nothing here can answer it, two days out, and that an agent picking up any content task has nowhere to look.

Two things are needed and they are different in kind:

  • AUG-06 needs an account and postable files. Seven raw takes is not seven posts — the cadence is 3/week and each post is a cut, captioned, vertical file. This is now verified rather than assumed: zero clips have been edited, and the footage isn't even on this machine — see the block above.
  • AUG-05 needs a project page before anything can be posted to it. The writing half is its own block, directly below.

2026-08-17 — the window is open and the machine was asleep for the run-up. It suspended Friday 12:29 and resumed this morning at 08:29 — 68 hours, no reboot. Saturday off is CAD-OFF working as intended and this is not a criticism of the weekend. It does mean that everything here that needs a computer starts this morning from zero, on day 2 of 7, with three milestones sharing the window.

2026-08-21 — and it never got the computer. The machine suspended again on Monday at 09:31, an hour after that run, and did not come back until tonight's cold boot. Week 2 has had about 62 minutes of desk time in it. So the three milestones sharing this window close tomorrow untouched, and that is absence rather than avoidance — worth saying because the two call for different responses. What hasn't changed is the ask: one line naming the handles, which is the cheapest unblock in the file and needs no computer at all. AUG-07 has now added a blog to the same question — see the block at the top.

2026-08-24 — the window is not approaching, it is open: AUG-06 began today, and the question is exactly as unanswered as it was ten days ago. Re-checked this run: no TikTok, Instagram, YouTube or Hackaday.io handle appears in any markdown file in this vault, and the live site still links to no social profile. The other half is unchanged too — 0 clips edited, 0 video files on this machine. The revised rate makes the first week two files rather than three, which is a real reduction; two files still need somewhere to go. This has been the cheapest unblock in Soon for ten consecutive days, it needs no computer, and one line in Notes: closes it.

2026-08-29 — day six, and the answer has not changed in fifteen consecutive runs' worth of asking. Re-checked: no TikTok, Instagram, YouTube or Hackaday.io handle in any markdown file in this vault, no social link on the live site, 0 clips edited, 0 video files on this machine. It needs no computer, no decision and no money.* One line in Notes: closes it.

2026-08-26 — day three of an open milestone, and the answer is the same as it was on day one. Re-checked: no handle in any vault markdown file, no social link on the live site, 0 clips edited, 0 video files on this machine. Twelve consecutive days as the cheapest unblock in Soon.** It needs no computer, no decision and no money — one line in Notes:.

Steps - [ ] Write the handles down — one line in this file's Notes: is enough, and it unblocks every future content task - [ ] If they don't exist: create the Hackaday.io project page, and whichever short-form account you actually intend to post to - [ ] Add the social links to the site footer while you're there — the site currently links to nothing - [ ] Edit at least three clips into postable files — the cadence is running now, not starting

Done when: every channel Week 2 posts to exists, and its handle is written down somewhere an agent can find it.

  • In Progress
  • Done

Notes:

Draft the Hackaday.io project page and the first two build logs

automatable · raised 2026-08-14 · AUG-05 CAD-LOG SEP-11 · due 2026-09-07 (was 2026-08-22)

2026-08-22 (timeline change) — sixteen days instead of today, and it is still the best-value item on the board. AUG-05 moved to 2026-09-07 and CAD-LOG's rate dropped to one build log a fortnight through December, so two drafted logs is now the better part of a month of cadence rather than one week of it. The AUG-07 urgency is gone — Show HN is October — but the dependency below is unchanged and the material is unchanged.

2026-08-17 — the window is open and today is the day §11 assigns to it: "schedule the week's posts, write the Hackaday log." CAD-LOG's first week is this week. Of everything in Soon, this is the one item that needs nothing from you to start and nothing physical to finish.

AUG-05 is in its window now and the writing is the whole milestone. Timeline.md specifies log #1 down to what it must contain: "what Impulse is, why the phone can't be the enforcer", stating the commercial intent plainly. content-push.md §3 adds the norms — Hackaday.io is where all build content lives, over-posting is impossible there, and a single line admitting this is going to be a product buys complete goodwill.

You are unusually well supplied for this and none of it is written up publicly. The material already exists in this vault, in finished prose:

  • the ESP32 → nRF migration and why channel sounding replaced an inference engine — Concepts/NRF Redesign.md, firmware_spec_v3_nrf.md
  • three regulators dead out of five prototypes, with the input-voltage comparison and the hot-air repair — the 2026-08-10 log and agent-notes.md
  • the antenna keepout finding — two chip antennas, 30 mm required, 1.15 mm actual — Concepts/Antenna Placement.md
  • "RSSI is a liar" — the proximity engine measured at 70–80% in the field, which is content-push.md §4's own best HN candidate and is a build log first

That is four logs' worth before anyone builds anything new. The constraint is that a build log is written in your voice about your bench, so a draft is a draft — but a good first draft of the project page plus two logs is reachable without you, which is exactly what automatable means.

One thing to get right, and it is the reason to read the draft rather than paste it: launch-plan.md §10's claims fence still forbids showing vibration and the LED ring on one unit until the board revision is validated, and ordered is not validated. A build log about the respin must not imply a working V1.

2026-08-21 — this block now feeds two milestones, and it is the best-value thing on the list. AUG-07's Show HN opens Sunday with a Tuesday posting slot and needs a URL you own (top block). The Hackaday.io project page is* that URL, and log #1's brief — why the phone can't be the enforcer* — is the same architecture argument content-push.md §11 wants the Show HN post to make. So drafting this closes AUG-05, starts CAD-LOG, and gives AUG-07 something to point at. It is still the one item in Soon that needs nothing from you to start and nothing physical to finish.

Steps - [ ] Draft the project page — what Impulse is, the commercial line, the header image - [ ] Draft log #1 to Timeline.md's specification: why the phone can't be the enforcer - [ ] Draft log #2 — the ESP32→nRF migration is the strongest and doubles as NOV-02's HN post (was SEP-07; moved to November 2026, where it finally has measured numbers behind it) - [ ] Read them in your own voice before posting; a build log that reads like a spec is worse than none

2026-08-24 — 14 days, unchanged in every particular, and still the best-value item on the board.** Re-listed rather than re-argued: it is the one item in Soon an agent can start this minute and finish without anything physical, and the project page plus SEP-11's blog are the two artefacts standing between you and a URL that GATE-TRAJECTORY can actually count.

2026-08-30 — 8 days, and the material got dramatically better overnight. Every source listed above is a retrospective; last night produced the first thing this project has that reads as a build log written from a bench, and Hackaday.io's audience is exactly the one that rewards it. Three candidates, in order: "four pads on a 100-pad LGA were never soldered, and a reflow that changed nothing" — with the objective pull-up test that proved it and the lesson that an unwetted pad is visually obvious; "PWM cannot reach this pin, and DMA completion lied about it" — 0 highs in 199 samples while the engine reported a full transfer, which is a genuinely good debugging story and ends in a peripheral-domain map; and "the LED chain decodes 0.5 µs as a zero", with the dark-versus-white diagnostic table. All three are in .bringup/README.md and agent-notes.md in near-publishable prose. This also removes the §10 hazard the block warns about below — none of these three logs needs to claim vibration and the ring run together, so they can be drafted and posted without touching the claims fence at all.

2026-09-05 — 2 days. Unchanged and still the nearest-dated automatable item in the file. Worth saying plainly: this is the one of the three things due this weekend that does not need you to start it — the other two are a blog you have to decide the home of, and a Sunday of filming nobody else can do. If the weekend has to give somewhere, this is the piece that can be handed off instead of dropped.

Done when: a project page and two build logs are drafted, fenced against §10, and waiting on nothing but your read.

  • In Progress
  • Done

Notes:

⚠️ The site has no analytics — and posting has started

needs human help · raised 2026-08-14 · SEP-10 AUG-02 AUG-09 GATE-TRAJECTORY · due 2026-08-31 — four days overdue · verified against the deployed source

2026-08-22 (timeline change) — this stopped being a chore nobody scheduled and became a dated milestone with the money question already answered. It is now SEP-10, due 2026-08-31 — nine days, and one of only two new Phase-1 milestones the revision added. Two things follow. AUG-09 (review analytics, double down on the best hook) moved to 31 October explicitly because this has to exist first for it to mean anything — so this is on that milestone's critical path, not adjacent to it. And BUD-ADS's first window is $0–200, "tooling only — analytics, scheduling, a link tracker", which makes a paid analytics plan the single sanctioned expenditure in the entire plan before December. The trade-off that was never explicitly weighed is now decided in the plan's favour.

2026-08-17 — re-checked, still nothing: index.html loads exactly one script. AUG-06's window opened yesterday, so from here every day of posting is a day of traffic that will never be attributable. The install is still ten minutes; what it buys shrinks daily.

There is no traffic measurement on impulsestore.net. index.html loads exactly one script, the app bundle. No Google Analytics, no GTM, no Plausible, Umami, PostHog or Fathom, no Firebase Analytics.

The attribution half is built — src/lib/attribution.ts captures all five UTM keys and attaches them to the signup, so a subscriber will carry the source that brought them. That is the half that survives; it is also still subject to email-capture-setup.md §4's untested question of whether Kit's free plan stores custom fields at all.

What's missing is the denominator. From Sunday the funnel is views → profile clicks → link clicks → site visits → emails, and every stage is measured by the platform except the one on your own domain:

Stage Measured by Exists
Views, completion rate platform-native ✅
Profile clicks, link clicks platform-native ✅
Site visits nothing ❌
Email captured, with source Kit + attribution.ts 🟡 built, §4 unrun

Timeline.md gives a whole expected-conversion table in view → email, and AUG-09 on Aug 30 is "review analytics; double down on the best-performing hook." Neither is answerable without this. Traffic you didn't measure cannot be backfilled — the cost of waiting is not the install, it's the two weeks of history you don't get back.

Roughly ten minutes: a script tag in index.html, or Firebase Analytics since the site is already on Firebase Hosting. Privacy-first options (Plausible, Umami) avoid a cookie banner and are the better fit for this audience; GA4 is free and is what a creator or press contact will ask for.

2026-08-21 — the reason to do this stopped being retrospective. Until now the cost of waiting was history you don't get back. AUG-07's Show HN could land Tuesday (top block), and an HN front page is the single largest traffic event anywhere in the plan — 10–40k visits in a day, per Timeline.md's conversion table. Arriving unmeasured means you learn nothing from the one ticket you can only buy three or four times: not how many came, not what fraction converted, not which paragraph they came for. Ten minutes, and it wants doing before Tuesday rather than before Sunday's first post. index.html still loads exactly one script — re-checked this run.

2026-08-22 — the Tuesday HN post is in October now, so that particular argument is withdrawn. What replaces it is duller and harder to dismiss: AUG-06 starts Monday, and from Monday every post is traffic that will never be attributable. Re-checked again today — index.html still loads exactly one script, the app bundle.

2026-08-24 — AUG-06 opened today, so the sentence above stopped being hypothetical. Re-checked for the fifth run: index.html still loads exactly one script, the app bundle. SEP-10 is 7 days out. Two things are worth holding together: it is ten minutes of work, and it is the only expenditure BUD-ADS sanctions before December**, so neither time nor money is the obstacle. Nothing has posted yet, so no traffic has been lost yet — that stops being true with the first post rather than at the end of the month.

2026-08-29 — 2 days.* Eighth check: index.html still loads exactly one script. Nothing has posted, so no traffic has been lost yet — but this shares Monday with AUG-02 and SEP-12, and it is the only one of the three that is ten minutes and entirely yours. AUG-02's UTM acceptance test is the same sitting.

2026-08-26 — 5 days, and re-checked for the sixth run: index.html still loads exactly one script. Still nothing posted, so still no traffic lost — but SEP-10 is now the nearest dated item in the whole plan that is entirely within your control, which the other two things due 08-31 are not.

Steps - [ ] Pick one — Plausible/Umami (paid, no banner, better fit) or GA4/Firebase (free, already in the stack) - [ ] Install it before the first post goes up - [ ] Run email-capture-setup.md §4's acceptance test while you're in there — it's the other half of AUG-02 and has never been run - [ ] Check a UTM'd visit end to end: link → pageview recorded → signup → utm_source stored in Kit

Done when: a UTM'd visit shows up as a pageview and, if it converts, as a subscriber carrying its source.

  • In Progress
  • Done

Notes:

⚠️ Neither module's grant covers the watch — the WM02C's never did, and the BM20C's granted mobile on 2026-09-11

needs human help · raised 2026-08-11 · BLK-15 AUG-12 AUG-13 · from Washington Labs' reply

Washington Laboratories replied to quote #1 and sent the actual grant. Not a price — a scoping correction, and it lands above everything the FCC docs had assumed. Read in full in Concepts/Module Grant Conditions.md; the email is emails/WL Labs Exchange.md.

X8WWM02C is a mobile grant: ≥ 20 cm from all persons. The watch breaks it at 5 mm on the wrist. No arithmetic fixes this, because it is a clause on the grant rather than a consequence of the power number, and FCC Certification.md §5 spent its whole length on the power number. Fixing it needs a Class II permissive change, which only Fanstel may file. The lab's recommendation is a change of ID — Fanstel writes one letter, you hold your own FCC ID for the module, and you file your own permissive changes from then on.

✅ Corrected 2026-08-12, and you were right to push back. This block originally said the grant also forbade co-location with any other transmitter, and that the watch broke both conditions. It doesn't. The grant sentence ends "except in accordance with FCC multi-transmitter procedures" — so putting the WM02C beside the BM20C is permitted, via the simultaneous-transmission evaluation in KDB 447498 D01 §4.4 that FCC Certification.md §5 was already doing. Your reasoning was the right reasoning: a WiFi companion module that may not sit beside a host radio would be an incoherent product. One condition is broken, not two, and the one that remains is the exposure category. Corrected across nine documents; the reading error is written up in agent-notes.md.

✅ 2026-09-22 — and the BM20C's grant, now read verbatim, carries the same exception. "…except in accordance with FCC multi-transmitter product procedures" — one word different. So this correction was not a reprieve specific to the WM02C; it is how these grants are written, and it now holds for both modules on evidence. The two radios may sit on one board under both grants. What does not improve: the 20 cm exposure category is broken on both, and on BLE it has no design-side escape.

Two figures moved with it: the grant declares 0.17 W (+22.3 dBm), not the datasheet's 18.24 dBm, so the 2.4 GHz exclusion ratio is 53, not 26.2. And a permissive change became the baseline path for a WiFi watch rather than the failure case.

✅ 2026-08-12 — the cost of that baseline was overstated, and it was the number that alarmed you. launch-plan.md §12.5's $15k → $35k prices a full intentional-radiator retest, which is route 3 in Module Grant Conditions.md §5 — not the change-of-ID route Steve actually recommended. A Class II PC that changes only the exposure category, supported by an exclusion calculation rather than a SAR measurement, is a paperwork filing — TCB fees of a few thousand, no chamber time. The realistic route-2 bill is a grantee code, the CoID filing, the C2PC filing, and the Part 15B SDoC you owe anyway. The KDB 178919 question is what could still move it by an order of magnitude, and it is free to ask.

❓ The urgent part is none of the above. Fanstel said on 2026-08-04 that BM20C testing completes "this month" — that filing is open now. If they file it mobile-only the way they filed the WM02C, then the BLE-only fallback stops being SAR-excluded by calculation alone, and that claim is currently load-bearing in three documents and in BLK-15. Asking them to scope an open filing for portable body-worn use costs them a paragraph. Asking after it grants costs a permissive change. drafts/fanstel-followup.md has eight items and none of them is this one.

2026-08-12 — the BM20C's exposure category is now the top item here, above the WM02C's. Module Grant Conditions.md §5 states why and it had not been said anywhere: wornness-gating can rescue the WiFi radio; nothing can rescue BLE. The watch transmits BLE while worn — that is the enforcement channel. If the BM20C grants mobile-only, a permissive change on the BLE radio is unconditional and no design change avoids it. Your prediction that it will be mobile-only is recorded there with what supports it: the mechanism is the standard one, but X8WBC15 is not mobile-only, so it is a per-part decision rather than Fanstel policy. ⚠️ BM15C ≠ BC15, and only the BC15's grant has been read.

2026-08-17 — the draft has now waited five days, and the month it was racing is more than half gone. drafts/fanstel-exposure-category.md has not been modified since 2026-08-12 15:15. Fanstel said on 2026-08-04 that BM20C FCC testing completes "this month"; it is the 17th. Nothing about this is a criticism of the pace — it is the one item on the whole list whose deadline belongs to someone else, and the cost of being late is not a delay, it is a permissive change instead of a paragraph. Two questions, one screen, no blanks to fill.

2026-08-21 — nine days unsent, and ten days of "this month" left. drafts/fanstel-exposure-category.md is still stamped 2026-08-12 15:15, and so is drafts/wll-steve-followup.md. Two things now have dates rather than urgency attached:

  • AUG-13's "ask the lab within 2 weeks" expires 2026-08-23 — Sunday. That clock started when the SAR desk work was done on 08-09, and the Steve email is what stops it.
  • Fanstel's month has ten days in it. The asymmetry is unchanged and is the whole point: scoping an open filing costs them a paragraph, scoping a granted one costs a Class II permissive change that only they can file.

2026-08-21 (timeline change) — this block is explicitly carved out of the four-month delay, and the reason is worth stating. The new plan defers paying for certification until after the campaign, which is a sound decision about money. It defers nothing that is somebody else's calendar, and this block is the largest such thing in the project. Two items now carry Phase 1 milestone IDs of their own:

  • SEP-12, due 2026-08-31 — ask Fanstel to scope the open BM20C filing for portable body-worn use. Unchanged in substance from everything above; it simply now has a date and an ID, and the date is theirs, not yours.
  • SEP-13, due 2026-09-30 — open the WM02C change-of-ID conversation. New. This is the item most able to move the ship date on its own, and it is a negotiation with a company that took days to answer a one-line question, not a purchase you can schedule. It concludes at SHIP-05 by May 2027, and if it is still open then, September 2027 is not the ship date. Starting it in April 2027 alongside the lab booking is precisely how a five-month buffer becomes zero.

Six extra months help this block in one real way and one illusory way. Real: the BM20C grant has six more months to land, so the BC15C fallback becomes a decision rather than an emergency. Illusory: none of that time counts unless the two conversations above start now, because their duration is set by Fanstel's response latency and not by your calendar.

Both emails need a mail client and nothing else — no computer state, no blanks, no decisions. They were the two items this gap could least afford to leave sitting, and they are the two that would have cost the least to send from a phone.

✅ 2026-08-26 — checked against the FCC database for the first time, and the window this block has been racing is verified still open. Nobody had ever looked. Full note in docs/agent-notes.md; three results, in descending order of consequence.

  • No FCC grant for a BM20C exists, from any grantee. A site-wide product search returns "No FCC filing matches were found for BM20C", and Fanstel's grantee code X8W carries 36 authorisations of which none contains BM20 or 20C. ⚠️ This does not mean they haven't filed. An application is not public until it grants, so a negative is exactly what an on-schedule certification looks like from outside. What it does establish is the thing this block needs: the grant has not issued, so question 2 in drafts/fanstel-exposure-category.md is still free, with five days left in the month Fanstel named. The draft's own second line — "their FCC testing is open now; the whole value of this email is that it arrives before the filing closes" — was an assumption on 2026-08-12 and is now confirmed.
  • The BM15C ≠ BC15 warning below can be sharpened. X8WBM15C exists and was granted 2025-01-07 (BLE 6.0 module) — so your 2026-08-08 note was right that the BM15C is already certified, and it is a different grant from X8WBC15 (2025-07-25). Its exposure category is still unread, and that is the question that matters: the BC15's portable evaluation is what the fallback argument rests on, and nothing establishes the BM15C shares it. One lookup, same as the BC15's was.
  • Fanstel has granted nothing at all since 2026-03-20 (X8WBT840X). Five months, against a 2025 cadence of roughly one every six to eight weeks — X8WBM15C 01-07, X8WBC15 07-25, X8WBM05 09-03, X8WWM02C 09-18, X8WLR62X1E 09-19, X8WLR68E 12-05. It proves nothing about the BM20C, since a filing in progress is invisible. It is simply the only external evidence anyone has about the throughput of the company whose calendar SEP-13, MAR-05 and all of Phase 6 hang on — and it argues for starting the change-of-ID conversation now rather than on its 2026-09-30 due date.

✅ 2026-08-28, and again 2026-08-29 — re-checked twice, unchanged both times, two days left in Fanstel's month. Same 36 authorisations under X8W, none containing BM20; https://fccid.io/X8WBM20C returns 404; Fanstel's newest grant of anything is still 2026-03-20. The window has now stayed open for the entire seventeen days the draft has sat unsent, which is luck rather than planning.

⚠️ And the two dates are not the same date — three runs have written as though they were. SEP-12 is due Monday because Monday ends the month Fanstel named. Question 2 stops being free on the day the grant issues, which is an unrelated event with no notice and no relationship to the end of August: it could land before Monday or in October. Reading Monday as the expiry overstates this week and, worse, would make next week feel safe. The asymmetry is the argument, and it does not have a deadline attached — an open filing costs Fanstel a paragraph, a granted one costs a Class II permissive change only they can file.

Re-check before citing any of this: https://fccid.io/X8W takes ten seconds and mirrors the FCC's own search at https://www.fcc.gov/oet/ea/fccid.

⛔ 2026-09-20 — the ❓ above is answered, by events, the bad way. X8WBM20C granted 2026-09-11, mobile, with the identical 20 cm clause. Everything this block said about the asymmetry was correct and the window closed with the draft unsent — thirty days open, and it shut on day thirty-one. The block's own prediction is now the record: the exposure-category question stopped being free, and the BLE radio is the one it bites hardest, because wornness-gating cannot reach a radio that transmits while worn. The first step below has therefore changed character rather than lapsed: send it as a permissive-change / change-of-ID ask covering both modules, not as a scoping question. Its own block is at the top of Soon; the record is in docs/agent-notes.md, 2026-09-20. One genuinely good thing came with it — the grant number now exists, which was MAR-05's precondition and half of BLK-15.

Steps — Fanstel, today - [ ] Send drafts/fanstel-exposure-category.md. Two questions, one screen, no numeric blanks to fill — written to go today, because their filing is open now and question 2 stops being free once it grants - [ ] Start the FCC Grantee Code application, without waiting for a reply. Tens of dollars, real lead time, gates every filing downstream, and useful under every outcome except the best one (Module Grant Conditions.md §5.1) - [ ] Add to the other draft: the grant declares 0.17 W, your datasheet says 18.24 dBm average — which governs, and does the published backoff CONFIG reduce the certified maximum or only the typical? - [ ] Send fanstel-followup.md too, once the four numeric blanks are filled. It has been drafted and unsent since 2026-08-10 — which is exactly why the exposure question was split into its own email

Steps — Steve Koster / WLL - [ ] Send drafts/wll-steve-followup.md — accepts the SAR quote, books the call, and carries the seven items below as an agenda. Long on purpose: he offered a call, and most of what's open is TCB judgement rather than rule text. Item 1 is the wornness question and it decides the architecture; items 4a/4b are 30-second lookups that could make items 1–3 unnecessary - [ ] Accept the SAR quote he offered - [ ] Ask for the complete grant — the page he sent shows only rule part 15C (2412–2462 MHz), but its own grant note says the module is certified under two Part 15 sections. Is 5 GHz actually in there? FCC Lab Quote Responses.md §2 declares UNII-1 and UNII-3 modes against it - [ ] ⚠️ Ask the KDB 178919 question: guidance exists saying a permissive change may not amend an application that was represented as mobile-only. Is mobile → portable genuinely a Class II here, or will a TCB push it to a new certification? Largest dollar figure of anything open, and free to ask - [ ] Ask whether Washington Labs is a TCB, or only a test lab. Certifications are granted by a TCB; a lab does testing. It decides whether Steve can carry a change of ID and a permissive change end to end or whether you need a second organisation — and nobody has checked - [ ] Ask the two questions his reply left: wrist as an extremity (NT = 7.5 not 3.0), and coex arbitration vs summing the two radios — he assumed summing in passing without addressing the argument - [ ] Ask him to quote the BLE-only variant as a real alternative, not a contingency line - [ ] Ask the two questions the X8WBC15 exhibits left: what its grant says about co-location (expect the same multi-transmitter exception), and which antenna gain governs — the portable exhibit's 1.50 dBi or the mobile one's 6 dBi? - [ ] Take the call he offered — most of what's open is TCB judgement rather than rule text

Steps — documents - [ ] ⛔ Hold labs 2 and 3. The scope text declares 5 GHz modes that may not be granted and omits the permissive change that is now most of the work. Three comparable quotes for the wrong job are worth nothing - [ ] Re-run FCC Certification.md §5 at 170 mW, with the grant-condition gate above the arithmetic - [ ] Re-open the 2026-08-11 "v1 ships with WiFi" decision on the new cost — the WATCH_REMOVED reasoning is untouched and still right, but it was weighed against "8 dB of range or a SAR test"

Not affected: Concepts/FCC Respin.md. Every board item in it stands — none of this is drawable.

✅ That lookup is done — you did it yourself on 2026-08-11, and the answer is mostly good. The exhibits are in the vault at files/X8WBC15_rf_exposure_report.pdf and files/X8WBC15_MPE_report.pdf, both ISL report ISL-25LR090FMPE. Three findings, worked through in Concepts/Module Alternatives.md §5:

  • The property that mattered is confirmed. "According to §2.1093 this is a Portable device." The fallback module is authorised for use against a body — the exact thing X8WWM02C is not — and it is authorised that way today, from the vendor you are already talking to.
  • "With SAR" does not mean a SAR test was run. There is no measurement in the filing. It is a SAR test exclusion by calculation: 8.01 dBm + 1.50 dBi gain = 8.94 mW, (8.94 / 5) × √2.48 = 2.82 against a 3.0 threshold. Same practical outcome for a BLE-only build; different reason, and the reason is the next bullet.
  • ⚠️ The margin is 6%, and our own arithmetic was flattering it. FCC Certification.md §5 computed 2.5 for this case with no antenna gain at all. Fanstel's lab includes gain and declares zero tune-up tolerance to reach 2.82. Add the 1 dB tune-up our calculation assumed and it is 3.46 — not excluded. The BLE-only fallback still clears, but only at a near-zero declared tolerance, which is paid for in production yield. Corrected in FCC Certification.md §5 and filed to agent-notes.md.

Two things the exhibits don't settle, and both are still one lookup for Steve: what X8WBC15's grant says about co-location — expect the same multi-transmitter exception the WM02C carries, and for a single-radio build it may not bite at all — and why the two exhibits in one report use different antenna gains, 1.50 dBi in the portable evaluation against 6 dBi in the mobile one. At 6 dBi nothing is excluded at 5 mm.

Switching modules does not otherwise fix this — Concepts/Module Alternatives.md researched all 12 nRF54LM20A and 21 nRF7002 modules on the market. No nRF54LM20A module from anyone holds an FCC grant yet (Raytac "intended", Ezurio "early preview"), so the BM20C isn't behind — the whole part is. And the 20 cm clause is industry boilerplate, carried word for word by u-blox — complete with the same multi-transmitter exception. A wrist-worn product needs a permissive change whoever's module is on the board, and it needs it for the exposure category rather than for having two radios. Two things worth doing anyway are in that document's §7. ⚠️ BC15 ≠ BM15 — different modules, different FCC IDs, and only the BC15 has the portable evaluation.

  • In Progress
  • Done

Done when: Fanstel has answered the BM20C exposure-category question, and the route to a legal wrist-worn WM02C (change of ID, PC, or drop it) is chosen rather than assumed.

Notes:

❓ Wornness-gated WiFi — no longer optional: it's the only way WiFi goes on a wrist without a SAR test

needs human help · raised 2026-08-12 · BLK-15 AUG-12 AUG-13 · from your 2026-08-11 log

Written up as Concepts/FCC Respin.md §4.1, as you asked. Your idea: if the WiFi radio provably transmits only when the watch is off the wrist, the exposure category changes and the SAR problem goes away.

The product half is stronger than you framed it. firmware_spec_v3_nrf.md §1.5's three WiFi dependencies split exactly along your line — WATCH_REMOVED needs the radio only when the watch is off by construction; the anchor's WiFi and SNTP are a different unit's radio and are untouched; and the only casualty is getOnWifi/getOffWifi, which §1.5 already calls the least load-bearing and which your 2026-08-09 log had already offered the phone's GPS to replace. You lose the criterion you were willing to lose and keep the one that settled the WiFi decision.

The regulatory half is aimed at the right target — and after the 2026-08-12 correction above, it is aimed at the only target. X8WWM02C has exactly one condition a wrist device can't satisfy: ≥ 20 cm from all persons. Co-location is permitted. So this idea is not half a fix for two problems, it is a candidate fix for the single one.

It doesn't make the argument automatically, though. Off the wrist isn't 20 cm from a person — a watch on the nightstand beside a sleeping head is inches from one, which is the Sunrise Lock scenario itself. And a grant condition constrains the installation, not the duty cycle. Assume the permissive change is still required; what wornness plausibly changes is what that PC has to demonstrate, and whether a SAR test sits inside it.

One design correction worth having now, because it decides whether the feature works at all. You listed the IR sensor and the IMU as two ways to do the same thing. They aren't. The IMU route — "hasn't moved for several minutes" — puts a multi-minute delay in front of the most latency-sensitive message in the system, and the bypass works during it. Gate on IR. §4.1 works through why a conservative filing wants both signals and what ANDing them costs.

2026-08-12 — this stopped being an idea and became the decision. You asked whether a different WiFi part avoids the problem. None does, and none can (Module Alternatives.md §8.3): the SAR-exclusion ceiling at 5 mm is 9.6 mW and no WiFi radio is a 9.6 mW device, so every WiFi module carries the same 20 cm mobile condition. The ESP32-C3-MINI-1 grant was checked as the obvious counter-example and carries it word for word. Two ways to put WiFi on a wrist, and part selection is not one of them: a permissive change with a SAR test, or this. Treat it as a design requirement to settle rather than an option to explore.

And one cost nobody has priced: a radio that is off while worn is cold when it's needed. Association plus DHCP from a cold nRF7002 is seconds, and WATCH_REMOVED is the message where seconds matter. Folds into the range measurement already on the list — which should now measure time-to-delivered from a cold radio, not just range.

2026-08-31 — the sensor this whole argument gates on now has a driver, and it is reading crosstalk. The nRF port found the SAADC mapping empirically (AIN1 is the IR receiver; it is in no datasheet we hold) and discovered the swing is negative — the ITR8307's phototransistor pulls the node down under illumination, so more reflection means a lower raw reading, and impulse_worn_sample() returns dark-minus-lit to make "more reflection" a larger positive number. CONFIG_IMPULSE_WORN_THRESHOLD_MV is a guess at 150. On a desk with nothing in front of the sensor the difference was already 64 mV of emitter-to-detector crosstalk**, which is the noise floor this threshold has to clear. Nobody has put the board on a wrist. That measurement is ten minutes and it is the empirical foundation of the regulatory argument above — a wornness gate you cannot demonstrate is not a filing position, and §5.2's datasheet note already flags this sensor as the worn one.

2026-10-14 — v5 now ships the gate this block warned against. Spec v0.20 did two things on 10-13, both built and verified in Kconfig. §1.6 confines the watch's WiFi to removal escalation, so it transmits only after a not-worn edge. That is the wornness gate, by construction. And §6.4 makes the v5 worn signal IMU stillness (no movement above 400 for 300 s), because the IR pair can't work on v5: the receiver moved, and the enclosure crosstalk is 75–90 mV against 200 mV. Two consequences for the filing argument. First, a still, sleeping wrist reads as unworn, and §6.4 accepts that because it fails toward the alarm. For the regulatory argument it's the wrong direction: WiFi can transmit from a worn watch. Second, every removal now carries the five-minute latency flagged above. The firmware choice is defensible for enforcement. It doesn't support an "only transmits off-body" claim to a lab. Don't put the v5 build in front of Steve or a lab as the wornness-gated design; that needs the IR fix (a v6 item) or IR ANDed with IMU.

Steps - [x] Put the question to Steve, in the email or on the call he offered: if the host guarantees in firmware that WiFi only transmits off-body, does that change the exposure category for that radio — and does it do anything for co-location, or is the permissive change required regardless? ✅ 2026-08-12 - [ ] Set CONFIG_IMPULSE_WORN_THRESHOLD_MV from a real wrist — worn, not worn, and a watch lying face-down on a nightstand, which is the case that decides whether the gate is honest - [ ] If the answer is "it narrows the PC but doesn't remove it" — the expected one — decide whether removing the SAR test is worth the getOnWifi/getOffWifi loss - [ ] Only then does anything go in firmware_spec_v3_nrf.md; §1.5 currently records a WiFi commitment this would partly reverse

  • In Progress
  • Done

Done when: Steve has said whether a firmware-guaranteed off-body transmit condition changes the exposure category, and the idea is adopted or dropped on his answer.

Notes:

⚠️ The launch video's closing line — ship date fixed, pre-order still wrong

needs human help · raised 2026-08-12 · second defect found 2026-08-13 · half resolved 2026-08-21 · AUG-03 AUG-04 BLK-05 · from kickstarter-page.md §0.2, verified against the script and the live site

2026-08-21 (timeline change) — defect 1 is closed and defect 2 is not. The timeline change settled the ship date, so there is now one answer instead of three: target September 2027, communicate October 2027. Impulse Launch Video.md line 153 and kickstarter-page.md have both been corrected in place, and the script now also names the campaign date (1 March 2027).

Two things are left, and one is new. The pre-order half of the sentence is still wrong and still depends on the GATE-DEPOSITS decision below — nothing about the timeline change answers it.

⚠️ 2026-08-22 — and the correction itself needs cleaning up before you shoot. The ship-date fix was written inside line 153's > block, together with the ⚠️ flag and a parenthetical explaining what changed. kickstarter-page.md's own convention — which this script shares — is that prose in > blocks is copy, i.e. the words you read aloud. As it stands, line 153 is a spoken line with editorial notes embedded in it. Harmless while nobody is filming; a bad five minutes if it goes in front of a camera as written. Whoever resolves the pre-order half should rewrite the whole line as clean copy and move the provenance into a non-quoted note, the way the rest of the script does it. And the live website now says "Ships Q1 2027", which is wrong by three quarters rather than by a few weeks; website/ is outside the vault and no agent here may edit it. That is a one-line fix in HeroSection.vue:19 and it is currently the largest factual error on a page serving traffic.

Both problems are in one sentence, Impulse Launch Video.md line 153 — the payoff at the end of the video you are cutting this week:

"so: it ships around january to march of 2027, maybe sooner, and right now, the watch and anchor are available for pre-order at 40% off, on either my website or on kickstarter…"

1. The date. Three live assets, three answers:

  • launch-plan.md — target March 2027, communicate April
  • the script — "january to march 2027, maybe sooner"
  • the live site (HeroSection.vue:19) — "Ships Q1 2027"

The Kickstarter figure is the one that carries legal weight — an estimated delivery date on a campaign creates an FTC 30-day-rule obligation — so it should be the anchor and the other two should move to match it, not the reverse. kickstarter-page.md uses April 2027 on that basis. "maybe sooner" is the phrase to lose first: it is the one that reads as a promise and is the least defensible of the three.

2. ⚠️ The call to action points at two things that do not exist (new, 2026-08-13, verified). The script sends viewers to a pre-order on the website or on Kickstarter, and:

  • The site has no order path. Pre-orders were deleted on 2026-08-09 — OrderPage.vue is gone, and the hero now says "No card, just an email." That was the right call (launch-plan.md §13 risks 12 and 18) and the site is internally honest; the script is what didn't move with it.
  • There is no Kickstarter page, and when AUG-03 puts one up it is a pre-launch page, which collects follows. You cannot pre-order on one.

The number checks out, at least — 40% off is the early-bird tier, PricingSection.vue:92, first 400 orders at $119. So the discount is real; the transaction isn't.

This is the most expensive kind of copy error you can ship, because it is a promise to take money in a video published under your own face, and the fix costs one sentence today. It also collides with GATE-DEPOSITS below: the honest replacement depends on what you decide deposits are and where they live, so decide that first and write this line second.

Steps - [ ] Confirm April 2027 is the date you want to communicate - [ ] Rewrite line 153's CTA to match what will actually exist the day the video goes up — email capture, a pre-launch follow, or a $15 reservation if GATE-DEPOSITS is settled by then - [ ] Fix the launch video script before the cut (both halves are the same line) - [ ] Fix the site's ship date (HeroSection.vue:19)

  • In Progress
  • Done

Done when: one date appears on the campaign page, the video and the site, and the video's CTA names something a viewer can actually do.

Notes:

⚠️ A certifiable WiFi watch exists that doesn't need Fanstel — know it before you negotiate

needs human help · raised 2026-08-12 · BLK-15 AUG-12 · from your BC/BM series question

Your read was right and sharper than the document it corrected. Fanstel certifies the wrist-oriented BC series for the wrist and the BM series for everything else, the BC line stops at the nRF54L15, and there is no Fanstel part that is both portable-certified and able to host an nRF7002. Written up as Concepts/Module Alternatives.md §8.

The RAM half is verified and it's worse than "tight." Nordic's own figures: nRF7002 station mode needs 222 KB of RAM against the nRF54L15's 256 KB total — and Ezurio publish an FAQ saying you get less than 256, because the FLPR core reserves some. Nordic also state that BLE/WiFi coex is not supported on the nRF54L15, with a reported ble_coex RAM overflow, and recommend the nRF5340 for a simultaneous design. That settles the question §7.3 had left open since 2026-08-11: no nRF54L15 from any vendor can host an nRF7002, and the reason is Nordic's silicon, not Fanstel's module.

Answering your question B: no — and not on exposure category. None of the twelve nRF54LM20A modules is FCC-certified at all (Raytac "intended", Ezurio "early preview", Fanstel in testing), so there is nothing to be portable-certified. On the nRF54L15 side there is a second portable-approved option already in §5's table: u-blox NORA-B2, approved in its integration manual for "mobile and/or portable host platforms", with a documented change-of-ID and a printed commitment to supply the approval letter. ⚠️ That claim is vendor documentation — XPYNORAB2 has never been looked up, and it's worth adding to Steve's list.

Answering your question A: the nRF7002 is a companion IC — your MCU runs the entire WiFi stack, which is why it costs 222 KB. Offload modules run the stack on-module and cost the host kilobytes: TI CC3200MOD/CC3235MOD, Inventek ISM433xx, Microchip ATWINC1500/1510, ST SPWF04Sx, or an ESP32-C3 as a co-processor — where you already have firmware experience. With one of those, BC15C becomes a viable host again.

But the important finding is the one that closes the door on part-shopping — see the wornness block in Soon. No WiFi module is portable-certified at usable power, from anyone, because the 5 mm exclusion ceiling is 9.6 mW. Switching WiFi vendors does not buy the exposure category.

So: BC15C (or NORA-B2) + an offload WiFi module + a wornness gate is a coherent architecture with a portable-certified BLE radio, no coex requirement, no 222 KB, channel sounding intact, WATCH_REMOVED intact — and BLK-15 dead. It costs a new BLE module, a new WiFi module and driver, a second respin, the 256 KB you bought 512 KB to avoid, and getOnWifi/getOffWifi.

This is not a recommendation to switch, and nothing should be ordered on it. Its value is that you know it exists while you wait for Fanstel. If the BM20C comes back portable-certified, none of it is needed — and it makes a refusal from Fanstel expensive rather than fatal, which is worth having in mind before you ask them for a favour.

2026-08-12, second pass — the architecture is worked out and it rests on one unconfirmed reading. §8.4.2 names ESP32-C3-MINI-1 (2AC7Z-ESPC3MINI1) as the co-processor, running stock ESP-AT over UART so there is no second firmware to maintain — its grant was read in full, its WiFi power is 0.071 W against the WM02C's 0.17 W, and it is slightly smaller than the module it replaces. On your "approved modules list" question: there is no companion-module whitelist. Approved antenna lists are real; co-location is a procedure, and both grants explicitly permit it subject to the FCC multi-transmitter procedures — the ESP32 grant says so in as many words, which is a second independent confirmation of the 2026-08-12 correction.

⛔ Six of the seven compliance obligations are satisfiable on paper. The seventh is the whole thing. The ESP32-C3 grant says "Separate approval is required for all other operating configurations, including portable configurations with respect to 2.1093." A wristwatch is a portable configuration. The wornness argument says the radio isn't in one, because exposure only exists while transmitting — coherent, and not what the grant says on its face. That is the same shape as the mistake made on 2026-08-11. Do not design around it until a TCB says yes.

Steps - [ ] Read Module Alternatives.md §8 — it is the whole answer and this block is the pointer - [ ] Add XPYNORAB2 to the list of grants for Steve to look up - [ ] Ask Steve the row-1 question — does a firmware-guaranteed off-body transmit condition take a WiFi module out of "portable configuration", or is a wrist device portable regardless of duty cycle? Same question as the wornness block; this architecture is a second thing riding on it - [ ] Ask what a composite investigation adds to the quote — host tested with all transmitters installed (KDB 996369 D04). ⚠️ apps.fcc.gov 403s here, so that requirement comes from secondary summaries and has not been read in the primary text - [ ] Decide nothing until Fanstel answers. This is a contingency to hold, not a plan to start

  • In Progress
  • Done

Done when: Fanstel has answered, and this is either discarded as unnecessary or promoted to a plan.

Notes:

⚠️ 8 hours doesn't reach 5:30pm either — the example day still doesn't close

needs human help · raised 2026-08-11 · BLK-04 AUG-01 AUG-03 AUG-04 · from filing your battery decision

Your decision is filed and it closed the 9pm half. impulse_overview.md now says 8 hours minimum, the 9pm sentence is deleted, the strikethrough is gone, and firmware_spec_v3_nrf.md §6.3 carries 8 h as a floor rather than a target — because a floor is what can be advertised. launch-plan.md §12.11 and §13 are updated.

The arithmetic still doesn't work, and it's worse than before rather than better. BLK-04 asked for either the example day or the figure to change. Both changed — and they moved apart:

  • Full at 6am, guaranteed 8 h → flat at 2pm.
  • The example day still enforces a gym-arrival window at 5:30pm.

That's three and a half hours past the floor, in the same document that now advertises the floor. The 9pm window was the last item in the day; 5:30pm is the latest one that matters, and nobody has looked at it because the blocker was written about 9pm.

This is urgent for a reason that has nothing to do with hardware: you are cutting the launch video and standing up the pre-launch page this week, and both inherit whichever answer you give. Copy is being written right now against a day that doesn't close.

Three ways out, all available today, none of them a firmware question:

  1. Move the gym window earlier in the example day — 3pm or 4pm reaches comfortably on 8 h.
  2. Put a top-up in the example day — "it charges while you shower" or similar. Honest, and it makes the charging rhythm part of the product story rather than a caveat.
  3. Advertise a figure that reaches 5:30pm — 12 h from 6am. You've said 10–12 h is the aim but not guaranteed, so this is the option that spends credibility you may not have yet.

If there's no answer, nothing gets written and the constraint stands: firmware_spec_v3_nrf.md §6.3 and launch-plan.md §12.11 both now forbid copy that pairs the 5:30pm window with the 8-hour figure.

Steps - [ ] Pick one of the three - [ ] Update impulse_overview.md's example day to match - [ ] Check the launch video script and the website for the same day before either ships

  • In Progress
  • Done

Done when: the example day and the advertised battery figure describe a day that is actually possible.

Notes:

⚠️ "The alarm you can't snooze" — but donning grace is configurable to 30 minutes

needs human help · raised 2026-08-11 · BLK-05 AUG-04 · from the 2026-08-10 log, verified against the spec

You wrote that you "didn't show the 5 minute snooze feature, because i figured its not necessary and just adds unnecessary complexity, although i did mention it verbally in the script." Leaving it out of the footage was the right call. The problem is the words, not the footage.

The claim, in two places. impulse_overview.md §Sunrise Lock: "it is the alarm you can't snooze." Impulse Launch Video.md line 23, the payoff after the 35-second cold open: "so that's an alarm you can't snooze."

What the feature actually is. donningGraceS (firmware_spec_v2.md §5.4.4) suppresses watch-side enforcement for N seconds after the watch is put on, and quiets the anchor via WATCH_WORN the moment you don it. Sunrise Lock's worked example uses 300 s. The app clamps the field to 0–1800 (§5.4.4, spec line 389) — so a user can configure thirty minutes of silence, obtainable by putting the watch on and getting back into bed.

The honest counterargument, which is why this is a question and not a defect. You cannot snooze it from bed — you have to actually put the watch on, and enforcement resumes by itself with no further input. And the duration is set by past-you in the app, which is the product's whole thesis rather than a hole in it. That is a defensible reading. It is not obviously the reading a Kickstarter comment thread will reach, and you called it "the snooze feature" yourself — which is the tell.

Two fixes, and they're cheap now and expensive after the video is cut:

  • Copy: "an alarm you can't snooze from bed", or "the only snooze is one you set last night." Both keep the punch and survive someone reading the spec.
  • Bounds: 1800 s is a BLK-02 primitive-bounds question wearing a different hat. Thirty minutes of grace on a wake-up commitment is not a grace period, and nothing currently stops it.

2026-08-12 — one document has now picked a side, which makes deciding this more urgent rather than less. kickstarter-page.md ships "the alarm you can't snooze from bed" in its blurb, with a note at §0.1 explaining that the last three words are load-bearing. That is the fix this block recommended, adopted in one place. impulse_overview.md, marketing_strategy.md, launch-plan.md §1 and the launch video script all still carry the unqualified version — so the campaign page and everything around it now disagree. Pick one and make the other four match.

2026-08-13 — it is already published, in two places this block hadn't counted.** The claim is live on impulsestore.net right now, and the two instances are not equally exposed:

  • src/components/home/SunriseLock.vue:11 — "The alarm you can't snooze, because it isn't on your nightstand. It's the whole room." The subordinate clause is doing the same work as the kickstarter page's "from bed": it says why, and the why is true. This one is close to defensible as written.
  • src/components/home/UseCases.vue:14 — "The snooze button was always the problem; now there isn't one." This is the flat version, and "there isn't one" is the sentence a 30-minute grace embarrasses.

The script's two instances are lines 23 and 49. So the count is six places, not four, and two of them are serving traffic today.

Steps - [ ] Decide whether the claim as written survives contact with a 30-minute grace - [ ] If not, fix the line in impulse_overview.md §Sunrise Lock and the launch video script (lines 23 and 49) before the video is cut — plus marketing_strategy.md and launch-plan.md §1, which carry the same sentence - [ ] Fix the live site: UseCases.vue:14 is the one that needs it; SunriseLock.vue:11 already carries its own justification - [ ] Consider a tighter clamp on donningGraceS for wake-type templates — folds into BLK-02, which now has a sharper version of this problem in it

  • In Progress
  • Done

Done when: the strongest claim in the marketing and the widest setting in the app tell the same story.

Notes:

Log the subscriber count — the list is starting from zero and nothing is measuring it

human only · raised 2026-08-11 · AUG-02 GATE-EMAILS CAD-REVIEW · from your Kit fix

Auto-confirm is on — that's filed and the block is closed. What the fix also told us is the number nobody had: "nothing is lost — i didnt have any emails besides test emails anyways." So as of 2026-08-10 the list held test subscribers only, and GATE-EMAILS starts from approximately zero with 2,500 to go and 59 days to the gate check.

That's fine — it's day 2 of a 12-week plan. What isn't fine is that this is the third run in a row where no number reached a log. Timeline.md is unambiguous that emails per week, trending is the one metric that decides whether the hook is right, and a trend needs two points. The instrument works. It's a login.

2026-08-12 — fourth run, still one number, and it is now four days old. This is the cheapest open item in the file and the only one that has been open every single run. The Friday numbers review (CAD-REVIEW) is 2026-08-14 — two days — and it is the first one that will have anything in it.

2026-08-13 — the first CAD-REVIEW is tomorrow, and the one number it needs has still never been written down. Fifth run, one data point, five days old. A review with nothing in it is not a review; log the count today so tomorrow's has two.

2026-08-14 — the review is today. Sixth run, one data point, nine days old. content-push.md §12's Friday dashboard has six rows and exactly one of them can be filled right now — this one. The other five are empty by construction: no deposits mechanism, no posts yet, no pre-launch page, one creator email. So today's review is a login and a single number in the log, and that is a complete review for week 1.** Do that much and next Friday's has a trend in it.

2026-08-17 — the first CAD-REVIEW has been and gone, on Friday 08-14, and nothing records whether it happened. Seventh run, one data point, seven days old. The trend is still a single point, and the second point was supposed to arrive on the day the review fell. Friday 2026-08-22 is the next one, and it is the first that could produce an actual trend rather than a number.

2026-08-21 — that Friday is today; 08-22 is a Saturday and the last run had the date wrong. Eighth run, one data point, eleven days old. This is the second CAD-REVIEW and it still has one number available to it, the same one. Nothing about the four-day gap touches this item — it is a login and a number, from any device, including the phone. It has been the cheapest open thing in this file on every run it has existed, and it is now the only thing standing between two reviews and a trend.

2026-08-29 — that Friday was yesterday, and it passed like the other three. Tenth run, one data point, nineteen days old. GATE-TRAJECTORY is a trajectory and a trajectory needs two points; there is one, and it predates the site being live in its current form. This remains the cheapest open item in the file and the only one open on every single run** — and it does not need to wait for a Friday. Even a zero is a data point; especially a zero.

Steps - [ ] Write the subscriber count into today's daily log — even if it's 0, especially if it's 0 - [ ] Same again next Friday, 2026-09-04, at the CAD-REVIEW review — (08-14, 08-21 and 08-28 have all now passed) - [ ] Finish email-capture-setup.md §4's acceptance test — specifically whether utm_source actually stores, since the free plan may not carry custom fields. Blank fields mean no attribution while believing you have it

  • In Progress
  • Done

Done when: two counts exist in two logs, a week apart.

Notes:

AUG-03 — the copy exists, the page still doesn't

human only · AUG-03 AUG-04 GATE-DEPOSITS DEC-01 · due 2026-09-30 (was overdue; window reopened by the 2026-08-21 timeline change)

2026-08-22 (timeline change) — this is no longer overdue, and the reason it slipped is still worth one line. AUG-03 now runs to 2026-09-30, 39 days. The notes below were written while it was a week past a closed window; read them for the queue behind it rather than the urgency. One thing did get harder: this page is still the likeliest home for GATE-DEPOSITS, and DEC-01 now opens reservations against a September 2027 ship — a nine-month hold. See that block below before building the page around a deposit.

AUG-01 is done and this block has shrunk to what's left. The 2026-08-11 log settles the orientation question that was open for three runs: 5 vertical + 2 landscape Sunrise Lock takes, and 2 vertical + 2 landscape Phone Dock takes, on top of 2026-08-10's. Seven vertical clips against a bar of 4–6, so AUG-06's 3×/week cadence has something to post on 2026-08-16.

The hard part of AUG-03 is also done, and it isn't the part that closes the milestone. docs/marketing/kickstarter-page.md is a full 272-line campaign page — title and blurb, tiers, risks, the FTC disclosure, an FAQ, with the claims fence restated at the top. What it can't do is stand the pre-launch page up, and no log in four days mentions that happening. Your own plan puts it after the video edit.

Two things in the draft need you before it ships, both in its §0.2: the ship-date inconsistency (its own block above) and whether the main tier is $125 or $135 — it uses $135, per launch-plan.md §4's own recommendation.

2026-08-13 — two days left, and the 2026-08-12 log's goals were a fifth day of shooting. Studio shots, location shots, action shots — all content, none of it this. That is not a criticism of the day; it is the observation that five consecutive logs have planned or recorded filming and none has mentioned the page**, while your own 2026-08-10 plan put the page third, after the audio edit and the cut. Whether 08-12's shots happened isn't recorded either way. If the page slips past Saturday, that is ordinary slippage on the one Phase 1 milestone with a hard external artefact behind it — worth knowing you're choosing it rather than discovering it Sunday.

On the claims fence: launch-plan.md §10 forbids showing vibration and the LED ring on one unit. You cannot violate this with footage and it's worth knowing why — DISABLE_MOTOR 1 compiles the motor out entirely on the ESP32 watch so the ring can own GPIO 10 (main.cpp:46). The "buzzing" you filmed is the buzzer on GPIO 21. The footage is safe; the script is the thing to check before the cut, since no frame that exists can support a vibration claim.

2026-08-17 — the window closed on Saturday and this was never mentioned in a single log. Five logs planned or recorded filming; none mentioned the page. That is ordinary slippage on one milestone and it is behind you now — nothing is gained by treating a closed window as an emergency. What is worth recovering is the reason.** A milestone that slips by decision teaches you something about the plan; one that slips by attention teaches you nothing, and right now nothing in the record distinguishes them. One line in a log fixes that permanently. Meanwhile the queue behind it is unchanged: this page is the likeliest home for GATE-DEPOSITS, and it carries the ship-date decision the launch video also needs.

2026-08-21 — a week overdue, and the queue behind it got longer rather than shorter. Nothing has changed here; the machine was off for four and a half days. What's worth noticing is that this milestone is no longer competing with Week 2 — it is competing with Week 3, which opens Sunday with AUG-07, AUG-08 and CAD-CREATOR's 20 emails a week. AUG-03 does not get an emptier week by waiting, and it hasn't for three weeks running. The 272-line copy is still done and still cannot stand itself up.

2026-08-14 — one day left, and no log has been written for two days. Nothing has changed here since yesterday: six consecutive logs have planned or recorded filming, none has mentioned this page. The choice is now tonight's rather than the week's. If it slips, it slips — say so in a log**, because the thing that costs you is discovering on Sunday that Week 1 closed with one of its three milestones untouched and nothing recording why. Sunday also opens AUG-04, AUG-05 and AUG-06 simultaneously, so this does not get a quieter week to land in.

Steps - [ ] Stand the Kickstarter pre-launch page up — and decide first whether deposits live on it; see the block below - [ ] Settle the two §0.2 decisions the page copy is blocked on: ship date, and $125 vs $135 - [ ] Edit the audio and cut the video (the b-roll is now shot) - [ ] Check the script for any wrist-vibration claim, and for the ship date, before you cut

  • In Progress
  • Done

Done when: the pre-launch page is live and taking follows.

Notes:

⚠️ GATE-DEPOSITS has no mechanism — and now it has a nine-month hold problem too

needs human help · raised 2026-08-10 · complicated 2026-08-21 · GATE-DEPOSITS DEC-01 AUG-03 · from email-capture-setup.md §7

2026-08-21 (timeline change) — more time, and a genuinely harder question. Reservations move from mid-September 2026 to 1 December 2026 (DEC-01, was SEP-02) and the count is checked at FEB-06 on 2027-02-14 (was OCT-08). That is fourteen weeks to gather 250 instead of six, which is the easy half.

The hard half is new: a $15 deposit taken on 1 December 2026 against a September 2027 ship is a nine-to-ten-month hold. That is well outside the ~120-day chargeback window launch-plan.md §12.12 warns about, and long enough that a processor may impose a rolling reserve — on exactly the money that was supposed to pay for the pre-scan. This should change the decision below, not just its date. Before defaulting to a Stripe payment link that captures cash, ask a processor whether an authorization now, capture at campaign launch arrangement is available; Kickstarter's own pre-launch page (§7's suggestion) sidesteps the question entirely by never taking money, at the cost of the conversion evidence that makes deposits worth having in the first place. That trade is the decision, and it is yours.

Removing pre-orders on 2026-08-09 was right — launch-plan.md §13 risks 12 and 18 both say so, and the reasoning is written up properly. But the thing that was supposed to replace them doesn't exist. DEC-01 opens $15 refundable reservations on 1 December 2026, and FEB-06 on 2027-02-14 counts 250 of them as one of three gates.

Deposits are also the gate with the strongest evidence behind it: deposit-holders convert at 40–60% against 3–5% cold. It is the wrong one to lose by default.

The decision, which is yours: where do deposits live? §7 suggests Kickstarter's own pre-launch page rather than the site, which would fold this into AUG-03 and avoid rebuilding a checkout you just deleted. The alternative is a $15 Stripe payment link on the site — which works, and reopens the traffic-splitting problem §13 risk 18 objects to.

2026-08-11 — AUG-03 is now days away and this is still undecided. If deposits are going to live on the pre-launch page, that is a thing to know while building it, not after.

Steps - [ ] Decide: Kickstarter pre-launch page, site payment link, or something else - [ ] Whichever it is, put a date on it that is before mid-September - [ ] Write the refund promise down before taking the first $15 — it's the whole reason a deposit isn't a pre-order

  • In Progress
  • Done

Done when: a deposit can actually be placed, and launch-plan.md §4 says where.

Notes:

❓ SAR: pay for the test, or cut WiFi power 8 dB? — your WiFi decision put this on the critical path

needs human help · raised 2026-08-09 · promoted 2026-08-11 · AUG-12 AUG-13 BLK-15 · from the SAR analysis

You decided v1 ships with WiFi, and that decision is filed (firmware_spec_v3_nrf.md §1.5, launch-plan.md §5, NRF Redesign.md §A4, BLK-15). It was the right call for the right reason — WiFi is the transport WATCH_REMOVED needs, so dropping it reopens the Sunrise Lock bypass rather than merely costing two criteria.

It also promoted this question from hypothetical to load-bearing. Concepts/FCC Certification.md §5: 2.4 GHz WiFi cannot be excluded from SAR testing at Fanstel's declared power — ratio 26.2 against a threshold of 3.0, and it doesn't come down at any separation a watch can offer. Three ways out, and route 3 is now closed by your decision:

  1. Cut declared TX power to ≤ +9.8 dBm in firmware. Free, no test, no schedule cost — but roughly 8 dB off WiFi range.
  2. Test SAR. ~1–2 weeks, five figures, plus failure-and-retest risk.
  3. ~~Ship BLE-only.~~ Ruled out 2026-08-11.

⚠️ 2026-08-12 — read the grant-conditions block at the top of Soon before acting on any of the three. Washington Labs' reply reframed this: the ratio was never the binding constraint, the grant declares 0.17 W rather than the datasheet's 18.24 dBm (ratio 53, not 26.2), and route 1 is not available to you at all — an integrator has no standing to redeclare a module's certified maximum. All three routes now pass through a permissive change. What's below is still the right shape of the decision and the range measurement is still the cheap input to it; the numbers and route 1 are superseded.

The sting is that route 1 spends exactly what you just paid to keep. The longest-range demand in the system is WATCH_REMOVED reaching an anchor two floors away — that is the whole reason WiFi survived — and route 1 takes 8 dB off it. Choosing route 1 without knowing the range budget risks buying the module and then quietly disabling the thing it was bought for.

The measurement that makes this answerable is cheap and available today, on hardware that exists. Nobody has measured what WiFi range WATCH_REMOVED actually has on the ESP32 build. It's a datagram, a laptop, and a walk downstairs. It is the input to a five-figure decision.

2026-08-12 — the rig for this exists and has never been run. ImpulseFirmware/WatchRangeTest and AnchorRangeTest were built on 2026-08-11 to answer exactly this, with per-300 ms-slot coverage on the LED ring over a 12 s window and a coded-PHY set alongside the 1M baseline. agent-notes.md records that no board had been flashed. No daily log mentions them at all. Flashing two boards and walking downstairs is the whole measurement.

Steps - [ ] Flash WatchRangeTest / AnchorRangeTest and measure WATCH_REMOVED's real range — two floors, the actual house - [ ] Measure time-to-delivered from a cold radio while you're there — the wornness-gating block needs it and it's the same walk - [ ] Work out what 8 dB does to that figure (roughly 2.5× the distance, free-space; less through floors) - [ ] Choose route 1 or route 2, and record the declared maximum in firmware_spec_v3_nrf.md §1.1 - [ ] Make sure the lab quotes price both (already asked — see the Fanstel/labs block)

  • In Progress
  • Done

Done when: one of the two routes is chosen, and firmware_spec_v3_nrf.md §1.1 records the declared maximum.

Notes:

⚠️ Draw and order the respin — antenna keepout, and the power tree in the same spin

human only · raised 2026-08-09, merged 2026-08-11 · OCT-10 AUG-14 BLK-03 BLK-15

2026-08-21 (timeline change) — this is the item the extra six months were bought for. It now has a milestone ID (OCT-10, due 2026-11-30) and a real window instead of being squeezed between a board arriving in August and a certification in December.

Two things follow. AUG-14 (validate Board V1) runs to 2026-10-31 rather than three weeks, which matters because the power-tree failure behind three of five dead prototypes takes days to appear — "leave it powered for a fortnight and see" is now an available experiment, and it wasn't before. And this respin is the board that gets certified: SHIP-03's pilot run in April 2027 builds it, and launch-plan.md §12.6 is certifying the wrong board revision. There is now enough calendar for V1 → find the fault → respin → trust it, which is the first version of this sequence that was ever schedulable.

Written up in full as Concepts/FCC Respin.md (you asked for it in the WiFi block's notes — "with everything i have to do for this respin"). It answers both items on your 2am list, adds the three you were missing, and ends in a checklist. This block is the tracker; that document is the content.

Your two items, answered. The antennas do both have to hang off an edge — and not the same edge, because 42 mm of board gives at most 20 mm of separation against the 30 mm both datasheets ask for. So: opposite edges, diagonally offset. Your routing worry inverts — splitting the modules frees the contiguous 19 × 23 mm block they currently share, which is where the room for everything else comes from. The real cost is a longer QSPI run.

What wasn't on your list. The BM20C deviates identically (0.6 mm short of the same edge — it isn't just the WiFi module). The power tree has to go in this spin: U1 pin 2 lands directly on /VBAT with no switch, no fuse, no current limit, which is how a chafed servo lead flattened a pack and killed a regulator on 2026-08-10. And the outline shrinks to ~32.6 × 42 mm, which is an enclosure question nobody has opened.

2026-09-15 — drawing started 2026-09-14; see the ⚠️ placement block at the top of Soon. No step below is ticked, because none can be verified as done from the files: the modules moved, but not to the listed edges, and the power-tree parts are not in the netlist.

2026-10-06 — ordered and built. Two v5 boards ran on 10-05. Measured against this block's done when: the antennas overhang, and range improved ~18 dB per board, but on the same edge; the servo rail is unprotected and the VBUS parts are absent. So the milestone's action happened and this block's condition did not. Whether that makes a v6 is the ❓ at the top of Soon. Nothing below is ticked; "Next batch ordered" is true, but ticking it would read as the board this block describes.

Two things are outstanding that would change the layout, and both are already asked for: Fanstel's answer on module separation (item 6 of the draft, unsent) and the EV-WM02C reference Gerbers. Neither blocks the power-tree changes, which are independent of every antenna question and are the ones that decide whether the next batch survives being used.

Steps - [ ] Servo stall current written down — it picks the part - [ ] Send the Fanstel email; wait on item 6 if the schedule allows - [ ] Pull EVM-WM02C-VB-gb.rar and diff the keepout against Fanstel's own layout - [ ] Check the BM20C footprint against Fanstel's library — drawn silkscreen 14.8 mm vs datasheet 15.8 mm, and the whole east keepout is dimensioned off it - [ ] WM02C → west edge north, antenna overhanging - [ ] BM20C → east edge south, antenna over a ≥ 5 mm void - [ ] No signal traces under either module; no ground plane under either antenna - [ ] Nothing in the WM02C's extra 2.3 mm past the WM02E courtyard - [ ] Re-cut the outline; confirm against the enclosure - [ ] Servo rail: current-limited load switch or fuse — plus a GPIO and a spec entry if it's a switch - [ ] Input capacitor on VBUS at U5 pin 1; Schottky VOUT→VIN; C5/C18 to 10 V or ceramic - [ ] Re-export the netlist and re-verify firmware_spec_v3_nrf.md §2 before ordering - [ ] Next batch ordered

  • In Progress
  • Done

Done when: a board is ordered whose two antenna areas are both compliant, whose servo rail survives a shorted lead, and whose layout has been diffed against Fanstel's reference Gerbers.

Notes:

Send the Fanstel and FCC-lab emails — both drafts are written and neither has gone

automatable · raised 2026-08-09 · AUG-12 BLK-15 · from the 2026-08-09 log

"draft an email for me to send to Fanstel, and draft one for the 3 labs. placeholders in the email are fine. put it in /drafts one doc per email." Both drafts exist. Nothing has been sent.

2026-08-21 (timeline change) — deadlines, not urgency. AUG-12 (three lab quotes) now runs to 2026-09-30, and quotes age well — the quote is not the certification, and getting three is only worth anything if all three answer identical scope text. The Fanstel half did not get more relaxed: SEP-12 is due 2026-08-31 because their filing month ends then, and SEP-13 (the change-of-ID conversation) is due 2026-09-30. Both are in the carve-out described in the WM02C grant block above. AUG-13's "ask the lab within 2 weeks" clock still expires 2026-08-23 and the Steve draft is what stops it.

Everything these emails need to say is already written down — the Fanstel chase block below has the full question list, and Concepts/FCC Certification.md §5 has the SAR numbers the lab email should state rather than ask.

One thing to get right in the lab email: ask for the BM20C quote and the BLE-only delta, and expect that delta to come back negative on the RF-exposure line, because a BLE-only build needs no SAR test at all. That delta now prices a contingency rather than an option — you decided on 2026-08-11 that v1 ships with WiFi — which is a reason to still ask for it, not a reason to drop it.

2026-08-09 — much of the lab email is now written. Concepts/FCC Lab Quote Responses.md holds paste-ready answers to a lab intake form: description, all operating modes, cable counts, dimensions and electrical, and an additional-information block carrying three TCB questions and the BLE-only delta request. drafts/fcc-lab-quote-request.md should wrap that rather than restate it, or the two drift. Two blanks in it are yours: cell capacities and enclosure dimensions/weights.

2026-08-10 — lab 1 has already had it. The 2026-08-09 log says you found a local lab and filled in its free quote form; that's Washington Laboratories (wll.com), logged in the responses document's new "Where it has been sent" table. Two labs to go, and the value of three quotes is entirely in the scope text being identical. One caveat on lab 1: the form was reached from their Part 87 (aviation) page, so confirm on the reply that they quoted Part 15 Subpart B plus the RF exposure evaluation.

2026-08-10, later — item 1 of the Fanstel draft is already answered and has been rewritten. They emailed to say both modules shipped, so that question became a tracking-number ask; the grant questions are untouched and are still the reason to send it.

2026-08-11 — item 6 is now blocking the respin. The Fanstel draft asks whether there's a required separation between the two antennas. Concepts/FCC Respin.md §5 names that answer as the one thing worth waiting for before drawing, because the inferred 30 mm is what forces opposite edges and the shrunken outline.

2026-08-24 — one clock expired yesterday and the other has seven days left in it. Both drafts are still stamped 2026-08-12 15:15** — twelve days — with no blanks left in the Steve one and no decision in front of either.

wll-steve-followup.md missed its window. AUG-13's SAR analysis was done 2026-08-09 with a two-week ask on getting a lab to sanity-check it; that ran out 2026-08-23. Nothing is lost that a fresh email can't recover — it simply no longer arrives inside the interval the analysis itself specified, and Steve offered the call.

fanstel-exposure-category.md has the shorter fuse, and the fuse is not yours. SEP-12 is due 2026-08-31 because Fanstel said on 2026-08-04 that BM20C testing completes "this month." Scoping an open filing costs them a paragraph; asking after it grants costs a Class II permissive change that only Fanstel may file. That asymmetry is the whole argument for sending it now rather than later — the due date passed on 08-31, and the free window it actually depends on closes on the grant date, which is not on any calendar you hold.

2026-08-26 — the fuse is verified, and it has five days left. Both drafts are still stamped 2026-08-12 15:15 — fourteen days. This run checked the FCC database and the BM20C grant has not issued, so fanstel-exposure-category.md's premise holds: the question it asks is free while the filing is open and costs a Class II permissive change once it grants. That is no longer an inference from Fanstel's email — it is the public record as of today. The email needs sending, not editing**; it has no blanks and no decision in front of it.

2026-08-29 — seventeen days unsent, two left in Fanstel's month. Both drafts still stamped 2026-08-12 15:15. The database was re-checked today and the grant still has not issued, so the premise holds for a fourth run. There is nothing to decide and nothing to fill in. One correction to what this note said yesterday:* "after Monday its month is over" is true and is not the same as "after Monday it's too late."* The question stays free until the grant issues, whenever that is — so Monday is a prompt, not an expiry, and missing it is a reason to send on Tuesday rather than to stop.

Steps - [x] drafts/fanstel-followup.md — the grant, the ship date, the grant conditions, the fallback part number ✅ 2026-08-10 - [x] drafts/fcc-lab-quote-request.md — scoped, SAR position stated, three TCB questions asked, fallback delta requested ✅ 2026-08-10 - [x] Placeholders marked clearly so you can fill them in one pass ✅ 2026-08-10 (4 in the Fanstel email, 4 numeric blanks + [LAB NAME] in the lab one) - [x] Candidates for labs 2 and 3 researched and named ✅ 2026-08-10 - [ ] Fill the four numeric blanks — watch cell mAh, anchor cell mAh, two enclosure weights, mains adapter make/model/FCC ID - [ ] Send the Fanstel reply - [ ] Send labs 2 and 3, and the short scope correction to lab 1

  • In Progress ✅ 2026-08-10
  • Done

Done when: both drafts are in vault/drafts/ and you've sent or edited them.

Agent log — 2026-08-10: Wrote drafts/fanstel-followup.md and drafts/fcc-lab-quote-request.md (/todo). The clarification round settled two things: US-only market scope and name specific candidate labs. Decisions taken after that:

  • The lab draft wraps FCC Lab Quote Responses.md rather than restating it — a covering email plus a paste order, with the technical answers copied verbatim from that document. Two documents saying the same thing in different words is how three quotes stop being comparable. Reversible by inlining the blocks, at drafts/fcc-lab-quote-request.md §3.
  • US-only recorded in two places: launch-plan.md §5 (the decision and why it doesn't foreclose either market) and the responses document's §0 checkbox table, where CE and IC flip from conditional to unchecked. The reasoning is that a conditional left on a quote form becomes a line item.
  • Three emails, not two. Lab 1 needs a short scope correction — the 2026-08-09 form was reached from Washington Labs' Part 87 (aviation) page. Sending it before their quote lands is cheaper than after. drafts/fcc-lab-quote-request.md §4.
  • Labs 2 and 3: Element Materials Technology Washington DC LLC (the former PCTEST, Columbia MD) and CKC Laboratories, with F2 Labs as alternate. Element/PCTEST was picked as the SAR-and-TCB specialist most likely to answer the three exposure questions rather than punt — its number may well be uncompetitive and the answers are still worth the email. The trap found while researching: lab 1 is Washington Laboratories, Ltd and lab 2 is Element Materials Technology Washington DC LLC — different companies, confusingly similar names. Two quotes from one company is one quote. Accreditation scopes are desk research, not phone calls; the draft says to verify before sending.
  • Did not ask Fanstel whether the BM20C will be certified in time. They already answered that as precisely as they will ("this month"). Asked for the grant number instead, which is falsifiable — it exists or it doesn't.
  • Added an eighth item to the Fanstel email that wasn't in this block's list: the WM02C's certified antenna-gain and band-edge backoff CONFIG file. It's a grant condition that lives in firmware (firmware_spec_v3_nrf.md §1.1) and Fanstel publish it as a file — using theirs verbatim beats transcribing the datasheet table.
  • Flagged, not fixed: if the BM20C's grant declares a maximum above +8 dBm, the BLE exclusion ratio of 2.5 has only 0.5 of headroom against the 3.0 threshold. The Fanstel draft's answer-routing table says to re-run FCC Certification.md §5 on receipt.

Not done, deliberately: nothing was sent, and the four numeric blanks are left blank rather than estimated — a guessed cell capacity on a quote form is a number a lab will hold you to.

Agent log — 2026-08-10 (/parselogs): Rewrote item 1 of drafts/fanstel-followup.md from "has that order shipped?" into a carrier-and-tracking-number ask, after the 2026-08-10 log recorded Fanstel confirming both modules are on their way. Renumbering was rejected — the document's own §"What to do with the answers" table refers to items by number. The closing advice changed with it: the item to chase by phone is now item 2, the grant number, because that is the only one on MAR-05's critical path (was OCT-05; booking the lab slot moved to mid-March 2027).

Notes:

Chase Fanstel on the BM20C FCC grant

needs human help · raised 2026-08-08 · BLK-15 AUG-12 · from the 2026-08-08 log

Fanstel's reply carries two risks, not one: the grant ("we plan to complete FCC testing this month") and the silicon ("we ordered nRF54LM20A and B a few months ago. There is no confirmed ship date yet"). The regulatory strategy in launch-plan.md §5 rests on the first; the schedule rests on the second.

Your fallback is written into §5 and BLK-15. The datasheet you filed 2026-08-09 settled the big question the good way: the fallback module (nRF54L15) supports channel sounding, so the whole proximity design survives it. Its costs are now specific — no WiFi (no getOnWifi/getOffWifi, no §5.5.3 anchor repair) and RAM halves to 256 KB, which is the exact constraint your email says drove you off it.

Update 2026-08-09 — half this blocker was never real, and the integration guidance was never outstanding. Both datasheets carry Fanstel's Part 15B mounting and layout guidance in full; you already had both files. The WM02C is already certified — FCC ID X8WWM02C, ISED 4100A-WM02C, TELEC 201-240555, on p.1 of a Ver 1.00 production datasheet. What the BM20C draft (Ver 0.82, July 2026) confirms is the other half: its FCC / ISED / CE / TELEC / NCC rows are all blank — the uncertified status in writing, from Fanstel, dated. Full reading in Concepts/FCC Certification.md.

Update 2026-08-09, second pass — the fallback is more expensive than this block says. Losing WiFi also loses the WATCH_REMOVED datagram (v2 §5.4.4/§5.5.1) and the anchor's SNTP time, so a BC15C build reopens the Sunrise Lock bypass rather than merely dropping two criteria. It remains the cheapest path through certification and is now visibly the most expensive path through the product — which is worth knowing before the labs quote it, not after.

Update 2026-08-10 — the supply half is discharged and the grant half is all that's left. Fanstel emailed to say both the WM02C and the BM20C are shipping and on their way. That is the "no confirmed ship date" answer overturned for these two modules; it says nothing about the grant, nothing about volume, and nothing about which silicon revision is in the box. Everything that gates MAR-05 is still outstanding (was OCT-05).

Update 2026-08-11 — the fallback is now a contingency, not a candidate. You decided v1 ships with WiFi, which means a BC15C build is what happens to this design if the grant fails rather than something being weighed against it. That makes this block's remaining questions load-bearing in a way they weren't: there is no longer a cheaper plan B you were half-considering anyway. The grant number is the whole of it.

AUG-12's lab quotes are folded into this block — it's the same round of emails, and the SAR answer means you can now scope them instead of asking. The drafts themselves are the block above. One of the three is out: Washington Laboratories, 2026-08-09.

Update 2026-08-26 — the grant has not issued, and this is the first time anyone checked rather than waited. BLK-15's instruction is "get the grant number in writing before booking a lab slot", and the grant number is also a thing you can simply look up. Today: no BM20C authorisation exists from any grantee, and Fanstel's X8W code holds 36 grants with none matching. That is not evidence they are behind — applications are not public until they grant — but it does close the possibility that the grant issued quietly and nobody noticed, and it confirms the free window that the exposure-category email depends on. Two side findings: X8WBM15C was granted 2025-01-07, so the fallback in your 2026-08-08 note below is certified exactly as you said (its exposure category is still unread, which is the part that matters); and Fanstel's newest grant of any product is 2026-03-20, five months ago. Filed in docs/agent-notes.md, marked prune-on-grant.

Update 2026-08-28, and again on 08-29, 08-30, 08-31 and 09-01 — re-checked five more times, nothing moved on any of them. Same 36 authorisations, no ID containing BM20 or 20C, Fanstel's newest grant of anything still 2026-03-20. The month they named has now ended without a grant, which is the fourth week running that a company answering one-line questions in days has been quietly late on its own estimate. The note in docs/agent-notes.md was updated in place with each date rather than duplicated. Nothing here changes the plan — BLK-15 already says to treat the grant as unscheduled — but it does mean the exposure-category email has been free to send for seventeen consecutive days, and that freedom expires on the grant date rather than on any date in this file.

Steps — Fanstel - [ ] Re-check https://fccid.io/X8W before the next lab conversation — ten seconds, and it is the cheapest half of "grant number in writing" - [ ] Read X8WBM15C's RF-exposure exhibit — is the BM15C portable like the BC15, or mobile-only? The fallback argument assumes the former and nothing has checked - [x] Confirm the BM20C/WM02C order actually shipped ✅ 2026-08-10 (their email; no tracking number yet — item 1 of the draft now asks for one) - [ ] Grant number in writing - [x] Part 15B integration guidance for both modules ✅ 2026-08-09 (already in the datasheets; discharges AUG-11) - [ ] BM20C grant conditions / test report once issued — certified antenna type, peak gain, declared max power. The labs need these; a draft datasheet has none of them. - [ ] Confirm the part shipping to you is the part being certified (BM20C vs BM20BC, nRF54LM20A vs B) - [ ] BM20C evaluation-board Gerbers or layout library (the WM02C's are public at fanstel.com/nrf54-70-document; the BM20C's aren't) - [ ] Confirm the fallback part number (datasheet says BC15C, your notes say BM15C) and get its BM20C footprint compatibility in writing - [ ] Ask whether there is a required separation between the BM20C and WM02C antennas (item 6 — now blocking the respin, see FCC Respin.md §5)

Steps — the three labs (AUG-12) - [x] Lab 1 — Washington Laboratories, free quote form ✅ 2026-08-09 (confirm on the reply that it was scoped Part 15 Subpart B + RF exposure, not the Part 87 page you reached it from) - [ ] Labs 2 and 3 — same scope text, or the three numbers aren't comparable - [ ] Scope: one PCB / two host configurations / two exposure categories - [ ] State the SAR position rather than asking it — BLE excluded at 2.5, WiFi not at 26.2 - [ ] Ask: is the wrist an extremity (10-g threshold 7.5 instead of 3.0)? It's a 2.5× swing and free to ask - [ ] Ask: does BLE/WiFi coex arbitration count as preventing simultaneous transmission, or do the ratios sum? - [ ] Ask for the BM20C quote and the BLE-only fallback delta — which should be negative on the RF-exposure line, since a BLE-only build needs no SAR test at all

  • In Progress ✅ 2026-08-08
  • Done

Done when: you have the grant number, the grant conditions, and three written quotes that survive the BM20C falling through.

Aug 8th Notes: exact email from Fanstel when i emailed them on Aug 4th Hello,

I am a small business owner planning to switch one of my product's PCBs to use either the BM20C or the WM02C20C in the near future if possible. I currently use the BM15C, but I am memory constrained on this device.

I am just emailing to inquire: approximately when will the BM20C enter mass production, and what is the rough timeline for FCC certification for both these modules?

Thank you,

David Macpherson -> their response David:

We plan to complete FCC testing of BM20C this month. We ordered nRF54LM20A and B a few months ago. There is no confirmed ship date yet.

Best Regards,

that last part is strange to me; their website seems to infer that the BM20C is very much orderable. in fact, i ordered one just now. I ordered a BM20C and a WM02C. I will report back in a couple days, 5-6, and make sure that UPS says that its on its way

In the worst-case where its not on its way, i can order a BM15C, which cannot work with the WM20C, but thats fine, i just wont have Wifi for the prototype. The BM15C is footprint compatible to my knowledge with the BM20C. Importantly, the BM15C is very much already FCC certified, so i will most likely email these labs saying "hey, im planning on using the BM20C, assuming its certification passes, what is a quote?" and worst case scenerio where the BM20C falls through, i get these labs to certify a no-wifi BM15C board. open to suggestions here - but i am reasonably confident the FCC certification will come through for the BM20C, but maybe not on my timeline.

❓ The nightly run works now — so decide what an unattended commit is allowed to do

needs human help · raised 2026-08-09 · resolved 2026-08-12 · from inspecting the system

It runs. The 2026-08-08 #todo asked for a 3am cron job; what exists is a systemd user timer, impulse-parselogs.timer, at 04:00 daily, Persistent=true. It failed four nights running on 401 OAuth access token has expired, and the 04:00 run on 2026-08-12 authenticated and wrote this file — the first successful unattended run. Progress.md's as-of date now advances without you, which is this block's own Done when.

What's left is the thing this block flagged and nobody has decided. An unattended run commits the vault, so from this morning your specs and launch documents get a commit every day with a message you didn't read, written by an agent working from whatever the logs happened to say. That is the design — it is the only backup those documents have, and a missed night is worse than an unread commit. But it is now happening rather than being planned, and two properties of it are worth choosing deliberately:

  • A failed run still leaves no trace you'd find. .parselogs.log is gitignored and one line long per failure. Four nights passed before anyone noticed, and only because a human went looking.
  • An unattended run can now edit outside the vault — the 2026-08-12 run corrected a wrong pin in WatchFIrmware/README.md and left that repo dirty. Correct, and reported in Progress.md. Still: an agent editing a git repo you didn't ask it to touch, at 4am, is a thing to have agreed to rather than discovered.

2026-08-13 — it is mostly not a 4am run, and that changes what the question is. This run started at 13:04, not 04:00. The unit is right (OnCalendar=*-*-* 04:00:00, Persistent=true) and the machine has been up since 2026-08-12 01:32 — it sleeps overnight, so the 04:00 trigger is missed and Persistent=true fires it on resume. The 2026-08-11 run did the same thing at 13:05 and failed; 2026-08-12 is the only run that has ever actually happened at 04:00, and only because the machine happened to be awake after a 01:32 boot.

The consequence is small but it inverts the block's premise: "Progress.md's as-of date advances without you" holds only on nights the machine stays awake. The rest of the time the run lands while you're at the desk, minutes after you sit down — which is arguably better (you're there to read it) and is worth knowing rather than assuming. If you want the 04:00 behaviour for real, the fix is WakeSystem=true on the timer, which needs the machine to suspend rather than power off.

This run took the conservative reading of the undecided question below and edited nothing outside vault/. Two things it would otherwise have offered to fix — a stale ship date and a "there isn't one" snooze claim, both in website/ — are flagged in their own blocks instead.

2026-08-14 — third consecutive resume-triggered run, at 11:22:53, and one of the three questions below is now answered. The machine has been up since 2026-08-12 01:32 and has not rebooted since — yet the 04:00 triggers on both 08-13 and 08-14 were missed and caught up on resume. That is only possible if the machine suspends rather than powers off, which is exactly the condition WakeSystem=true needs. So the third step below is a real option rather than a maybe: it would work.

The pattern is now three for three — 13:05, 13:04, 11:22 — so the run reliably lands within minutes of you sitting down, not overnight. That is arguably the better behaviour, and the only thing wrong with it is that nobody chose it.

2026-08-17 — a weekend of suspend produced exactly one run, not three, and that is a property of Persistent= nobody had checked. The machine suspended Friday 12:29:44 and resumed Monday 08:29:16 — 68 hours, no reboot — and the timer fired once, on resume. Persistent=true records the last trigger and fires once if a calendar event was missed; it does not replay each missed occurrence. So the 08-15 and 08-16 runs did not happen late, they did not happen at all, and nothing anywhere says so.

That sharpens the third step below rather than adding a new one. WakeSystem=true is still the fix if you want the 04:00 behaviour, and it is still known to work on this machine. What's new is the cost of not setting it: it isn't "the run lands when you sit down," it's "a weekend away is a weekend with no runs and no notice." Four runs in a row have now landed on resume — 13:05, 13:04, 11:22, 08:29.

⚠️ 2026-08-21 — the 2026-08-14 finding above is wrong, and the fix it recommended would not have helped. That note concluded the machine "suspends rather than powers off, which is exactly the condition WakeSystem=true needs" — inferred from a boot ID that hadn't changed in three days. It changed. The machine suspended Monday 2026-08-17 at 09:31:20 and the next journal entry is a cold boot tonight at 21:04:59, a new boot ID: somewhere in those four and a half days it went from suspended to off.

WakeSystem=true sets an RTC alarm. It cannot wake a machine that has no power state to wake into. So across the longest gap this timer has seen — 08-18, 08-19, 08-20 and 08-21's 04:00 triggers, four consecutive missed occurrences — the recommended fix would have produced zero runs, exactly as Persistent=true did. It fired once, on boot, five seconds after power came back.

The generalisation, which is the part worth keeping: the trigger has never once fired at 04:00 except on 2026-08-12, when the machine happened to be awake after a 01:32 boot. Five runs in a row have now landed on resume or boot — 13:05, 13:04, 11:22, 08:29, 21:05 — and tonight's was 9pm on a Friday, so "it lands minutes after you sit down" is not a reliable property either. Any scheduling fix that assumes the machine is reachable is fixing the wrong thing; what this timer actually depends on is the laptop being switched on, which is a fact about your week rather than a systemd setting.

The first step below — OnFailure= into a notification — is untouched by any of this and is still four lines. The second one is why this run edited nothing outside vault/, for the fourth time.

2026-08-22 — this gap was a genuine suspend, so both of the last two notes were right about different nights, and that is the whole finding. The machine suspended 01:39:04 this morning (PM: suspend entry (s2idle)), resumed 13:24:15, same boot ID, no reboot — and the timer fired on resume for the sixth consecutive time: 13:05, 13:04, 11:22, 08:29, 21:05, 13:24. The 04:00 trigger was missed while the machine was awake at 01:39 and asleep by 04:00.

So WakeSystem=true would have worked last night and would not have worked over the 08-17 → 08-21 gap. This laptop does both — it suspends on ordinary nights and gets powered off for days at a time — and no timer setting covers the second case. That is the honest version of the answer to step three, and it is a smaller decision than it looked: WakeSystem=true buys you the ordinary nights and nothing else. Worth setting if you want the file waiting for you at breakfast; worth not bothering with if what you actually mind is the four-day silences, because it does nothing for those.

The one thing that would cover both is step one — a notification on failure, or on a run that hasn't happened in N days — and it is still four lines and still undone.

2026-08-24 — the first failure since the fix, and it went unnoticed exactly as step one predicts. Sunday's run (08-23 13:31) failed: exit 1 after 7m49s, with Request timed out as the only line in .parselogs.log. Nothing was produced, nothing was committed, and the sole reason you are reading about it is that today's run went looking. One failed night in three, and it left no trace you would have found — that is step one below demonstrated rather than argued, and it is still four lines of OnFailure=.

Two smaller facts, both confirming the picture rather than revising it. Eight consecutive resume-or-boot fires: 13:05, 13:04, 11:22, 08:29, 21:05, 13:24, 13:31, and today's 10:04. In the timer's whole life the 04:00 trigger has fired at 04:00 once, on 2026-08-12, and only because the machine happened to be awake after a 01:32 boot. So "the daily run" is in practice "a run on the first morning you open the laptop," which is a fine thing to have and a different thing from what the unit file says.

And today's run is unattended and confined itself to vault/, for the fifth time, because step two is still undecided. It cost nothing this time — there was no new log, so nothing to route outside the vault — but the run that finds something worth filing in a firmware repo at 10am on a weekday is the one this question is actually about.

2026-08-26 — a second demonstration that Persistent= catches up to the present rather than replaying, and this time it cost two days rather than a weekend. The machine powered off 08-24 at 23:57 and came back 08-26 at 11:07 as a cold boot. Two 04:00 triggers were missed — 08-25 and 08-26 — and the timer fired once, four seconds after boot. The 08-25 run did not happen late; it did not happen. Same property found over the 08-15/08-16 weekend, now seen twice, and it is the reason step one below covers more than the failure case: a run that never fires and a run that fails both leave exactly the same trace, which is none.

Ninth consecutive resume-or-boot fire — 13:05, 13:04, 11:22, 08:29, 21:05, 13:24, 13:31, 10:04, 11:07 — and the 04:00 trigger has fired at 04:00 once in the timer's life, on 2026-08-12. Nothing here revises the picture; it is the same laptop-is-switched-off fact, now with a second data point on the cost. Step two is still undecided, so this run confined itself to vault/, for the sixth time. It cost nothing again — there was no log to route — but today's run did find something outside the workspace worth filing (the FCC grant check), and it filed it inside the vault, which is the conservative reading working as intended rather than by luck.

⚠️ 2026-08-29 — a day was skipped, today's run was twelve hours late, and the failed run from a week ago is still the only one that mattered. This is the last new note this block needs; the picture is complete. Three facts, in order of consequence.

  • There was no run on 08-27 at all. The machine suspended 08-26 13:12 and resumed 08-28 13:26 — 48 hours, one boot ID — and the timer fired once, on resume. Two 04:00 triggers, one run. That is the same Persistent= property found over the 08-15/08-16 weekend and again over the 08-25 power-off: third confirmation, and the first time the cost was a single ordinary weekday rather than a weekend or a trip. There is no setting that fixes this. It is not WakeSystem=; a suspended laptop that stays suspended past the next trigger loses the intervening days no matter what the unit file says.
  • Today fired at 16:42. Suspended 01:56, resumed 16:42, ran immediately. Tenth consecutive resume-or-boot fire — 13:05, 13:04, 11:22, 08:29, 21:05, 13:24, 13:31, 10:04, 11:07, 13:26, 16:42 — against one genuine 04:00 fire in the timer's entire life, on 2026-08-12. "Daily at 04:00" is a description of the unit file and of nothing else. (Corrected 2026-09-03, updated 2026-09-04 — this stopped being true four days after it was written. 08-30, 08-31, 09-02, 09-03 and 09-04 all fired at 04:00, so the count is 6 of 21, the last three are consecutive, and 09-04 fired four and a half hours after a cold boot. The claim that survives is narrower and still the load-bearing one: the timer fires at 04:00 whenever the machine is on at 04:00, and produces nothing at all when it isn't — which is a fact about your week, not about systemd.)
  • 08-23 failed and nobody was told. Exit 1 after 7 m 49 s, Request timed out, nothing produced and nothing committed. Found only because a later run read the journal.

The three facts collapse into one decision, which is step one. A run that fails and a run that never fires leave the same trace, which is none — and this is the only process backing up every spec and launch document in the workspace. OnFailure= catches the first; a "no successful run in N days" check catches both. Steps two and three are worth deciding and neither is load-bearing next to this one.

This run did not add OnFailure= itself. It is four lines, and it is a change to how an automated process behaves on this machine, proposed by that process, running unattended, on the exact question this block exists to have you answer deliberately. Say the word and it takes a minute.

2026-09-10 — step one is no longer a design question. It has been answered by events, and the answer cost four nights. The timer fired correctly on 09-06, 09-07 and 09-09. The service failed at startup each time — status=1/FAILURE after 680–1020 ms, an expired OAuth credential, exactly the failure mode that preceded the first successful run in August. 09-08 has no record; the machine was down. Four consecutive nights produced nothing, committed nothing, and told nobody, and the only reason it is known now is that this run went looking at journalctl. In that same window the two most substantial working sessions in a fortnight happened and went unrecorded — so the outage was not harmless, it was concurrent with the thing it exists to capture.

This is exactly what the block predicted, in its own words: "a run that fails and a run that never fires leave the same trace, which is none." It is now also true that a run that fails and a run that succeeds leave the same trace to you, because nothing surfaces either.

OnFailure= is still not taken unilaterally, for the same reason as before — an unattended process editing its own supervision is the question this block exists to have you decide. But the balance has changed: the cost of deciding it wrong is four lines in a unit file, and the cost of not deciding it has now been paid once. Recorded in agent-notes.md under 2026-09-10, including the general form — any scheduled agent on this machine should assume its credential will expire and be built to say so.

2026-10-22 — a new failure mode, and the same silence. The 10-21 catch-up run (11:32, after the machine was off at 04:00) exited 1 after 5 s with SSL certificate verification failed (UNABLE_TO_VERIFY_LEAF_SIGNATURE), an authority Claude Code didn't trust. Today's run, from the same machine, connected fine, so it was transient or tied to whatever network the laptop was on then. That makes the causes so far: OAuth expiry (twice), request timeout, network errors, and now TLS. Every one was silent. Step one is still the fix for all of them.

Steps - [ ] Decide whether a failed run should notify you — systemd's OnFailure= into a desktop notification is about four lines · ⚠️ four runs lost to this on 09-06/07/09 - [ ] Decide whether an unattended run may edit outside vault/ at all, or should confine itself to the vault and file the rest as a todo - [ ] Decide whether you want WakeSystem=true, or would rather the run land whenever the machine next comes up — it is currently the second, by accident rather than by choice. (2026-08-14 claimed the machine only ever suspends, so this would work; corrected 2026-08-21 — it was powered off for four and a half days and WakeSystem= cannot reach that state. It would help on a suspended night and does nothing for a trip away.) - [ ] Skim the next few automated commits before they pile up — git -C ~/Impulse/vault log --since=yesterday -p

  • In Progress ✅ 2026-08-12 — authenticating; the timer fired and produced Progress.md unattended
  • Done

Done when: you've decided what an unattended run may touch and when it should fire, and a failed one reaches you.

Notes:

❓ This file is 1,500 lines and most of the growth is mine — may I prune the per-run notes?

automatable · raised 2026-08-29 · from measuring what this skill has been doing to its own output

  • In Progress
  • Done

Todos.md is meant to be skimmable in thirty seconds and it is not. Forty-five blocks, and the largest single category of text in it is dated notes written by /parselogs runs, most of which say a version of "re-checked, unchanged." The blog block carries eight of them; the footage block six; the analytics block seven; the nightly-run block nine. Every one was correct on the day it was written and almost none of them is worth reading now.

The mechanism is the problem, not any individual note. Each run re-verifies the same facts, finds them unchanged, and — until today — appended a fresh paragraph saying so. That is a process that adds length in exact proportion to how little is happening, which is precisely backwards: the quieter the week, the longer the file gets. Eight days without a log has produced four runs and roughly thirty new paragraphs of "still true."

What this run did about it, which is the smallest safe thing. It added no new dated notes to existing blocks. It edited the most recent note in each block in place instead — same information, same date stamp, one paragraph rather than two. That stops the growth. It does not undo it.

What I'd like to do, and won't without a yes. Collapse each block's stack of dated re-verification notes into a single line: "re-verified unchanged on 8 dates, most recently 2026-08-29." Roughly 400 lines come out and no fact is lost — the dates and counts survive, and the argument each block makes was never in those notes to begin with.

Three things I would not touch, whatever the answer:

  • Every **Notes:** body, verbatim, forever. That is your writing.
  • Every **Agent log —** block. That is /todo's record of decisions it made, and it is referred to elsewhere.
  • Any note that carries a finding rather than a date — the 2026-08-12 grant-conditions correction, the Persistent= behaviour, the donningGraceS 65535 reading. Those are the reason some blocks are long and they are worth their length.

If there's no answer, nothing is deleted, and runs keep editing the newest note in place rather than appending — so the file stops growing but stays long. That is a stable state, not a bad one; it is just not a thirty-second one.

Steps - [ ] Yes or no in Notes: — one word is enough

Done when: either the per-run notes are collapsed, or a decision to keep them is written down so no future run raises this again.

Notes:

Everything else

Protect the servo rail — the part choice, once you have the stall current

automatable · raised 2026-08-10 · AUG-14 BLK-03 · you asked for this block

On Board V1, U1 pin 2 is /VBAT with nothing in the path — no switch, no fuse, no current limit — so the only thing between an external three-wire cable and a dead short across a Li-ion cell is the pack's protection IC. The ESP32 board had Q2 there; V1 dropped it. On 2026-08-10 exactly that fault flattened a pack and took a regulator with it, from nothing more than tape working loose.

The load makes the case rather than the accident does. A servo stalls at amps, draws inrush on every movement, and hangs off a lead that flexes in normal use inside a case a customer opens. That is the profile you fuse, independent of what happened this week.

Two shapes to choose between, and the trade is real. A PPTC polyfuse is ~$0.05 and one part, but it is slow — hundreds of milliseconds at moderate overload — so it prevents a flattened cell and a cooked regulator without preventing a brownout, and its series resistance costs voltage exactly when the servo stalls. A current-limited load switch or eFuse is ~$0.50–1.00, responds in microseconds, and gives back the ability to cut the servo rail in firmware, which V1 currently cannot do at all. You already use a TPS22916 for WiFi VDDIO, so the family is familiar.

The number that decides the part is the servo's stall current, which you have and no document records.

2026-08-11 — the respin item is now tracked in the merged respin block in Soon and written up in Concepts/FCC Respin.md §2. This block is kept for the part-selection work, which is the part an agent can actually do once you supply the one number.

Steps - [ ] Write down the servo's stall and inrush current — everything below is picked from it - [ ] Decide: polyfuse, or current-limited load switch with a firmware enable - [ ] If the switch: give it a GPIO and record it in firmware_spec_v3_nrf.md §2 and §7, so the port can turn the servo rail off - [ ] Check the drop across whichever part at stall current — a servo browning itself out is a new failure, not a fix - [ ] Into the respin alongside the antenna keepout

  • In Progress
  • Done

Done when: a shorted servo lead trips something and the board carries on, instead of flattening the pack.

Notes:

Write the FCC lab test firmware — forced TX modes, and a way to select them

needs human help · raised 2026-08-10 · AUG-12 · from tightening the lab quote responses

Concepts/FCC Lab Quote Responses.md §4 promises the lab "a dedicated test firmware build exposing forced continuous-TX modes (per band, per standard, per channel) and forced actuator states." That build does not exist and cannot be written yet — chunk A of the port hasn't started. This block exists so the promise is tracked somewhere other than a sentence in a form response you've already sent.

It isn't optional politeness. Production firmware quarantines loosening schedule changes for ~24 h (firmware_spec_v2.md §9), so you cannot reconfigure a watch quickly on a bench, let alone in a chamber at hourly rates. Without direct mode selection the lab drives the product through its real state machine and you pay for the discovery.

Two open questions, and the first is answerable now.

  1. How does the lab select a mode? Undecided, and it contradicts something you've already told them. USB-C is power-only — J3's D+/D− are unrouted deliberately (v3 §1.4, §2) — so there is no serial console. That leaves the wake button (crude, but zero cables: press-count cycles the mode), BLE from a laptop (needs a link up during setup, which perturbs any measurement not meant to include it), or SWD via the TagConnect pad — which puts a fourth cable in the chamber after §3 declared three. Settle it before the setup call.
  2. Which modes, exactly. Per band, per standard, per channel for WiFi; BLE advertising / connected / CS at max TX; and forced actuator states — all 12 LEDs at full brightness, motor on, buzzer on, servo sweeping. §2's worst-case combination has to be reachable in one command, not assembled by hand.

Steps - [ ] Decide the mode-selection mechanism, and correct §3's cable count if the answer is SWD - [ ] Write the mode list into firmware_spec_v3_nrf.md §10 as its own chunk, carrying §1.1's grant-condition gain/backoff CONFIGs - [ ] Build it once chunks B and I land — it is a Kconfig on the same tree, not a separate firmware - [ ] Confirm with the chosen lab that a vendor test build is acceptable at all

  • In Progress
  • Done

Done when: a lab-test Kconfig build puts either role into any declared mode without the app, and the lab has agreed the selection mechanism.

Notes:

Research the two-module antenna placement rules

automatable · raised 2026-08-09 · AUG-11 BLK-03 · from the 2026-08-09 log

"look into how exactly i need to do the new hardware placement to be in compliance with the placement guidelines for the WM20C and the WM02C. like, is there a minimum distance they must be apart from eachother? neither datasheet addresses directly to my knowledge what to do in the presence of another? do they both hang off the edge, and i need to gaurentee a minimum distance?"

Your reading is right — the mounting rules in both datasheets are written for one module on a board and say nothing about a second radiator nearby. That is a real gap and it plausibly constrains the respin's outline, not just its keepouts: two chip antennas that both have to overhang the edge, on a watch-sized board, is a geometry problem before it is a compliance one.

2026-08-10 — answered, in Concepts/Antenna Placement.md. Short version: both antennas must overhang, but not the same edge — there isn't 30 mm of room on one. And the datasheets do answer the separation question, just not in the section you'd look in: both state ≥ 30 mm from the antenna area to all external metal, and the other module's shield can is external metal. That number happens to land within a millimetre of λ/4 at 2.44 GHz, which is the conventional co-location minimum, so two independent routes agree. Board V1 currently has 1.15 mm.

2026-08-11 — the two remaining steps moved into Concepts/FCC Respin.md §3 and §5, where they gate the drawing rather than the research. This block stays open only until they're done.

Steps - [x] What each datasheet actually says about keepout, ground clearance, and edge placement ✅ 2026-08-10 (and a second sanctioned option nobody had noticed: "Good" = antenna over a void with 5 mm of pour clearance, not only "Best" = overhang) - [x] A recommended minimum separation, with what it's based on ✅ 2026-08-10 — 30 mm, from Fanstel's own external-metal rule - [x] Whether both antennas can overhang the same edge, or need different ones ✅ 2026-08-10 — different edges; one edge leaves at most 20 mm - [ ] Pull EVM-WM02C-VB-gb.rar from fanstel.com/nrf54-70-document and diff the keepout against Fanstel's own evaluation layout (needs a .rar extractor and a Gerber viewer — the last step that can't be done from the datasheets) - [ ] Confirm the BM20C footprint length against Fanstel's library — the drawn silkscreen is 14.8 mm, the datasheet implies 15.8 mm

  • In Progress ✅ 2026-08-10
  • Done

Done when: the respin has a placement rule it can be drawn to, written down with its source.

Agent log — 2026-08-10: Wrote Concepts/Antenna Placement.md (/todo). No clarification round — this was research, and the design calls were mine to make. What it found and what I decided:

  • Read the Board V1 geometry out of Impulse.kicad_pcb rather than trusting any pin table, per CLAUDE.md. Board is 40.00 × 42.00 mm; both modules sit on the west edge, U8 WM02C at y 89.50–101.50 and U7 BM20C at y 102.65–112.65.
  • Established which end of each module is the antenna by pad containment, not by assumption. Castellations sit in the RFI shield and never in the antenna area, so the pad-free end is the antenna end — and the opposite orientation would put pads outside the shield, which is impossible. Both antennas face west. This matters because everything downstream is measured from it.
  • The BM20C deviates too. Todos.md said nobody had looked; now looked at. Its antenna area stops 0.6 mm short of the board edge, exactly like the WM02C's. The keepout fix is two modules, not one.
  • Decided to treat the 30 mm as a design target rather than a compliance limit, and said so in place. It is prefaced "for the best range performance", which makes it a recommendation — but it is the only number Fanstel give, and λ/4 agrees with it. Overturned by Fanstel's own answer, which is item 6 of the email draft.
  • Recommended the WM02C takes the overhang and the BM20C takes the 5 mm keepout, because only one overhang fits the enclosure. Reasoning: the WM02C is the module that already holds a grant, its antenna area is larger, and 2.4 GHz WiFi is the radio that may have to give up 8 dB to stay SAR-excluded. Reversible in one edit at Antenna Placement.md §4.
  • Worked one arrangement to concrete numbers (opposite edges, diagonally offset) rather than stating the constraint and stopping: 34.7 mm and 33.5 mm antenna-to-shield, 54.8 mm centre to centre. Directly opposite each other it misses at ~29 mm; the diagonal is what buys the margin.
  • Stated the cost rather than hiding it: the outline shrinks to about 32.6 × 42 mm if the enclosure's 45 mm holds. I could not decide the enclosure question — no case is specced — so §5 records it as a thing that would overturn the trade.
  • Corrected FCC Certification.md §2, which said Fanstel publish no BM20C layout files and to ask for them. They do — libraries, 3D STEP, and an EV-BMH20C schematic with Gerbers, plus the WM02C's certified CONFIG file by name (WM02C-Power-Setting_radiotest_prj.txt). Two items of the Fanstel email were rewritten off the back of it.

Not done, deliberately: no Gerber diff against EVM-WM02C-VB-gb.rar — it needs a .rar extractor and a viewer, and the file is Fanstel's best evidence, so it stays a step rather than being guessed at. No KiCad file was modified; the respin is the user's to draw.

Notes:

Verify the BM20C and WM02C integrations against Fanstel's guidance

needs human help · raised 2026-08-09 · AUG-11 BLK-15 · you asked for this block

You did the integration work before launch-plan.md existed and believe it's right; the only optional item knowingly skipped is the 32.768 kHz sleep crystal. This block is the second pass, against the actual guidance document rather than memory — because §12.5 makes deviation from the grant conditions fatal ($15k → $35k, plus a full intentional-radiator retest), and it is the one class of mistake that stays invisible until a lab finds it.

The things worth checking specifically: antenna keepout and ground clearance, any required copper pour or via stitching, feedline geometry, module-to-edge distance, and separation between the two modules' antennas. Board V1 is a prototype, so anything found here is cheap — it's a change to the next spin, not a respin of a certification article.

Update 2026-08-09 — started, and the first deviation is already found. The guidance was in the datasheets all along, so this block is unblocked. The WM02C's antenna sits over the four-layer stackup, which the mounting rules forbid. Two more deviations to rule out, plus one that isn't a deviation at all: the skipped 32.768 kHz sleep crystal is embedded inside the BM20C module and was never needed — take it off the list. A third item is now firmware rather than layout: Fanstel's certified gain/backoff Kconfigs, recorded in firmware_spec_v3_nrf.md §1.1.

Steps - [x] Guidance document in hand ✅ 2026-08-09 (it was in both datasheets) - [x] BM20C layout checked against it ✅ 2026-08-10 — deviates, 5.5 mm antenna area 0.6 mm short of the edge - [x] WM02C layout checked against it ✅ 2026-08-09 — deviates, 7.4 mm antenna area sits over copper - [x] Separation between the two modules' antennas checked ✅ 2026-08-10 — 1.15 mm against a 30 mm recommendation - [ ] No signal traces routed beneath either module - [ ] Deviations, if any, listed for the next spin — done as Concepts/FCC Respin.md, 2026-08-11; this step closes when you've read it

  • In Progress
  • Done

Done when: you can name every place the layout departs from the guidance, even if the answer is "none."

Notes:

⚠️ Fit a cell to the V1 anchor — holdover is unmet, not merely unmeasured

needs human help · raised 2026-08-09 · updated 2026-08-11 · firmware_spec_v3_nrf.md §7, §11

Answered and filed. Your note settled all three parts of this, and firmware_spec_v3_nrf.md is at v0.9 carrying them: the anchor does not report mains loss to the watch; the watch treats a battery-running anchor identically; the app raises the notification (flagged into MOBILE_APP_SPEC.md §0 and its v1.5 change log); holdover is ≥ 90 minutes, against 1 h observed and 2–3 h on recent measurements.

The residual hole is recorded with your reasoning rather than silently accepted: someone willing to unplug an anchor and wait 90 minutes defeats it, that is an MVP-acceptable trade, and "it is not in our threat model to make sure the anchor gets plugged back in." Written into §7 so it can be revisited rather than re-litigated.

2026-09-12 — this stopped being a measurement and became a fitting job. The V1 anchor reads batt=0% with AIN0 at 38–53 mV, against ~2070 mV on the watch: no usable cell is fitted at all. It runs on external power and resets when that glitches — one reset observed at 372 s of uptime. So §7's ≥90 min is currently unmet, not unmeasured, and an anchor that resets on a mains blip stops enforcing mid-commitment. Your note below estimates 2–3 hours, and that figure is worth keeping in view but it came from the ESP32 anchor — a different board with a different draw. Nothing can be measured here until a cell goes on. Recorded in firmware_spec_v3_nrf.md §0.4 (v0.13).

What's actually left is a measurement, and it needs a board with a cell on it. 90 min is a requirement now; whether V1 meets it is unknown. Two things make it non-obvious: V1's CS-reflector role draws very differently from the ESP32 anchor's continuous scanning (in the cheaper direction), and the anchor that produced the 1–3 h figures is the one found flat and in protection lockout after five plugged-in days — so the charging path and the holdover number are the same measurement, not two.

Steps - [x] Decide whether mains loss is reported, or holdover alone is the answer ✅ 2026-08-11 — reported to the user by the app; the watch does nothing - [x] Set a holdover target in hours ✅ 2026-08-11 — ≥ 90 min - [ ] Fit a cell to the V1 anchor — nothing below can start until this happens - [ ] Measure it on Board V1 in the reflector role, and size the cell from the result - [ ] Confirm the anchor actually charges its cell and holds it charged — the 2026-08-10 failure says otherwise on at least one board

  • In Progress
  • Done

Done when: a V1 anchor is unplugged and still answers CS procedures 90 minutes later.

Notes: the board keeps working for at least an hour, but im pretty sure my recent measurements have been closer to 2-3 hours. I'm aiming for minimum 90 minutes in a marketing copy, as thats more than enough for most commitments. i will likely have to add something to the anchor/mobile app spec, so the mobile app reports when an anchor has been unplugged. it is not in our threat model to make sure the anchor gets plugged back in - users are responsible for this. the watch shouldnt do anything about an anchor thats dying, just keep treating it the same. this is probably subject to change, i just have enough on my plate for a MVP at the moment, and users wont fault me too much for this.

Write the nRF/Zephyr firmware spec

automatable · raised 2026-08-08 · from the 2026-08-08 log

The pin map is transcribed and verified into firmware_spec_v2.md §1.3, so the starting point exists. What's missing is the port plan: what translates verbatim from the ESP32 firmware, what needs tweaking, what the proximity engine becomes under channel sounding, and how the wake button changes §5.7.4's always-on analog clock. Split into chunks that can be built and tested independently.

Three constraints are now settled and should shape the draft rather than be discovered mid-way: RTT over SWD is the debug transport (no USB CDC), the LF clock runs on a crystal embedded in the module (corrected 2026-08-09), and the override mechanism is unsettled (Concepts/Safety.md), so leave a clean seam for it rather than porting the two-button hold.

Moved out of Soon on 2026-08-09. The draft exists and meets this block's own bar — a coding agent could start from it. It stays open rather than done because you haven't read it.

2026-08-31 — the spec's own bar has been cleared twice over: a coding agent did start from it, and the result runs. The document is now at v0.11 and its §0.4 parity table has ✅ rows. The three constraints above all survived contact: RTT is the transport (and has three traps that each look like a dead board), the LFXO is confirmed running by a +34 ppm drift measurement, and the override seam was left rather than ported. The NCS version pin is answered — v3.4.0, in west.yml — as is the item §11 flagged "check this first": the CS API shape was assumed and turned out to be right. What is still waiting on you is unchanged and is the only reason this is not ticked: you have not read it.** That is now a bigger ask than it was, and worth doing as §0.4 plus §0.5's last two entries rather than end to end.

  • In Progress ✅ 2026-08-09
  • Done

Done when: a draft exists that a coding agent could start building from.

Agent log — 2026-08-09: Drafted docs/specs/firmware_spec_v3_nrf.md v0.1 (/todo). Clarification round settled two things: the watch and anchor are the same PCB (so both do channel sounding, and the engine is deleted outright with no fallback), and the new spec inherits v2's MCU-independent chapters by reference rather than restating them. Decisions taken after that:

  • Moved v2 §1.3's pin table into v3 §2 rather than copying it, leaving a pointer behind. Two pin tables for one board is the drift this workspace keeps paying for. Reversible at firmware_spec_v2.md §1.3.
  • Role selection is compile-time Kconfig, not runtime. A runtime-flippable role means a watch can be told it is an anchor, and anchors do not enforce — that turns all of §9 into one settings byte. Costs two firmware images. Reversible at v3 §1.3.
  • Kept the AWAY/NEAR evidence asymmetry as a 2:1 dwell ratio, and marked it a floor rather than a tunable. It is about attacks being subtractive, not about RSSI, so it survives the pivot. v3 §4.4; reasoning in agent-notes.md.
  • Deleted the 600 s STILL poll tier with the motion channel that justified it — it existed because a motionless wrist produces no new fading draws, which does not constrain a time-of-flight measurement. Flagged in §11 as worth re-deriving once CS energy is measured.
  • A failed connect is an abstention, not an AWAY reading, bounded by CS_ABSTAIN_MAX_CONSECUTIVE = 5 then resolving to the criterion-dependent fail-safe. v2 got this wrong once and it produced a real saturation defect. v3 §4.5.
  • Calibration-v2 becomes a per-anchor threshold override, and widening it is a §9.1 loosening — quarantined 24 h. Otherwise a per-anchor distance is a one-tap bypass of every stayNear commitment. v3 §4.7.
  • Wake button: short press lights the clock for CLOCK_SHOW_MS = 5000; long press reserved for the override, unimplemented. All button events routed through one dispatcher so the override has a clean seam. v3 §6.2.
  • ~~CLOCK_GUARD_S = 30 for the RC-clock wake guard band~~ — withdrawn 2026-08-09. Rested on there being no LFXO; the datasheet says both crystals are embedded in the module. Now 5 s of jitter insurance, needing no measurement. v3 §3.2.
  • Every other invented number is in §11 with what would overturn it. Nothing is stated as measured.

Not done, deliberately: no code, no MOBILE_APP_SPEC.md §0 lockstep flag (that is an app-spec edit, and the deletion list it needs is v3 §4.8 — raised as its own block), no moved-anchor detection design, no CLAUDE.md device-table correction.

Agent log — 2026-08-09 (/parselogs): v0.3. §1.1 records the WM02C's certified gain/backoff Kconfigs as a grant condition on firmware (NCS ≥ 2.6.1) — this existed in no document and is a §12.5-class mistake if missed. §6.3 records the 7–10 h runtime target with its provenance (10 h measured on ESP32-C3, clock disabled — different silicon) and an explicit note that it does not discharge BLK-04. Chunk I, §0.4 parity, and two §11 rows updated. CLAUDE.md's stale anchor/engine description corrected in the same run, as this block's sibling asked.

Agent log — 2026-08-09, second /parselogs run: v0.4. New §1.5 — what the WM02C actually carries, written because the 2026-08-09 log weighs dropping it. The finding that drove it: WATCH_REMOVED/WATCH_WORN are WiFi-only (send_to_anchors() early-returns on !g_wifi_connected, main.cpp:1782), so the v2 §5.4.4 mitigation for the out-of-range bypass has no transport in a BLE-only build. §1.5 states the three dependencies and explicitly records no decision. §0.4 chunk-I row and §0.5 change log updated. Also filed to agent-notes.md and Concepts/NRF Redesign.md §A4.

Agent log — 2026-08-11 (/parselogs): v0.9, recording three decisions you made in Todos.md notes, each into a section that had been written to hold a space for it. §1.5 now records v1 ships with WiFi, and states the consequence the decision inherits: the SAR question stops being hypothetical, because the ~8 dB cut that avoids a SAR test spends the range WATCH_REMOVED needs — which is the reason WiFi was kept. §7 records mains loss is reported to the user by the app, not to the watch, withdraws the earlier expectation that this would share a design with moved-anchor detection (§4.6), and states the accepted residual hole with your reasoning attached. §6.3 records 8 h minimum as a floor rather than a target, and flags that it half-discharges BLK-04 — the 9pm window is gone but the example day's 5:30pm window is still three and a half hours past the floor. §0.4 parity and two §11 rows updated.

Notes:

⚠️ The nRF port deletes GATT characteristics the app still implements

automatable · raised 2026-08-09 · from writing firmware_spec_v3_nrf.md

Deleting the proximity engine deletes wire surface, and the app doesn't know yet. firmware_spec_v3_nrf.md §4.8 lists exactly what goes: four anchor characteristics (prox vector, prox score, fingerprint ctrl, fingerprint data) and the watch's calibration control. MOBILE_APP_SPEC.md §0 needs the lockstep flag that the firmware spec's own §0 rules require, and MOBILE_APP_SPEC §8.5's guided walk-around calibration screen loses its purpose entirely — it should shrink to a "set the distance for this anchor" control, not be repurposed.

Worth doing soon and cheaply, because the app is on the critical path (launch-plan.md §12.20) and this is the difference between "the app needs two screens changed" and "the app needs an unknown amount of work." Everything else in the contract is deliberately frozen, including SCHEDULE_FORMAT_VERSION = 0x02.

2026-08-10 — done, and the list was five characteristics rather than four. MOBILE_APP_SPEC.md is at v1.4 with the lockstep flag in §0, the doomed characteristics marked in §6.2, and §8.5 rewritten to say what the screen becomes. Checking the list against the app's own constants found a sixth deletion nobody had counted — see the flag below.

2026-08-31 — the deletion is now real on hardware, and the app still doesn't know. phone_sim drove the nRF watch and anchor on 2026-08-30 and reported calib-v2 char present: False on both — the §4.8 deletion is no longer a plan, it is the behaviour of a running device. That does not make this urgent yet (the ESP32 contract is still the live one, and the app talks to it), but it does change the shape: the documentation half of this block is finished, and what remains is app work that nobody has scheduled**, on the dependency launch-plan.md §12.20 calls the least visible in the plan. SHIP-08 is June–July 2027 and the app has had no commits since the pivot.

  • In Progress ✅ 2026-08-10
  • Done

Done when: MOBILE_APP_SPEC.md carries the lockstep flag, names the removed characteristics, and says what §8.5 becomes.

Agent log — 2026-08-10: MOBILE_APP_SPEC.md → v1.4, firmware_spec_v3_nrf.md → v0.7 (/todo). No clarification round; the deliverable was defined by the block's own Done when. Decisions:

  • Verified the deletion list against impulse_app/lib/utils/ble_constants.dart rather than transcribing v3 §4.8, because CLAUDE.md makes the app the fourth declaration of this contract. That is what caught the omission: anchor Calibration Mode …000F is live in WatchFIrmware/src/watch_prox_transport.cpp and declared app-side, and appears in no spec at all. Calibration-v2 is deleted by v3 §4.7, and …000F exists for nothing else, so it is deleted too. Added to v3 §4.8 with a §0.5 entry and a §0.4 chunk-E note, per that document's §0 rules.
  • Annotated the four doomed anchor characteristics in §6.2 with a dagger rather than deleting them. They are live on every device that exists; a spec that removed them today would describe no hardware. Reversible by deleting six dagger marks.
  • Did not write …000F and …001C into §6. Both are missing from the app spec's "complete" GATT contract and both are on their way out — documenting them properly means verifying payloads against firmware for characteristics scheduled for deletion. Named in §0's flag with their source lines, and raised as its own block below for firmware_spec_v2.md, which is the document that ought to have them.
  • Wrote §8.5's replacement as a prohibition as well as a spec. "Do not repurpose the walk-around flow into a distance-measuring wizard" — the instinct will be to keep the donut UI and point it at CS, and the flow exists to make an unphysical number trustworthy. Also recorded that widening a per-anchor threshold is a §8.9 loosening, because otherwise the replacement control is a one-tap bypass of every stayNear commitment.
  • Flipped no parity row to done, and added one row that says "deliberately not started." Acting on any of this now would break the app against the only firmware that ships.

Not done, deliberately: no app code touched, and firmware_spec_v2.md left alone.

Notes:

⚠️ Two shipped GATT characteristics are in no spec at all

automatable · raised 2026-08-10 · from checking the nRF deletion list against the app's constants

firmware_spec_v2.md §6 and MOBILE_APP_SPEC.md §6 both present themselves as the complete GATT contract. Neither contains the anchor's Calibration Mode …000F or the watch's Calibration Ctrl …001C, and both are real: …000F carries the calibration-v2 phase the watch drives during a walk-around burst (WatchFIrmware/src/watch_prox_transport.cpp:16, phases NONE/INSIDE/EDGE/FINALIZE), and both are declared in impulse_app/lib/utils/ble_constants.dart at lines 24 and 39.

They shipped without ever being written down. CLAUDE.md says this contract is declared four times and that changing it means touching all four — these went into two of the four and no document, and survived two spec generations that way. They were nearly missed again when the nRF port drew up its deletion list.

It is only half a problem, because both are on the way out — v3 §4.8 now deletes them along with the rest of calibration-v2. The reason to fix firmware_spec_v2.md anyway is that v2 is the reconciled reference for the firmware that actually exists, and it will stay the live contract until the port lands. Whoever next reads v2 to answer "what does the anchor expose?" gets a wrong answer today.

Worth checking whether they are the only two. The fastest version of that audit is to diff ble_constants.dart against v2 §6's tables and phone_sim/impulse_phone/constants.py — three declarations, one pass, and anything present in two of them and absent from the spec is the same defect.

Steps - [ ] Diff ble_constants.dart and phone_sim/impulse_phone/constants.py against firmware_spec_v2.md §6 — find every characteristic in no spec - [ ] Document …000F and …001C into v2 §6.1/§6.2 with payloads verified against the firmware, plus a §0.1 parity row and §0.2 change-log entry - [ ] If the audit finds others, decide per characteristic whether it is contract or debris

  • In Progress
  • Done

Done when: every characteristic declared in the firmware or the app appears in firmware_spec_v2.md §6, or is recorded there as deliberately undocumented.

Notes:

Put the KiCad schematics under version control

needs human help · raised 2026-08-10 · from your own note — "i never version-controlled the Impulse board schematics, i shouldve in retrospec"

It cost something concrete today. The V3 boards on your bench carry VCC on U1; you changed it to VBAT in June, right after they arrived, and the file moved on while the boards didn't. There is no revision anyone can check out to see what a given board was actually built from — so an agent reasoning from Impulse.kicad_sch got the rail wrong, and the only correction available was your memory. That works while it's one person and three months. It stops working at the point where a lab, a contract assembler, or a returned unit needs to be matched to a revision.

~/Documents/KiCad/ImpulseBluetooth is outside ~/Impulse, so this is its own repo and doesn't touch the workspace-root rule in CLAUDE.md. It needs a .gitignore — that tree carries .rar archives, .step and .wrl models, Impulse-backups/ (dozens of near-identical copies), .history/, and ~*.lck files.

The thing that makes it worth doing is tags, not commits. A tag per fabricated batch — v3-esp32-fab, v1-nrf-fab — is what turns "which board is this?" into a question with an answer.

2026-08-11 — and it just cost something again. The regulator block was closed by the repair with the "which revision were the V3 boards fabricated from?" question still open. That question is unanswerable today and would be trivial with a tag.

Steps - [ ] git init in ~/Documents/KiCad/ImpulseBluetooth — not in ~/Impulse - [ ] .gitignore: Impulse-backups/, .history/, *.lck, *.rar, fp-info-cache, and the 3D model dirs if they're vendor-downloaded - [ ] Tag the current state as the V1 fab revision - [ ] Reconstruct a v3-esp32-fab tag if any copy of the pre-June revision still exists — Impulse-backups/ may hold one - [ ] Decide whether it gets a remote. Same call as the vault: a public one publishes the design

  • In Progress
  • Done

Done when: you can check out the revision any physical board was built from.

Notes:

⚠️ The live site exists in exactly one place — your working tree

needs human help · raised 2026-08-12 · AUG-02 GATE-EMAILS · from re-measuring the repos

website/ has 16 uncommitted changes, and they are not scratch work: src/lib/, src/data/, src/components/home/, EMAIL_CAPTURE.md, a rewritten Home.vue and router, and the deletion of OrderPage.vue. That is the entire 2026-08-09 email-capture rebuild — the thing AUG-02 was closed on, deployed to impulsestore.net and serving traffic now. None of it is committed anywhere, so a disk failure or a careless git checkout takes out the live site's source and the only instrument GATE-EMAILS has.

Progress.md has carried this as a line in the risks table for three runs. It is one command, and it is the cheapest insurance in the workspace.

One thing to get right before committing, and it is why this is needs human help rather than a chore: that repo's GitHub remote is public (originn, verified 2026-08-10). Check what goes in — .obsidian/ is untracked and ungitignored there, and src/stripe_backup_code.txt is the block below. The .obsidian/ in website/ was checked this run and is harmless (24 KB, four config files, no plugins and no tokens — unlike vault/.obsidian/), but it should be ignored rather than committed by accident.

Steps - [ ] Add .obsidian/ to website/.gitignore — and src/stripe_backup_code.txt while you're there - [ ] Read git -C ~/Impulse/website status once, deliberately, before staging — it is a public repo - [ ] Commit the email-capture rebuild - [ ] Push, if you're happy for the site source to be public — it already is

  • In Progress
  • Done

Done when: the deployed site can be reconstructed from a commit rather than from your laptop.

Notes:

Clean up the stale Stripe backup-code file in the public website repo

needs human help · raised 2026-08-10 · what's left of the rotation block you closed

You rotated the code on 2026-08-09 and the new one is at ~/Impulse/stripe_backup/stripe_backup_code.txt — that's the path you couldn't remember, confirmed by timestamp, and it is not inside any git repo. The exposure is closed and the code still committed at website/src/stripe_backup_code.txt is dead.

What's left is filing, and it's worth doing only because the file still looks live to anyone who finds it — including you in six months, and anyone who reads a public repo.

One thing to keep in view rather than act on: the new code sits one directory above ~/Impulse, which CLAUDE.md says must never become a git repo. It was one once, by accident, in August. That rule now has a credential behind it.

Steps - [ ] git rm --cached src/stripe_backup_code.txt in website/, and add it to .gitignore - [ ] Move the new code into a password manager rather than a text file, if you'd rather - [ ] History purge (git filter-repo) is now optional — the code it exposes is dead. Skip it unless you're rewriting that history anyway

  • In Progress
  • Done

Done when: nothing in the website repo is named like a live credential.

Notes:

Redesign the hard override — the two-button 10-second hold is out

needs human help · BLK-01 · launch-plan.md §11.2 · remade 2026-08-09

Replaces the old "spec the hard override" block, with your conclusion built in: the two-button hold is not implementable on Board V1 (one user button plus reset) and is judged the wrong mechanic regardless, because a stop that needs the case open is a tax on the person in distress and a speed bump for the person cheating.

Concepts/Safety.md now lays out the alternatives — split short-press-silences from long-press-overrides, make the override loud rather than difficult, use the countdown as deliberation time, and set a floor that users may make more visible but never less available. It also argues that the vulnerable-user worry you raised is mostly a BLK-02 primitive-bounds problem, not an override problem: someone in crisis should rarely be depending on the override, and if they are, the device was allowed to enforce too hard for too long.

§11.2's requirement is unchanged and shouldn't be reopened — an unconditional stop, watch-alone, not disableable. What's open is the mechanism, and five specific questions at the end of that document.

  • In Progress
  • Done

Done when: §11.2 is rewritten with a mechanism that works on V1's one button, and Concepts/Safety.md shrinks to whatever is still undecided.

Notes:

automatable · raised 2026-08-09 · firmware_spec_v3_nrf.md §4.6

Deleting fingerprints deletes the only thing that ever noticed an anchor had been moved. Channel sounding measures the distance to the anchor honestly — but if the nightstand anchor is now in the kitchen, an honest distance to it means nothing, and "move the anchor" becomes the cheapest bypass in the system. It needs no tools and leaves no trace.

The fix is nearly free because the anchor and watch are the same board: the anchor has an IMU populated and is mains-powered. An anchor that detects sustained motion can flag itself, and the watch can decline to treat a recently-moved anchor as authoritative until it's re-confirmed in the app. What needs designing is the threshold, what "re-confirm" means, and whether flagging is a loosening change under §9.1 (it probably is — a user who can clear the flag can move an anchor).

2026-08-11 — it lost its sibling, and that sharpens it. The mains-loss question was expected to share this design and does not: the answer there was that the watch does nothing, because an unplugged anchor tells the truth until it stops answering whereas a moved one lies about where it is. That asymmetry is the argument for why this one does need watch-side handling, and it's worth putting in §4.6 when it's written.

Not urgent: it's a chunk-G-and-after task, and the port has to exist first.

  • In Progress
  • Done

Done when: it's specified in firmware_spec_v3_nrf.md §4.6 with thresholds and a re-confirmation flow.

Notes:

Decide and document the primitive bounds

needs human help · BLK-02 · §11.3

Max window duration, min gap between windows, daily cap, escalation cap.

Promoted in importance by the override work: Concepts/Safety.md argues these bounds — not the override — are what actually protect a vulnerable user, because §11.4 keeps the device deliberately blind to what is being restricted, so the bounds have to hold unconditionally. Getting the override right does not rescue an unbounded primitive.

2026-08-11 — one concrete example turned up. donningGraceS clamps to 0–1800 s, so a wake-up commitment can carry a thirty-minute grace. That is a bound nobody chose, sitting under a marketing claim that says the alarm can't be snoozed — see the flag in Soon. Worth using as the worked example when you set the rest.

2026-08-13 — that example is worse than it read, and the spec already admits it. Checked against the code rather than the spec this time. The 1800 s ceiling is enforced only by the clients. The app clamps (schedule_encoder.dart:101, seed_templates.dart:116) and phone_sim rejects out-of-range (schedule.py:142). The watch does neither — deserialize_events() (main.cpp:900) length-checks every field and clamps beepAnchorCount to 8, but copies donningGraceS straight off the wire into a uint16_t and uses it unbounded at main.cpp:3355 and :4907. The reachable maximum is 65535 s — 18 hours 12 minutes.

This is documented, not a defect found: firmware_spec_v2.md line 406 says it in as many words — "must be 0–1800 (app-enforced clamp; the firmware does not correct out-of-range values)." Nothing to correct in either document. What it changes is this block's job:

  • It is not a live bypass today. Increasing donningGraceS is a §9.1 loosening, so raising it on an existing commitment is quarantined ~24 h (main.cpp:3551). The gate holds.
  • But it is exactly the bound BLK-02 exists to decide, and it is the one place where the root-of-trust model is delegated to the client. CLAUDE.md's own invariant is that the app never enforces — the reason debug writes are compiled out of release builds rather than runtime-gated is that anything the app is trusted to enforce is a bypass for anyone who writes their own GATT client. The contract is documented and BLK-12 intends to publish the code.
  • So the real question is which bounds the watch enforces itself, not what the app's spinner allows. donningGraceS is the worked example, and it argues for the answer being "the watch clamps, and the spec says so."

  • In Progress

  • Done

Done when: written into the spec as numbers, with each bound saying which device enforces it.

Notes:

Draft SAFETY.md

automatable · BLK-12 · §11.7

The public-facing safety document — turns removal of the safety bounds from a cleanup task into an argument someone must make in public. Blocks making the code public, not ship.

Distinct from Concepts/Safety.md, which is internal design thinking about the override mechanism. This one is the repo-facing statement of what the bounds are and why removing them is a choice. It should probably wait until BLK-01 and BLK-02 settle, or it will document a design that changes.

  • In Progress
  • Done

Done when: drafted and reviewed by you.

Notes:

Write the prepared response to the coercion narrative

needs human help · BLK-06 · launch-plan.md §12.8

Before launch, not during. §12.8 calls this the reputational tail risk nobody plans for: one "I bought a dystopian punishment watch" take and you spend the launch on defence.

  • In Progress
  • Done

Done when: a calm written response exists that you'd be happy to post as-is.

Notes:

Clinician hour

human only · BLK-14

One psychologist working with eating disorders or OCD, asked: how would a patient of yours misuse this?

Concepts/Safety.md adds a second question worth asking in the same hour: would a patient of yours be able to use this stop, in the state they'd need it? That is the test the override design can't pass on its own reasoning.

  • In Progress
  • Done

Done when: the conversation has happened and the notes are filed.

Notes:

Trademark filing on "Impulse"

human only · BLK-13

The lever for open-source safety bounds, since a license can't restrict use.

Your $350 / post-launch note is now in launch-plan.md §13 with one caveat attached: deferring the filing is fine for the launch itself, but §11.7's open-source safety argument depends on owning the name. Publishing the code before filing spends the lever — so if BLK-12's SAFETY.md and going public land before the money does, this ordering needs revisiting.

2026-09-24 — file it as Impulse Gear LLC (organised 2026-09-23), not personally. See the LLC block in Soon.

  • In Progress
  • Done

Done when: filed.

Notes: costs $350. may do after launch if i get enough launch money.

Pricing and BOM decisions

needs human help · BLK-07–BLK-11

None of these block this month; all of them block the campaign. The module swap moved the BOM — two Fanstel modules in place of one ESP32-C3, on a 4-layer board instead of 2 — so BLK-09 in particular is now a real question rather than a confirmation.

2026-08-11 — the WiFi decision fixes the BOM you're costing against. Dropping the WM02C would have taken the watch and anchor from ~$15 to ~$10; you decided to keep it, so ~$15/$16 stands and BLK-09 and BLK-11 are answered against the WiFi build. That removes a conditional that had been hanging over both.

The ladder is now declared twice. As of 2026-08-09 the site's PricingSection.vue mirrors §4 — Starter $135, Complete $209, Whole home $269, Anchor 2-pack $69, early-bird $119. email-capture-setup.md §6 records it. If §4 moves, that component moves in the same edit, or the site advertises a price the campaign won't honour.

Steps - [ ] BLK-07 $199 outright vs $149 + subscription - [ ] BLK-08 main crowdfunding tier at $125 or $135 (plan recommends $135; the site already shows $135) - [ ] BLK-09 confirm $15/$16 are BOM, not landed — and re-cost against V1 - [ ] BLK-10 MOQ tier pricing in writing from the PCB manufacturer - [ ] BLK-11 anchor BOM reduction pass

  • In Progress
  • Done

Done when: each is decided and written into launch-plan.md §4.

Notes:

Regulatory/claims review with a lawyer before the first ad

human only · BLK-05

  • In Progress
  • Done

Done when: the review has happened and §10's claims fence reflects it.

Notes:

File the remaining datasheets

needs human help · raised 2026-08-08 · updated 2026-08-09

Three of four are done. BM20C.pdf, WM02C+Product+Specifications.pdf, and BC15M+Product+Specifications.pdf are all in datasheets/ with full README rows as of 2026-08-09, and reading them produced Concepts/FCC Certification.md.

What's still missing is the LIS3DHTR IMU datasheet, despite the part being central to worn/motion detection (spec §5.4.5) — and it is the part firmware_spec_v3_nrf.md §4.6's moved-anchor design would lean on. The nRF54LM20A SoC datasheet is also worth having directly from Nordic rather than via Fanstel's module document.

2026-08-10 — one more worth having, and it's now load-bearing: the XC6220B331MR regulator datasheet. It is the part in the middle of the failure investigation, and nobody has its thermal ratings or its behaviour in current limit to hand. 2026-08-11: still the input to the VBUS capacitor value in FCC Respin.md §2.2.

Steps - [x] BM20C ✅ 2026-08-09 - [x] WM02C ✅ 2026-08-09 - [x] BC15C fallback ✅ 2026-08-09 - [ ] LIS3DHTR IMU - [ ] nRF54LM20A SoC, from Nordic - [ ] XC6220 regulator, from Torex

  • In Progress
  • Done

Done when: all six PDFs are in datasheets/ and the README table is filled in.

Notes:


Manual notes

Anything written below this line is preserved across /parselogs runs.