Two notes nobody ever saw
Greenhouse has two places where you can write yourself a note. When you capture an idea, you can jot a quick sketch of what it is. When you log a touch on a project, you can leave a handoff note, a “letter to your future self” about where you left off. Both get saved. Neither one ever showed up anywhere in the app.
The capture note problem was structural: the field existed on every item, but the wire type that ships item data out to the frontend, the thing every card on the dashboard renders from, just didn’t include it. The UI had no bug hiding the note - there was nowhere in the data for the note to even arrive. That meant every Vault-or-Work decision, keep working on this or shelve it, was being made on a project’s name alone, sometimes an auto-generated one if you skipped naming it.
The handoff note was a different kind of miss. That data flows fine, it’s sitting in the touch history, and there’s already a command that returns it. The dialog where you’d actually want to read it, the one that pops up right when you’re about to log a new touch and pick up where you left off, just never asked for it. I built the delivery mechanism and then never wired the read side back in.
Fixing both was mostly about closing that gap rather than inventing new plumbing. Two fields added to the shared item type, populated from data that was already there. A fetch added to the touch dialog on open, best-effort, if it fails you just don’t get the banner, you’re not blocked from logging your touch. A show-in-Finder button and a “dormant for” duration added to the one card that was missing what every other card already had.
One design decision I made along the way: whether “dormant for” should compute the current time inside the component, or take it as a value passed in. I went with passing it in, defaulting to the real clock when nobody supplies one. It’s the same rule this project’s backend already follows for anything time-based, never call the system clock from inside a function you want to test deterministically. A test can hand it a fixed number and assert on an exact string instead of writing a regex that just hopes the day boundary doesn’t land wrong.
Related reading
The scan that offered to import itself
An import scanner that found the app's own scaffolding, then re-offered a folder it had just imported - two versions of the same missing conversation between layers.
Adding a native macOS menu to Greenhouse broke Cmd+Q, and my test harness couldn't press Cmd+N either
set_menu replaces the default menu, it doesn't extend it - taking Quit, Hide, and every Edit shortcut with it. Then the WebDriver actions endpoint turned out unable to press a key.
Teaching a project manager to recognize a Logic Pro session
.logicx files aren't files, they're bundles - and the filter hiding .DS_Store junk was hiding every DAW project too. Plus the silent no-op click that fooled a retry loop.