Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
596363e
docs: record cohort 2 run sheets (runs 11-40)
toobuntu Jul 19, 2026
ad9f651
docs: index cohort 2 in cursor-on-black matrix
toobuntu Jul 19, 2026
6638933
docs: record cohort 2 detection diff in P20/P29
toobuntu Jul 19, 2026
80ed1a0
docs: record run sheets 41-60 (C1 lever, group C)
toobuntu Jul 19, 2026
6e901dc
docs: index runs 41-60; add short codes, group C
toobuntu Jul 19, 2026
f2cb45e
docs: extend P29 with runs 41-60 findings
toobuntu Jul 19, 2026
ee5ce9f
feat: add extcycle recovery and repro trigger
toobuntu Jul 19, 2026
0b3e1f6
docs: record extcycle tooling; run 58 caveat
toobuntu Jul 19, 2026
dcaa3dc
docs: record run sheets 61-85 (soft trigger)
toobuntu Jul 20, 2026
96b2c3a
fix: repro wake ordering; add awake cue, --lock
toobuntu Jul 20, 2026
bf5f482
docs: record soft-trigger series; attribute cause
toobuntu Jul 20, 2026
9bf3c65
fix: detect wake via NSWorkspace notifications
toobuntu Jul 20, 2026
e07d882
docs: record shakedown failure and wake rework
toobuntu Jul 20, 2026
b8654be
docs: record run sheets 86-104 (MCL controls)
toobuntu Jul 20, 2026
ab5168a
docs: relabel AC runs 87-97 group B to D
toobuntu Jul 20, 2026
902e4f7
feat: auto-recover cursor-on-black at wake settle
toobuntu Jul 20, 2026
981032b
docs: record runs 86-104; auto-recovery notes
toobuntu Jul 20, 2026
2daa916
feat: add fbpower probe recover method
toobuntu Jul 20, 2026
710314b
docs: add ADR 0010; architecture recovery note
toobuntu Jul 20, 2026
172fe20
fix: address review of the wake-recovery query
toobuntu Jul 20, 2026
4739f4d
docs: write ADR 0009 (SP2309W color quirk)
toobuntu Jul 20, 2026
ea0bff7
docs: record auto-recovery validation runs 105-107
toobuntu Jul 20, 2026
db0849a
docs: note live auto-recovery validation in P29
toobuntu Jul 20, 2026
db4d0f7
docs: restructure ADRs 0009-0010 to MADR 4.0
toobuntu Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ Keys:
- `autoBlackoutOnExternalConnect` (BOOL, default YES)
- `blackoutActive` (BOOL) — persisted blackout intent
- `verbosityLevel` (Integer, default 1; 2 enables `[verbose=2]`-tagged log lines)
- `recoveryStrategy` (String, default `displaysleep`; `none` disables the
post-wake cursor-on-black auto-recovery — set via
`blackoutd recovery <none|displaysleep>`; see P20/P29 and
`docs/debug/cursor-on-black-matrix.md`)

## Key technical details

Expand Down Expand Up @@ -341,8 +345,10 @@ For non-trivial work, an agent should also read:

1. `docs/technical-debt.md` — current priorities and known issues
2. `ROADMAP.md` — milestone plan (cross-references the P-numbers above)
3. `docs/decisions/` — accepted ADRs (4 today: Trojan Source, daemon
presence, wake-settle timer, merge strategy)
3. `docs/decisions/` — ADRs 0001–0010 (0009 is `proposed`, the rest
accepted). For display work start with 0003 wake-settle timer and
0010 cursor-on-black detection/recovery; 0009 is the SP2309W color
quirk (repo-foundation has its own, unrelated 0009 on logging)
4. `CONTRIBUTING.md` — encoding policy, REUSE/SPDX conventions, commit
and PR conventions

Expand Down
12 changes: 12 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ fires reconfiguration callbacks as side effects. A 2-second window
connect/disconnect events. A safety check at window close catches any real
events that arrived during the window.

**Detector-gated wake recovery** — Some wakes leave the external display
black (cursor only) with every CG/WindowServer-visible field healthy — a
DCP/scanout stall below WindowServer. The one host-visible signal is a
WindowServer log line (SkyLight coalescing a pending hotplug "out" with
the wake's "in"; 56/56 black vs 0/33 clean across the empirical matrix).
At wake-settle, with an external present, the daemon queries the unified
log for that marker and, when present, runs a display-sleep cycle
(`pmset displaysleepnow` + `caffeinate -u`) — the recovery validated
locked and unlocked. Gated by the `recoveryStrategy` preference
(`blackoutd recovery <none|displaysleep>`). See ADR 0010 and
technical-debt P20/P29.

### Companion Project

[displayrecommitd](https://github.com/toobuntu/displayrecommitd/) is a
Expand Down
327 changes: 323 additions & 4 deletions docs/debug/cursor-on-black-matrix.md

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run011-grp-a-20260719-000924.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-000924

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 11 started: 2026-07-19 00:09:24
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. AC -> AC
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 00:09:42.726 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-000953
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [x] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [ ] E0 [x] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [x] yes [ ] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run012-grp-a-20260719-082315.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-082315

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 12 started: 2026-07-19 08:23:15
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 08:23:33.415 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-082343
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [ ] B1 [x] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [x] E0 [ ] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [ ] yes [x] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run013-grp-a-20260719-110044.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-110044

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 13 started: 2026-07-19 11:00:44
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 11:01:03.321 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-110117
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [ ] B1 [x] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [x] E0 [ ] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [ ] yes [x] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run014-grp-a-20260719-110205.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-110205

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 14 started: 2026-07-19 11:02:05
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 11:02:23.897 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-110237
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [x] B1 [ ] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [ ] E0 [x] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [x] yes [ ] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run015-grp-a-20260719-110325.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-110325

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 15 started: 2026-07-19 11:03:25
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 11:03:43.719 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-110357
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [ ] B1 [x] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [x] E0 [ ] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [ ] yes [x] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run016-grp-a-20260719-110439.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-110439

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 16 started: 2026-07-19 11:04:39
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 11:04:57.798 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-110511
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [ ] B1 [x] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [x] E0 [ ] E1 [ ] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [ ] yes [x] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
46 changes: 46 additions & 0 deletions docs/debug/repro-matrix/run017-grp-a-20260719-120552.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!--
SPDX-FileCopyrightText: Copyright 2026 Todd Schulman

SPDX-License-Identifier: GPL-3.0-or-later
-->

# repro run sheet — 20260719-120552

Machine-filled by `blackoutd repro`. Fill in the eyewitness
checkboxes and notes; the matrix
(`docs/debug/cursor-on-black-matrix.md`) indexes these sheets
per group.

```text
Run #: 17 started: 2026-07-19 12:05:52
Build: v0.4.0 built: 2026-07-19T04:08:56+00:00 (UTC)

Conditions (pre-sleep -> at capture):
group .................. A
lid .................... open -> open
moved during sleep? ... [x] no [ ] yes: ______
session ................ unlocked -> unlocked
power .................. battery -> battery
wake ................... scheduled (--wake 15)
recovery applied ....... none
settle ................. 20 s
daemon settled ......... 2026-07-19 12:06:10.853 blackoutd[80240:1872712] [wake] — display pipeline settled

Bundles:
post-wake = docs/debug/blackoutd-diag-20260719-120624
post-recover = n/a

@ wake (immediate — first look as the panels light):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [ ] B0 [x] B1 [ ] B2

@ post-wake capture (settled — at the "capturing post wake"
cue; the state the bundle records):
external ... [ ] E0 [ ] E1 [x] E2 [ ] E3
built-in ... [x] B0 [ ] B1 [ ] B2

Outcome:
cursor-on-black occurred this run? ... [ ] yes [x] no
(yes = settled external E1; note E2/E3 variants in Notes)
Notes: ____________________________________________________________
```
Loading
Loading