Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dmn-hack

Brain Default Mode Network (DMN) hack tool.

DMN Pager is a GNOME Shell extension that turns the top panel into a cognitive-state instrument: a live-drawn hourglass whose sand volume is the progress bar, and behind it a retro pager console where you declare what mode you are in, who you are being, and for how long.

It is a software prototype of a physical desk pager. Everything on screen is something the hardware would have to render, so the UI doubles as a firmware spec — and the whole config exports as a single JSON payload.

The pager console


What it does

Collapsed by default. The console shows three things — the role you are holding, the mode you are in, and the clock. The tab strip and its pages stay folded away behind the key, because in use you rarely need them.

The header block is the role — who you are for this block. The name is set large and the brief is spelled out underneath at a size you can read without leaning in. drops an inline list of roles to switch between. ARCHITECT, SURGEON, SCOUT, EDITOR, OPERATOR ship as defaults.

The mode is the chip beside the duration well, with the same picker. Each mode owns a unique colour (picking a taken colour swaps it with whoever had it), a glyph, a default length, and a directive — the line under TRAIN that tells the network what to do. That colour drives the header, the chip, the progress rail and the panel hourglass, so the whole instrument reads as one state. A mode can bind a role, so choosing the mode also assumes the role.

Switching happens only in those two pickers; editing happens only in the MODES / ROLES tabs. There is deliberately no third place to change either.

The duration well carries the block's shape: its length, and on the lower line when it started and when it lands — 13:27 @> 14:57 +7.

Four clocks, all sharing the same engine:

Tab What it is
TIMER Counts a fixed block down. Duration field, presets, ±5 min.
POMO Pomodoro: a focus leg per round, a short break between each, and the long break closing the set. Round pips, set total and landing time.
WATCH Stopwatch with hundredths, laps, best/worst split marking, copy-out.
ALARM Counts down to a wall-clock HH:MM — "page me at".

Minutes or seconds. The MIN/SEC key in the top strip switches the unit everywhere at once: how bare numbers in duration fields are read (90 is ninety minutes or ninety seconds), whether clock readouts show seconds, what the presets offer, and how much the steppers and the ± keys move.

The train — a ticker that reads like reading

A news ticker across the top bar, filling whatever width the panel can spare. It does not crawl. A uniform crawl reads as machinery and costs real attention to track. Reading is not continuous either: the eye jumps, fixes, jumps again, and rests longer at punctuation. The train moves the same way — one word arrives at the read head and holds, then the next.

The hold is beat + perCharacter × length, multiplied at punctuation: half the configured rest mid-clause, all of it at a full stop. The per-character term is what keeps it from sounding like a metronome — long words earn a longer look.

It rotates through three slots:

Slot Shows
BRIEF the active role's brief — always the live pager state
TRAIN the active mode's directive — likewise live
label one of your saved lines, advancing one per pass

So the first two always tell you where you actually are, while the third plays a list out over time. Each saved line carries its own repeat — hold it for several consecutive passes — and a global hold freezes the rotation on whatever is showing.

Every slot keeps its own rhythm. Motion, beat, per-character, punctuation rest, slide, words-per-step and the rest afterwards are stored per slot, not once for the ticker. The brief can hold each word in place at a walking pace while a saved line snaps past in chunks of three. A slot follows the defaults until you touch it; the first edit takes a private copy, marked in the slot row, and RESET hands it back to the defaults.

Three motions: STEP (the default above), RSVP (each word held centred, so the eye never travels) and GLIDE (the old continuous crawl, for contrast).

All of the ticker's setup lives in Settings → Ticker: the slot picker and its motion/rhythm, the font, the saved lines with their repeat, and the rotation switches. Resting the pointer on the ticker holds the line so you can finish reading.

The font is whatever is installed. Settings → Ticker → RhythmFont opens the system font chooser, so any family on the machine can drive the ticker. It sits inside the slot editor, so each slot picks its own face and size — leave the slot on Defaults to set the face for everything.

The panel indicator

Drawn with Cairo, not an icon theme:

  • Hourglass for timer and pomodoro. The top bulb is a cone, so the sand surface drops as remaining^(1/3) — slow at first, then a plunge, exactly like the real object. The bottom pile's level solves the trapezoid area so the two volumes stay consistent, and a grain stream flickers through the neck while running. It physically flips when a leg ends, and dims on pomodoro breaks.
  • Stopwatch with tick ring, swept sector and a hand that sweeps once a minute.
  • Bell for the alarm, filling as the wait burns down.

The glass is tinted with the active mode's colour, so the panel tells you your state at a glance without reading anything. Beside it sits the mode's glyph and the role name, cut with an ellipsis at ten characters — ⧗ 35m ◆ SURGEON — so the role is legible from the top bar without the chip ever growing enough to crowd the panel. The length is configurable, and 0 leaves just the glyph.

The indicator sits at the left of the top bar, next to the left-most item. Settings → PagerTop panel moves it: which box it lives in (left, centre or right) and its index within that box, whether the remaining time shows at all, how many characters of the role name survive, whether the mode name is spelled out beside them, and whether the glass takes the mode's colour.

Input Action
Click Open the console
Middle click Start / pause
Scroll ±1 minute
Super+Alt+D Open the console
Super+Alt+Space Start / pause

The pickers, the MIN/SEC key and the collapse key all live in the console itself.

Where things live

The console is for what you touch during a session; the settings window is for what you set up once. Nothing appears in both.

Console tabs TIMER POMO WATCH ALARM MODES ROLES
Settings pages Pager Ticker Modes Roles Log Signals

Log lives in the settings window: today's total per mode, the recent session list with cut runs marked, and a tab-separated copy of the lot.

POMO tab MODES tab

The header strip, the grey duration well with its landing stamp, and the colour-keyed chip beside it are lifted from the original sketch. Four phosphor themes ship: phosphor (green), amber, ice, ash.


Install

./install.sh

Then log out and back in — Wayland cannot restart the shell in place — and the extension is enabled. To try it without logging out:

dbus-run-session -- gnome-shell --nested --wayland

Or with make:

make install        # compile schemas + copy into place
make enable
make logs           # follow shell output, filtered

Requires GNOME Shell 47–49. Developed and verified against 49.8 on Fedora.


Layout

src/dmn-pager@blackswan.local/
├── extension.js        panel indicator, notifications, keybindings, session persistence
├── prefs.js            libadwaita editor + JSON config export/import
├── stylesheet.css      the casing, the phosphor screen, the rubber keys
├── schemas/            GSettings schema (all config lives in one dconf path)
└── lib/
    ├── clock.js        timer/pomodoro/stopwatch/alarm state machine  (no St — unit tested)
    ├── store.js        mode + role + ticker-line CRUD over GSettings JSON
    ├── icon.js         Cairo hourglass / stopwatch / bell
    ├── train.js        the top-bar ticker
    ├── pager.js        the console UI
    └── util.js         durations, colour maths, and the ticker rhythm model

clock.js measures against the monotonic clock, so suspend, DST and NTP steps cannot corrupt a session, while also keeping a wall-clock deadline so a lock/unlock cycle or a shell restart rehydrates the running session correctly. A session that expired while you were away is reported rather than silently dropped.


Development

make check      # parse every source file, then check for dangling method calls
make test       # unit tests for clock.js and util.js — no shell needed

make check does three passes. The first only parses: a class whose method was deleted still parses perfectly and then throws the moment the shell builds it. The second compares every this._foo(...) against the methods the file actually declares. The third checks every schema key is reachable from some control — an edit once deleted a whole group of ticker settings and nothing noticed, because a setting with no UI still parses, still tests, and still runs.

Visual testing

tools/shoot.sh renders the real extension in a throwaway headless GNOME Shell and writes a PNG. It seeds an isolated XDG_CONFIG_HOME, so your live session's settings are never touched.

tools/shoot.sh                        # timer tab, loaded fixture
tools/shoot.sh timer compact          # the shipped collapsed default
tools/shoot.sh pomodoro loaded
tools/shoot.sh stopwatch watch
tools/shoot.sh pick-role compact      # catches a picker mid-drop
tools/shoot.sh modes real out.png     # a real desk config, third argument

Scenarios come from tests/fixture.py (idle, running, watch, loaded, compact, real) and use fixed mode/role ids so history rows always resolve.

real is the odd one out: rather than a table invented for the screenshot, it is a working config lifted out of a live install with dconf dump, plus a few entries added to reach what a lived-in table happens not to have — a mode that binds a role, a role carrying a brief, a saved ticker line with repeat above one, and a BRIEF slot that has taken a private copy of the rhythm. It also runs the pager the way that desk runs it: bare numbers read as seconds, and the ticker gliding in an installed face rather than the default.

Its point is that the names are mixed-script — TASK/FOCUS and แค่อยู่ตรงนี้ in one table, SOFTWARE ENGINEER beside คนธรรมดา(คนหนึ่ง). Ellipsis, panel truncation and the ticker's word splitting all behave differently once the text stops being ASCII, and no invented fixture was reaching that.

the real config, TIMER tab the real config, MODES tab

The state is only ever seeded inside the nested shell, under a throwaway XDG_CONFIG_HOME — the live session it was copied from is never written to, so a snapshot of your own desk cannot disturb your own desk.

Two notes on why this is more involved than it looks: org.gnome.Shell.Screenshot only answers an allow-list of D-Bus senders, so the script injects a temporary in-process capture hook into the installed copy and removes it afterwards; and dconf always writes through whichever service owns the session bus, so seeding happens inside the nested dbus-run-session.

DMN_PAGER_AUTO_OPEN=<tab> is the only dev hook in the shipped source: it drops the console open shortly after the shell starts. Unset, it does nothing.


Toward the physical build

The whole configuration is one dconf subtree, which is the point:

dconf dump /org/gnome/shell/extensions/dmn-pager/

Preferences → SignalsCopy config puts the same thing on the clipboard as JSON:

Here is a real one — a desk in daily use, trimmed to three modes and three roles. The whole table, with the session log and the ticker settings around it, is the real fixture above, so the payload and the screenshots are the same state:

{
  "v": 1,
  "modes": [
    {"id": "m_ms74sjkh8cwu8", "name": "TASK/FOCUS", "color": "#c77dff", "glyph": "",
     "duration": 1800, "directive": "Focus just current task.",
     "roleId": "r_ms7da68m2yema", "runs": 6, "seconds": 15743},
    {"id": "m_ms7du943h5iw", "name": "แค่อยู่ตรงนี้", "color": "#9bb4a0", "glyph": "",
     "duration": 1500, "directive": "แค่อยู่ตรงนี้ แค่หายใจ แค่รู้สึก แค่มีชีวิต",
     "roleId": "r_ms7drqsgb596", "runs": 2, "seconds": 1996},
    {"id": "m_ms9r1kd0treal", "name": "TASK/REVIEW", "color": "#ffd60a", "glyph": "",
     "duration": 1800, "directive": "Read what exists before adding to it.",
     "roleId": "r_ms7dm72i8avkh", "runs": 0, "seconds": 0}
  ],
  "roles": [
    {"id": "r_ms7da68m2yema", "name": "SOFTWARE ENGINEER", "glyph": "",
     "directive": "", "modeId": ""},
    {"id": "r_ms7drqsgb596", "name": "คนธรรมดา(คนหนึ่ง)", "glyph": "",
     "directive": "กินอย่าอาย ตายอย่ากลัว ยากช่างหัว ตายปลด", "modeId": ""},
    {"id": "r_ms9r1kd1treal", "name": "ARCHITECT", "glyph": "",
     "directive": "Hold the whole system in view. Draw it before you type it.",
     "modeId": ""}
  ],
  "activeMode": "m_ms74sjkh8cwu8",
  "activeRole": "r_ms7da68m2yema"
}

runs and seconds are the lifetime counters the console shows under each mode; ids are generated once and never reused, which is what lets a session log written months ago still resolve to the mode that produced it. A mode with roleId set assumes that role when picked, and a role with an empty directive simply leaves the header brief blank.

Paste is the mirror of copy — Preferences → SignalsPaste config reads the same object back, replacing every mode and role at once, so a desk can be moved to another machine, or a table can be authored by hand and dropped in.

That payload is deliberately small enough to flash onto a microcontroller. The display contract the firmware has to honour is the screen area of the console: a header strip, a duration well with a landing stamp, a colour-keyed mode chip, a one-line role ticker, and a progress rail — plus one RGB LED for the mode colour and a mono readout for the clock.


Releases

Tag What landed
v0.2.0 The train — the top-bar ticker, its three slots and the per-slot rhythm model. A full libadwaita settings window (Pager Ticker Modes Roles Log Signals) with the session log and the JSON config payload. Panel placement and readout options. The test passes for dangling methods and unreachable schema keys.
v0.1.0 The console and the four clocks, modes and roles, the Cairo panel indicator, session persistence across lock and restart.
git tag                       # what exists
git show v0.2.0 --stat        # what a tag carries

The extension's own version lives in metadata.json (version for the shell, version-name for people) and is expected to match the tag.


Licence

MIT — see LICENSE.

About

Brain Default Mode Network (DMN) hack tool.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages