Changelog

1,076 changes across 26 active days in the last 30.

Every line below is a commit message, published as written. Merge commits, tooling commits and planning notes are left out; nothing is summarised or rewritten. Today is still in progress and will grow until the next build.

Sunday 20 September 2026

Athenana

  • iOS capture: record the fix wave's three Swift traps, trim the outbox's forgotten set to the file, and tolerate spaces in an entitlements plist
  • iOS capture fix wave, Swift minors: one ladder for the link sheet, a merged outbox move, sized refusals, Debug-only strings
  • iOS capture spec and docs: the built handler contract, §10 as the ledger, the measured counts
  • iOS capture fix wave: sweep dot-files out of the staged appex, drop the unread fromNativeHost, pin the fourth client and CORS credentials
  • Share sheet: re-encode a HEIC through the one ServerImage rule the intent already used
  • build-ios.sh --extensions: match each group under its own entitlements key, and read the closure off the stager
  • Outbox: an id this instance removed is never read back off a file whose rewrite failed
  • iOS capture: pin the three clients' field sets on the server, and record what the build learned
  • Safari staging: rewrite the manifest with /usr/bin/python3, since an Xcode script phase has no node on its PATH
  • Safari extension on iPhone: the existing extension, staged by the Mac build's rule, with the app's session answered by a native handler
  • UI test: retry the article-link tap, since the reader's position restore moves the link under it
  • Extension: only a session-shaped reply is a native host's answer, so an echoing handler cannot read as a signed-out phone
  • Extension: take the session from a native host when there is one, so the iPhone build needs no pasted token
  • App Intents fix round: a HEIC is re-encoded as JPEG since IntentFile will not, and Continue reading opens the article on a warm app too
  • iOS app: Save to Athenana and Continue reading as App Intents, so Shortcuts and Siri keep their composability
  • Outbox: a purge re-reads the file first, so a picture the extension parked goes with it
  • UI test: wait for the surface's single card to settle before tapping it
  • Outbox: re-read outbox.json before every read and write, so the share extension's entries survive the app's next save
  • iOS share extension: share → saved → done, with a note one tap away and an outbox for the plane
  • iOS app: an App Group for the outbox and a Keychain access group for the token, ahead of the extensions
  • CapturePayload: key an image on its bytes, not its name; a caption's trailing slash still marks the link
  • AthenanaKit: one payload for every capture, a multipart save, and an outbox entry that carries a file

wyome.com

  • Refresh the banked archive from the server
  • Make the reclassify() archive write atomic like the harvest write already is
  • Classify the two spam families in the generator too, and re-file what was already banked
  • Say that Athenana's reader now shows an item's pictures, from copies on its own server
  • Restore "no hidden image" on the weekly-email promise
  • Promise that no image in the weekly email reports an open, not only no hidden one

Saturday 19 September 2026

Athenana

  • Drop a forwarded newsletter's unsubscribe footer from the reader
  • Bring the reader's own tests onto the new picture rule, and stop "kept" meaning two things
  • Move the worker's --timeout with the budget FetchArticleImages raised
  • Reader: stop running blocks together, drop page furniture, and show an article's pictures again

wyome.com

  • Refresh the banked archive from the server
  • Say what the 403 double fault actually cost: refusals logged as 500
  • Serve Apache's own 403 page on the other three docroots too
  • Serve Apache's own 403 page to a refused request
  • Name both candidate paths in the missing-spam-list warning, and fix two facts
  • Test the Matomo wiring with a host that is not also in SPAM_HOSTS
  • Filter the Matomo referrer-spam list on the statistics page
  • Carry the referrer-spam block on the other three docroots
  • Refuse a request whose Referer names a known spam family
  • Record a referral only on a 200 or 304, so a refused request never reaches the page
  • Refresh the banked archive from the server

Wednesday 16 September 2026

Athenana

  • CSP: let the IndieAuth consent form redirect to the native apps' scheme
  • iOS app review fixes: pictures over the API with a bearer, a 304 keeps the reader's block, snapshots respect the purge, notes through ReadableHtml, and a lens keeps the way back
  • iOS app: a purged outbox takes nothing and the open reader flushes first; a failed refresh keeps the deck paging and spends no window
  • iOS app: offline deck and outbox replay on foreground, sign-out that purges, a release script, screenshots, and the record
  • iOS app: the back flipped over the surface's reader has Open original; a list jump pages; a dead state dropped
  • iOS app: the card back with share-out, lenses with their list and chip, and the surface with search
  • iOS reader: a flushed position names its rendering, so reopening the card resumes; the trailing report is the latest build's
  • Reading API and iOS reader: a card's position names its rendering, and the reader opens at the block only for that rendering
  • iOS reader: the article in a WebView, a block-indexed position through the outbox, tap-to-reveal chrome, Keep, the link sheet, typography per device
  • iOS app: Next mutates before it awaits, history is ids, and a refused token signs out with the full purge
  • iOS app: a swipe is Next and Back — it passes and remembers the card, as the compass does
  • iOS app: sign in, the deck and its compass, cards by type, and the stopping-point card
  • iOS reader: exclude the reparented <script> from position tracking, and clean up the postbuild strip
  • iOS reader: the page template and a script that reports the block index, tested with Node
  • AthenanaKit: the outbox and the article cache survive a purge or a newer position landing while a request is in flight, and a drop is reported
  • AthenanaKit: an article cache that revalidates by ETag, and an outbox that replays in order and keeps a position's own clock
  • AthenanaKit: pin the session's departures from the brief, and refuse a callback from another issuer
  • AthenanaKit: the session — PKCE, the IndieAuth flow that refuses a foreign state, and a token that lives only in the Keychain
  • AthenanaKit: models and a client for every reading endpoint, with fixtures the PHP suite holds to the presenter
  • iOS app: a generated Xcode project, the AthenanaKit package, and a build script that reads xcodebuild's own status
  • Reading API: a note reads from its body, and an image card carries the full picture
  • Newsletter review follow-ups: aspect-ratio note, access-log clause, comment reword
  • Newsletter view polish: one issue date, block @php, text escaping, lowercase wordmark, bulletproof Read pill
  • Send CORS on the woff2 fonts so Apple Mail renders them
  • Harden the newsletter body-identical guards against a smuggled value
  • Record what the weekly email fetches, and why that is the promise now
  • Say on the privacy page what the weekly email now fetches, and hold the view to it
  • Set the weekly issue in the app's own typefaces, served from this host
  • Show each emailed link's preview picture, through the public route, and pin that every reader gets one body
  • Fix two newsletter tests that were silently asserting nothing
  • Send the weekly issue as a designed page, with a text part beside it

wyome.com

  • Say what the weekly email now fetches: pictures and a typeface, the same for every reader
  • Refresh the banked archive from the server

Tuesday 15 September 2026

Athenana

  • Reading API review fixes: positions in UTC and on every card, a bad host lens is refused, and four tidy-ups
  • Reading API review fix: one position per item, the search test fails rather than passes under a transaction, and only the card back's own echo of visibility is exempt from the principle-6 guard
  • Reading API: prune passes nightly, hold principle 6 with a test, and record what the build learned
  • Deck settings: the switches, over the API and on a web screen
  • IndieAuth: our own apps as a client, returning to a custom scheme the client page lists
  • Reading API review fix: the card back gates Rec League behind the same switches as its share list
  • Reading API: the card back, share-out through one action both controllers call, and a share scope
  • Reading API: keep a passage over the API, and bind every highlight to its source item
  • Reading API review fix: the resurfaced shelf resolves switches in one query, not one per item
  • Reading API: the surface's two shelves, and one lens for tag, host and search
  • Reading API review fix: a tampered cursor is a 422 and not a 500, base64url for the iOS client, and a walk never re-deals what became in-progress after it began
  • Reading API review fix: a highlight in progress is dealt once, at the front; a switch off removes an in-progress item too
  • Reading API: deal the deck — in-progress first, then the operator's pattern over seeded ingredients
  • Reading API review fix: read items.host instead of re-deriving it, make both upserts race-safe, and cover ReadingCard
  • Reading API: the card, a block-indexed position that the older device cannot overwrite, and passes
  • Reading API review fix: drop the scope by name in RecordOpen, and two unused test imports
  • Reading API: the reader as blocks, with a hash and an ETag, and the open recorded
  • Deck switches: what a person may leave out, and the operator's defaults
  • Reading API: positions, passes, a highlight's source item, and per-user deck switches

WyHealth

  • Read a silent probe as no answer, not as absence

Hosting monitor

  • Stop not-served and dir-listing passing on a server nobody reached
  • Say the Mac was offline instead of rendering eight sites down

Monday 14 September 2026

Athenana

  • Run the feed cards the full column, the width the board's list view has
  • Select every tag on the manage-tags page with one press, and clear them with the next

Sunday 13 September 2026

Athenana

  • Prune a fetched feed with no entries whatever its age, and name each feed the prune takes
  • Raise the narration ceiling to 60,000 characters, and count the saved text on the item page
  • Keep a Day One entry whose URL line is longer than the save form allows as a note
  • Hand the Reeder job test the Day One action too, and untangle the format tests after the rebase
  • Bound the Day One decode and the text columns from the bytes, and anchor the guards
  • Name Day One on the import screen, and count its photos and skipped entries
  • Ask the zip for its journal before reading the upload, and bound the rest by size on disk
  • Route a Day One export through the import job, zip open for its photos
  • Own the Day One test zips, and say nothing per entry when there is no zip
  • Put a Day One entry's photos in the note's gallery, the first as its card picture
  • Say what keeps a binned Day One entry binned, bound the uuid, count tags as the vocabulary does
  • Import a Day One entry as a private note, or a private link when it is a share-sheet save
  • Refuse a URL line that carries prose, and read a CRLF body the same as LF
  • Read a Day One entry's text: the escapes, the share-sheet shape, the note body
  • Read the journal JSON out of a Day One zip, in place
  • Detect a Day One JSON export
  • Bound the import upload by an archive ceiling of its own
  • Run athenana:prune-feeds daily at 03:30
  • Forget feeds silent for a year: athenana:prune-feeds
  • Make the feeds page a list scroll.js extends fifty rows at a time
  • Move the Share panel under the saved page text
  • Drop the fill from the item page's Share panel; it keeps its outline
  • Put Previous / Next and Back on one row: the nav on the left, Back on the right
  • Put Read / Listen on the tags' own row, right-aligned; the chips wrap beside them
  • Move the add-a-tag field under the Title and note form; the chips stay under the title
  • Reorder the item page: title, tags, Read/Listen right-aligned, picture, share, labelled text
  • Call the first two tabs In and Out, under the Import / Share heading
  • Make site: search the saved URL's domain, and count a feed's saves the same way
  • Head the four sharing tabs "Import / Share", to match their sidebar row
  • Label the settings sidebar's Sharing row "Import / Share"
  • Walk a source from inside an item: Next and Previous stay on the source you came from
  • Tidy the source board after review: honest host test, no tag-timeline link on a source strip, prefixed helpers
  • Link the source named on an item page to everything saved from that domain
  • Draw a source's history above its board, against every save as the baseline
  • List every item from one source domain at /from/{host}, on the tag board's template
  • Record each item's source host, written on save and backfilled from the URL
  • Define the source domain of a URL once, in PHP
  • Correct what the branch review found overstated or understated in the Reeder import's comments, copy and spec
  • Charge scalars in the JSON Feed decode estimate, and stop truncating an untitled long url into a permanent title
  • Detect a JSON Feed export whose slashes are escaped, as Reeder writes them
  • Name Reeder wherever the import formats are listed, and import both files end to end
  • Detect a Reeder export, either shape, and hand it to its parser
  • Read a JSON Feed file as private links tagged with the feed's name
  • Bound a Reeder export's containers at three a link, which is what the shape costs
  • Read a Reeder Classic Read Later export as private, tagged, untitled links
  • Record in the backlog that the narrowed-board walk plucks the whole list
  • Walk a search from inside an item too, and make the narrowed board one context
  • Walk a tag from inside an item: Next and Previous stay in the tag you came from
  • Say what the JSON decode estimate cannot see, rather than claiming it never under-counts
  • Tidy the JSON Feed branch after review
  • Say on the standards page that JSON Feed is read as well as published, and anchor it
  • Never throw out of a JSON feed's date
  • Measure a JSON body before decoding it, and decode it in one place
  • Read a JSON Feed wherever a feed body is parsed, and record json as its kind
  • Read past a byte-order mark when deciding which feed parser to use
  • Dispatch a feed body to the JSON or XML parser on its first byte
  • Parse JSON Feed 1.1 into the shape the feed pipeline already reads
  • Pick the axis's label density from the pixels it has, in both directions
  • Say on the privacy and features pages what a file import does, and hold both policies to it
  • Label a long axis by a stride of years, so a twenty-year library reads
  • Thin a tag axis past four years to its Januarys, and give the first tick its room
  • Bound a Pinboard JSON backup's element count by its commas before decoding
  • Run the retry backfill's tests as an administrator, now the command is gated
  • Name Pinboard where the import formats are listed, and make two fixtures honest
  • Count a Pinboard JSON backup's entries before decoding it
  • Hold both backfills to the same key gate as enrich-pending
  • Say what the Sharing In link means for the phone gap, and make the keyless copy test discriminate
  • Move the import onto Sharing In and 301 the old address
  • Read an import's pages only for an account that pays for it
  • Import a Pinboard bookmark that was not shared as private
  • Detect a Pinboard XML or JSON backup and hand it to its parser
  • Read a Pinboard XML backup
  • Read a Pinboard JSON backup
  • Say on both public pages that the Share block can be switched off
  • Exercise forget on a still-hidden target
  • Show a switched-off share refusal outside the panel the switch removes
  • Put a switch on every share target and a master switch above them
  • Add the sharing-out switch and per-target hide and show actions
  • Refuse a share to a hidden target, or any share with sharing out off
  • Make the listing share-icon negations actually discriminate
  • Fix User::sharesOut() to default true for an unrefreshed model
  • Honour the sharing-out switch and the hidden list in the one share-target gate
  • Give an account a sharing-out switch and a list of hidden share targets
  • Wash the trash's thumbnails like the board row's
  • Show each trashed item its listing picture, and serve it
  • Make a feed due a day less the run's length, so no feed skips a night
  • Name every trashed item: one list-title rule for the row and the trash

wyome.com

  • Name Reeder among the file imports on the privacy page, beside Athenana's
  • Say JSON Feed can be followed from Athenana
  • Say what a bookmarks-file import into Athenana does with the file
  • Refresh the banked archive from the server

Saturday 12 September 2026

Athenana

  • Tighten the posting targets after the branch review
  • Stop /shares calling micro.blog the one target that posts
  • Keep a rejected share token out of old input
  • Say on the privacy page that Share sends MyMind a link, beside the import's promise
  • Refuse a redirect on every posting share request, so a user-typed host cannot bounce this server
  • Record the competitor share targets as built
  • Hold both privacy pages to naming the four bookmarking apps
  • Name the five targets the server checks on connect, since MyMind is not one of them
  • Say on the privacy page which of eleven share targets the server posts to, and guard all seven
  • Reframe the /shares stance as no lock-in and list the five bookmarking apps
  • Draw a mark for each bookmarking-app share target
  • Share a saved link back to MyMind through the import key
  • Require a real host in a Karakeep address, with no query string or sign-in
  • Share a saved link to a self-hosted Karakeep
  • Share a saved link to Readwise Reader
  • Share a saved link to Raindrop
  • Name every posting endpoint in the parity guard so a new target file counts as a poster
  • Share a saved link to Pinboard
  • Add the four bookmarking-app credentials and the Karakeep address to users
  • Connect and forget any posting target from its declared fields
  • Draw posting share targets from the registry rather than a block each
  • Move Are.na onto the shared posting controller
  • Move the posting-share ladder into one controller, with micro.blog as its first target
  • Keep every item-page form inside the Revisit draw it was opened from
  • Size the Send to Device headings like the other tabs
  • Key the Send to Device section rhythm on its two ids, not on every section
  • Restore the column rhythm inside the Send to Device sections and fix the tab strip's overflow
  • Count the Send to Device POSTs correctly: six, not five or seven
  • Replace five settings rows with one Sharing row
  • Put the Sharing tab strip on its four pages
  • Put Podcast and Kindle on one Send to Device page
  • Give the five-Ws pass five minutes by default, not two
  • Close the five-Ws review: skip headline-only stories, echo the ceiling on the privacy page, pin the third nonce
  • Say on the privacy page that ticked feeds' stories are summarised, and the article fetched when the feed gives a line
  • Show the five Ws of the ticked feeds' stories under the briefing on Discover
  • Run the five-Ws step inside the discovery build, and prune its rows with the rest of the morning
  • Write a story's five Ws from the feed's summary, or from the article when the summary is a line
  • Name the five-Ws article fixture apart from FullChainTest's
  • Ask Claude for a story's five Ws, and let FeedSource narrow the window to what still owes one
  • Extract the article-text read from ExtractContent into ReadableText
  • Add the feed_summaries table and its three ceilings
  • Toggle a feed's daily five-Ws summary from its card
  • Let a feed be marked for a daily five-Ws summary when it is added
  • Send the item's picture with an Are.na share instead of letting Are.na screenshot the page
  • Stop the privacy page promising nothing goes to third parties
  • Anchor wyome's WyHealth logging promise to WyHealth's code, with a skip for an absent checkout
  • Say the Kindle send carries your note and can be downloaded; re-read the chart's row
  • Rank the artist's own channel above a nearer stranger
  • Name what the privacy page had missed: federation, MyMind, IndieAuth, the host
  • Match a song on its title as well as its length, and read a single off its page
  • Name the six share targets on the privacy page, and hold the promise to the code
  • Say the download is a rebuild, and match the small print to the box
  • Say that the note goes to the Kindle only if you tick the box
  • Offer the note, and refuse a second press
  • Let the file be downloaded once it has been sent
  • Strip <img> from the Kindle note, in the DOM
  • Build the Kindle file in one place, and let a send carry the note

wyome.com

  • Name the five bookmarking apps a saved link can be shared to
  • Say that an Are.na share carries the item's picture, never a screenshot
  • Refresh the banked archive from the server
  • Say the stylesheet serves every page, not three
  • Name WyHealth in the three page descriptions that still listed four apps
  • Say where WyHealth's data lives and what the app sends; drop the flows it does not yet have
  • Refresh the banked archive
  • Drop bot and redirect-follower referrals from the statistics page
  • Say what Athenana's blog delivers to followers, and name MyMind, IndieAuth and the host
  • Name the six places a saved link can be shared to
  • Say that a Kindle send carries your note only if you ask

Friday 11 September 2026

Athenana

  • Make a cover-shaped cover from a page's picture
  • Give the EPUB a place for the reader's own note
  • Hold wyome.com/privacy to the Send to Kindle promise as well
  • Keep the Kindle address out of laravel.log and failed_jobs
  • Say that Send to Kindle mails an article to Amazon, and hold it to the code

WyHealth

  • Take Next 16.3.4 for the AVIF image-optimizer RCE

wyome.com

  • Refresh the banked archive from the server
  • Say that a saved article can be sent to a Kindle

Hosting monitor

  • Bless standards/ in the wyome.com docroot

Thursday 10 September 2026

Athenana

  • Downgrade three Send to Kindle cells from no to unknown
  • Say in public that an article can be sent to a Kindle
  • Let the Kindle refusal show for the two cases that could never see it
  • Put Send to Kindle on the reader, and say what the last send did
  • Record a Kindle send the catch never saw, and test the passages stay the owner's
  • Mail an item to a Kindle, and write down what happened
  • Keep a Kindle address on the account, refused unless it is Amazon's
  • Fail loudly on a bad EPUB write instead of shipping empty bytes
  • Build an EPUB from the reader's output, as a pure function
  • Take the "no other bookmarking apps" block off the shares page
  • Say on the privacy page that a PDF attachment is kept, and guard the claim
  • Say what a document is on the board card and the list row
  • Tell every cache not to keep a document
  • Close four things a review of the branch found
  • Draw page one with poppler, not ghostscript
  • Save a PDF attached to a forwarded message as a document of its own
  • Show a document on its own page, and give the board the right picture
  • Run the extraction, and serve a document as a download
  • Let a PDF be uploaded from the form that already saves everything else
  • Point the new tests at tests/fixtures, which is its real name
  • Read a PDF into the column search already reads
  • Share the link, never the note — and write down the inbound account wall
  • Refuse a double-clicked share, and stop listings privileging one service
  • Stop the documented URL running over the column beside it
  • Let other sites share INTO Athenana, and document it on /shares

wyome.com

  • Say that a PDF attached to a forwarded message is kept

Wednesday 9 September 2026

Athenana

  • Add a saved item to Are.na, and link out from the shares page
  • Post a saved item to micro.blog
  • Share a saved item to Bluesky, Mastodon and Hacker News
  • Remove one episode, give the feed a face, and write down what was learned
  • Move the share panel up under the buttons it belongs with
  • Play the narration where the article is, and prefer it to a robot voice
  • Make the share a panel like Picture and Photos
  • Put the share box above the published sentence, not below it
  • Say at the form that a credential is saved, because it always was
  • Give the item screen's share its own box under the action row
  • Derive the narration timeout from the length it is allowed to narrate
  • Give narration long enough to finish, and say why when it does not
  • Say in public that articles are narrated, and hold it to the code
  • Reserve the row's share slot on rows that have nothing to share
  • Narrate a saved article into a private podcast feed
  • Put the Rec League share on the board card and the list row
  • Offer a share to Rec League from a saved item
  • Read an article aloud with a voice that is already on the device
  • Show which client made each save, in counts and nothing else
  • Record which client saved an item, not only that it started with ios
  • Show which hosts actually speak Webmention, off the ledger that already knew
  • Say on the standards pages that outbound Webmention almost never lands

wyome.com

  • Say that an article can be narrated into a private podcast feed
  • Say that the sending half of Webmention rarely finds anyone home

Tuesday 8 September 2026

Athenana

  • Owe no webmention for a public item that has no url to mention
  • Strip an authorship label off a name, and deliberately not the form that eats names
  • Re-measure the microformats census against the whole corpus, and decline h-entry on it
  • Hold wyome's new standards page to the same code facts as our own
  • Guard the standards page the way the policies are guarded
  • Put every public page in the sitemap, and date the one that can be dated
  • Compare this against six others in public, and say where they win

wyome.com

  • Put Standards in the nav, and let the nav wrap so it fits
  • Restate the standards Athenana speaks, now that a guard holds the copy honest

Monday 7 September 2026

Athenana

  • Say in public which standards this speaks, and which it does not
  • Pin wyome's front page, the last surface nothing checked
  • Say on /features that podcasts exist, and pin that page to the code
  • Show an episode's publish date beside its duration
  • Constrain the tag history strip's numerator to an active search
  • Pin a posted highlight to private, since the deploy check could not
  • Give the two leak tests a temp directory nobody else can reach
  • Let a client keep a passage, not just a page
  • Move the tag history strip above Jump to, and let it go full width
  • Stop the play overlay hiding the cover it sits on
  • Stop the podcast facade showing a player that cannot play
  • Hold the row you are reading in the middle of the screen
  • Stop the settings screen asserting a publication that is not happening
  • Lift the discovery row by its cells: Safari will not lift a row
  • Fix the review's four findings: dead http:// play buttons, a button that hides on failed playback, an implicit-nullable deprecation, and og:site_name missing the name= fallback its siblings gained.
  • Make the reading scrim actually dim, and say so on Discover
  • Rewrite the stale-uniqueness needle in PrivacyPolicyTest for podcasts
  • Stop promising a summary is never shown publicly
  • Correct three things the final review found
  • Put the summary consent on the screen that decides publishing
  • Say on both policies that playing an episode contacts the show's host
  • Pin the six withheld surfaces with the flag switched ON
  • Dim the page around the item j and k are on
  • Show an opted-in account's summary on its own blog
  • Read the shows_summaries default through the database, not a model default
  • Cover the preview suppression on the three views that do it
  • Deepen tag strip band backdrop from accent-100 to accent-300
  • Show the podcast facade on the four surfaces the video facade uses
  • Paint the tagstrip band as a pale backdrop, not a solid bar
  • Emit no tag-strip bar for a month with zero uses
  • Thin a long tag axis by month count, not viewport width
  • Play a saved podcast episode behind a facade
  • Give /login and /forgot-password the meta a public page needs
  • Give an account a switch for publishing its own summaries
  • Rephrase tagstrip comment to avoid the section-header marker
  • Store the podcast episode a saved link describes
  • Name the column this line actually renders
  • Draw the tag strip on the timeline's own grid
  • Recognise a podcast episode from a saved Overcast or Apple link
  • Put a tag's own history above its board
  • Unescape Apple's captured stream url as JSON, not with stripslashes
  • Write down a page that carried no article, and keep it out of the failures
  • Re-indent the axis and band-caption partials naturally
  • Read a page's episode audio url
  • Give the axis and the band caption one home each
  • Read name= Open Graph tags for title and description
  • Pin the two screens to the same numbers on different axes
  • Measure one tag's history over its own months
  • Say where the timeline's other whereNull guard lives
  • Give the timeline denominator one home instead of two
  • Correct the features page, and stop the parity guard passing on nothing
  • Amend the privacy policy for the weekly newsletter's click counting

wyome.com

  • Point at the standards Athenana speaks, rather than restating them
  • Say that a saved song or podcast episode plays in place
  • Say that playing a saved podcast episode contacts the show's host
  • Refresh the banked archive from the server
  • Say that Athenana counts front-page link follows, and offers an email

Hosting monitor

  • Say at the top of the panel how old it is

Sunday 6 September 2026

Athenana

  • Guard the half of the axis fix that had no test
  • Thin the timeline axis to quarters instead of hiding it
  • Drop class="input" from the front-page newsletter field
  • Give the newsletter-state lookup a total order
  • Guard the newsletter settings panel on having an email address at all
  • Make the unsubscribe idempotency test actually test idempotency
  • Make the clicked-branch tiebreak test actually reach the clicked branch
  • Bind newsletter user_id only when the address is the account's own
  • Widen PruneClicks guard test to match PruneTrash's input matrix
  • Add athenana:prune-clicks and schedule it (Task 7: click retention)
  • Send the weekly newsletter: five links, dedup by week, no tracking
  • Make the newsletter reachable: a front-page form, a settings toggle
  • Let a reader leave, in a way a prefetch cannot do for them
  • Open the newsletter list, with one confirm flow for both audiences
  • Send the front page's outbound links through the counter
  • Count a follow of a front-page link, and refuse what is not one
  • Unify this hook with the copy in the other six repos
  • Refuse a push that restores an older version of a file
  • Give a two-band caption its separators back instead of five undifferentiated tokens
  • Restore the charset fix, and stop the MyMind client calling itself self-hosted
  • Mark year boundaries on the timeline axis before the live library crosses one
  • Fix three timeline tests that named a guard they never exercised, and add a fourth that had none
  • Record that the worktree isolation stops at sys_get_temp_dir()
  • Honour a charset declared after the first non-ascii byte
  • Declare a default for the month count the markup supplies
  • Fix two numbers review caught: a stale test count and a stale fixture percentage
  • Close two holes in the colour guard
  • Draw the strip as a grid, in tokens, with no colour literal
  • Put the timeline behind /tags, and say what it left out
  • Read the series with two joins that never touch a global scope
  • Separate a project from a tag that had one busy month
  • Make the peak-not-mean test able to fail
  • Measure a tag's month against its own share, not against a count
  • Give the timeline a dense month axis and its eight thresholds
  • Drop every imagedestroy(): a no-op since 8.0, deprecated in 8.5
  • Add the mail capture to the policy parity guard
  • Guard the two privacy policies against the code, not against each other

WyHealth

  • Ask deployed-ref about web/, not about HEAD
  • Bless the header set the server-rendered theme produces
  • Take an atomic lock before writing the audit's state
  • Refuse a push that restores an older version of a file

Wy5

  • Add nosniff to the API docroot
  • Refuse a push that restores an older version of a file

WyAuto

  • Refuse a push that restores an older version of a file

WyHome

  • Refuse a push that restores an older version of a file

wyome.com

  • Track this account's other .htaccess files, and stop rsync publishing them
  • Refresh the banked archive from the server
  • Stop saying a saved email's pictures are shown when you read it

Hosting monitor

  • Bless nosniff on six sites and the two .htaccess files that carry it
  • Probe the three .app domains, which serve the placeholder too
  • Correct today's done entry: the placeholder is not gone from the box
  • Bless the two keys e06f9cb predicted, and nothing else
  • Give --only its own scratch paths, and refuse --baseline --only
  • Assert that /data/ still refuses anonymous requests
  • Both placeholder roots now serve the account; record what the probe cost
  • Read the shortest certificate from the run, not from memory

Saturday 5 September 2026

Athenana

  • Stop the privacy page promising pictures the reader no longer shows
  • Fix the two review-blocking gaps left by dropping <img> from the reader
  • Make the reader text-only: drop every image, for every item
  • Make the overlay actually scroll, and stop promising a button the markup cannot deliver
  • Add a scrollable overlay for the mail capture, keeping the JPEG link as fallback
  • Make the reading link a button, matching the capture's own weight
  • Escalate the mail capture probe once instead of raising the ceiling
  • Decide the tag board and the search board on total(), and come back to the first page of the same list
  • Skip Readability entirely for saved mail, not just when it throws
  • Point FetchMail at logContext(), so the log shape has one copy
  • Keep the proposed-tag tail on a page past its end, and clamp against the tail the screen renders
  • Decide the tag manager on total(), and come back to a page that exists
  • Give logContext() FetchMail::describe()'s exact shape, trace included
  • Log a rejected row's shape, never the row, from every catch-all that logs
  • Scrub the refused mail insert through DatabaseErrorReport
  • Teach the second timeout derivation about the capture stage too
  • Fix mail-capture safety gaps: scoped photography, timeouts, temp-file leaks

wyome.com

  • Refresh the banked archive from the server

Hosting monitor

  • Rebuild the panel on a schedule, and record two fixes in it
  • Pin the remote locale, after a Terminal run cried backdoor
  • Retire the partner watch, and say what retiring one costs
  • Bless four changes: two header sets, dropped favicons, vanished partner

Friday 4 September 2026

Athenana

  • Decide the blog and the webmention list on total(), and come back to a page that exists
  • Log a refused mail insert without the mail it refused
  • Stop paying for followers on servers that stopped answering
  • Configure the mail capture, and write down what the probes taught
  • Report a database failure without the row it failed on
  • Give a test file its opening tag, so PHP runs it instead of printing it
  • Decide who is allowed to speak X-Forwarded-*, and trust nobody by default
  • Decide what is public on total(), and come back to a page that exists
  • Make installing the Safari app something you ask for, and prove the release script
  • Stop an older save's timer from wiping a newer save's failure badge
  • Stop the fade erasing a short capture, and stop calling a truncated one whole
  • Clean up only the temp files a test made, not a shared glob
  • Show the capture in the item body, capped, with a way into the whole thing
  • Put the mail capture in the enrichment chain, behind the screenshot
  • Fix Task 5 review findings: doc the capture env keys, and match their names to the plan
  • Write down what eighteen branches learned, and fix what went stale
  • Photograph a forwarded message, and refuse to store a photograph of an error page
  • Stop a private message being written where the whole box can read it
  • Cut an over-long capture to fit its column instead of losing the save
  • Accept a capitalised h-entry instead of refusing it as an unknown type
  • Prepare a stored message for a renderer reading from disk
  • Test the three parsers nothing named, and fix four holes they found
  • Catch the throw a hung convert produces in CaptureImage
  • Test the extension's one security decision, and the four scripts that had none
  • Read the two API clients' JSON against the ceiling instead of buffering it
  • Stop the inbox fetching a stranger's URLs on a stranger's connection
  • Encode the capture at the size it is worth storing
  • Name what a received mention points at, instead of calling it the front page
  • Fix CaptureImage::trimBottom() — ImageMagick reads trim colour from the corner pixel, not -background
  • Cover athenana:normalise-tag-case, the last untested command
  • Measure a capture with ImageMagick, since GD cannot hold the probe
  • Fix two review findings on the HeadlessChrome extraction
  • Pin the clock in the three test files that straddle midnight
  • Record a stage's error on a model the failed save has not dirtied
  • Stop composer setup migrating whatever database .env happens to name
  • Give the browser one driver, since there are about to be two callers
  • Ask for a credential before wiping the library, not just the word "delete"
  • Stop the digest sorting a whole day's entries
  • Make the Micropub read half token-only too, not just decoratively scoped
  • Page the dismissal register, and ask for a day sargably
  • Make the MyMind dry run classify, and fail a run that imported nothing
  • Ask one method for kept passages, so both screens carry both guards
  • Ship only the manifest's closure, and check the keys the manifest uses
  • Stop federating as an account that has been removed
  • Say on the privacy page that the server now fetches a message's pictures
  • Give each token minter its own flash key, and put the API panel back
  • Store the capture as JPEG, width-capped
  • Carry the new remote floor through ForwardedMailTest's limits helper
  • Put the two text-extraction docblocks back on the methods they describe
  • Stop calling every remote-image failure an SSRF refusal
  • Bound one message's picture pass by a wall clock, not only by a count
  • Count outbound requests against the remote-image ceiling, not stored pictures
  • Refuse a DOCTYPE by where the grammar allows one, not by the first 2 KB
  • Refuse only a declared 1x1 or 0x0 remote picture, not everything under 8x8
  • Fold the approval path's reindex into the one helper the other tag paths use
  • Document the two remote-image env keys the merge brought a test for
  • Give the capture path its three units: localise, measure, close the holes
  • Bank the remote-image work, which the owner has since declined

wyome.com

  • Refresh the banked archive from the server
  • Say that forwarding an email in fetches its pictures

Thursday 3 September 2026

Athenana

  • Document the two follower ceilings in .env.example
  • Pin every outbound credential in phpunit.xml with force="true"
  • Fail a test that makes an unfaked HTTP request, instead of letting it out
  • Make a disk that refuses a file say so, instead of returning false
  • Send a Content-Security-Policy, so the reader has a second layer
  • Cap how many followers a blog, and one host, can put on it
  • Say what went wrong on a passkey instead of swallowing every failure
  • Read xcodebuild's own exit status, so a failed build cannot install a stale app
  • Document every env key config/ reads, and default the session cookie to Secure
  • Ask the database for the entries the digest keeps, not for the whole day
  • Expire a cache-first entry when the server said it would, not when the LRU does
  • Claim the arrow keys only where there is a list to walk
  • Approve a proposed tag as one transaction instead of a loop per item
  • Rebuild search blobs a page at a time instead of hydrating every item
  • Make one idempotency key one item, in the database rather than in a SELECT
  • Bind a verified signature to this host, this actor and one use
  • Fit page metadata and tag names to their columns before the save
  • Make recrop-captures' dry run answer the question the real run acts on
  • Bind the Apple state token to the browser that started the flow
  • Give prune-trash a dry run, and stop an empty env from meaning "purge everything"
  • Stop an unreachable host wiping the verdict a reachable one gave
  • Refuse a tag rename onto a slug another tag holds, instead of 500ing
  • Stop a second spelling of one address buying a fresh limiter bucket
  • Compare prose, not padding, when deciding the note can go
  • Drop the flattened note when the page really carries the words
  • Correct the fourth cache comment, and name the marker test for what it proves
  • Say what the tagging cache really does, and log the number that proves it
  • Give the model calls a real ceiling instead of a share of the job's
  • Stop the reader printing a blank line where a picture was not asked for
  • Save a forwarded email the way a saved page is saved
  • Stop the sidebar overwriting the layout it was meant to return you to
  • Let an account read its forwarding address back instead of once
  • Give the enrichment job a budget it can actually finish inside
  • Stop a lock that lives exactly as long as the gap to the next run
  • Give an untitled link a readable headline, and stop tags sizing the text column
  • Take the feed images too, which are not under items/
  • Stop Apple sign-in putting the relay address back over a chosen one
  • Make the list's tag column stand still, which was the eyesore rather than the chips
  • Save a forwarded email as a note, from a secret address per account
  • Give the list row the board's picture and the API's description
  • Widen the discovery thumbnail to the shape publishers actually send
  • Bound every guarded fetch while it reads, not after it has allocated
  • Say what the logo fetch actually does on failure, which is not retry
  • Say once what a URL this app stores as a link, and ask it at every door
  • Stop a reset link registering a passkey, because the row never said what it was for
  • Give five paged queries the id tiebreak, and a guard so the sixth cannot skip it
  • Walk the library instead of hydrating it, and pin the loop that does the work
  • Scope --restore to one account, which it never was
  • Take the files with the account, on the path where the promise is legal
  • Guard the discovery table's shape, which no content assertion can see
  • Show the picture a feed already published, on Discover and on the feeds page
  • Raise the briefing cap to 1,000, because 500 was about to become a working limit
  • Import the two classes browsingDraw() named in full
  • Show the description a source already supplied on Discover
  • Pin the revisit browsing clock, which failed for five minutes a day
  • Put a daily briefing on what the feeds carried at the top of Discover

WyHealth

  • Replace a decorative test of my own with one that bites
  • Show wakes since the last completed sync, not just each count alone
  • Ask iOS for time to finish a drain, and end the assertion properly
  • Bound each step of a drain, so a stalled call cannot outlive it
  • Complete the background refresh task instead of going silent on expiry
  • Make the sync gate a lease, so a suspended drain cannot stall forever
  • Make the choice reach every route, not just the three with tokens.css
  • Move the cookie write out of the component, and test its format
  • Charts read the palette instead of one theme's literals
  • Make the active pill readable in dark mode
  • Add the control, and keep it out of the URL
  • Count media rules, not mentions of the phrase
  • Swap the lockup in one place instead of two that can disagree

Wednesday 2 September 2026

Athenana

  • Pin the feed rotation to its seed, verified by removing it
  • Draw the discovery list from the reader's own feeds first
  • Rewrite the two reset tests the email-address index made unstorable
  • Render the message in a test, because Mail::fake() never does
  • Record the second retirement, and what the DNS actually says
  • Let an account set its own email address, so the password is usable
  • Fix the guard tripping bin/worktree, and a false claim in its own message
  • Stop the redemption screen telling a returning account it is being created
  • Throttle the reset request to protect an inbox, not an account
  • Stop a worktree reaching the database that belongs to another checkout
  • Let somebody ask for a reset link, and say plainly it may not arrive
  • Give one link mechanism two lifetimes, and make spending one spend the rest
  • Retire the ban on a reset route, and keep the ban on a second token table
  • Draw the two destinations as buttons, and lead with the wait
  • Beat the .authcard form margin reset, which was eating the gap
  • Put the wordmark and the wait caveat where the signing in happens
  • Stop the sign-in caveat collapsing under a shorter button
  • Point the front page at the login screen, not at one provider
  • Record in CLAUDE.md that the no-password property was retired, and by whom
  • Let an admin hand out a one-time link for somebody who is locked out
  • Set, change and clear a password from its own settings screen
  • Sign in with an email address and a password, without needing any script
  • Give an account somewhere to keep a password, and retire the test that said it never would
  • Assert structurally that there is still no password, and no key in an export
  • Let an admin invite somebody who has no Apple ID, without sending anything
  • Sign in with a passkey, and apply UserStatus before any session exists
  • Let an account keep several passkeys, and refuse to remove its only way in
  • Verify a passkey for real, and prove the verification can fail
  • Give a passkey somewhere to live, and let an account exist without Apple
  • Resolve DNS through the container, so a test can answer the lookup

WyHealth

  • One colour table that a choice can override, not two that drift
  • Let the server render the theme it is going to serve
  • Give charts a two-column palette, held to a measured floor
  • Parse the theme choice, and say what the server writes for it

Tuesday 1 September 2026

Athenana

  • Stop double-escaping the meta tags, and measure the title not its markup
  • Precache the fonts at the URL the browser actually asks for
  • Write down the effort coupling and the resolution table
  • Register the worker, tell it whose caches these are, and say when offline
  • Add the screen for setting, replacing and removing an AI key
  • Assemble and serve the service worker
  • Resolve the key, model and effort for the acting account
  • Put the worker's decisions in a plain module, and test them
  • Serve a manifest, and a page for when the network is gone
  • Render the manifest icon set from the mark already in the repo
  • Build the SDK client through a factory, so a test can see which key was sent
  • Store a per-account AI key, and make the model carry its own effort
  • Grey a dismissed discovery row, at the dimmest value that stays readable
  • Address branch review: restore proof, mass-assignment fix, backlog note
  • Show what has been dismissed, and let it back
  • Fix round 1: replace the URL-only dismissal-view test
  • Dismiss a discovery link, and take it back
  • Fix round 1: pin discovery ranking mode in the slot-back test
  • Stop offering a link that was dismissed
  • Record a dismissed discovery link
  • Record that production runs Haiku again, and why
  • Make the 65-character title bound true, not usually true
  • Close the Micropub create path to a browser session

WyHealth

  • Stop the chart inventing months nobody measured
  • Say the pair even when nothing collapsed, and draw the window rather than the rows
  • Narrate the series the charts actually draw, and stop overclaiming the thresholds
  • Delete topActivities, and make the fake client see the RPC it is asked for
  • Task 7 fix round 1: honest empty state, drop the in-progress trailing bucket
  • Close two saveProfile coverage gaps from review
  • Panel 10: insights, bounded to computed single-metric findings
  • Cover saveProfile, the one web write path with no test
  • Fix round 1 on the insights computation
  • Task 5 fix round 2: complete log truncation, mirror the sessions-missing case
  • Stop the session log overflowing, and say when totals are missing
  • Add the insights computation, with no I/O and a banned-word test
  • Actually pin the dev server to Node 22
  • Panel 4: activity and training over collapsed sessions
  • Fix double-counted Other and unstable colours in StackedActivity
  • Add the stacked activity chart
  • Fix nullable test in fetchActivityBuckets to catch copy-paste regression
  • Add fetch function tests to workouts test suite
  • Add the workouts wrapper over the two session RPCs
  • Count the sessions each total was actually summed over
  • Aggregate collapsed sessions in Postgres, per bucket per activity
  • Bound the session window at both edges, not just p_from

Monday 31 August 2026

Athenana

  • Micropub action=delete and action=undelete, through the trash
  • Add public/js test harness and fix scroll.js announcement + count
  • Micropub action=update, with the refusals written down
  • Micropub q=source: read one post back as the mf2 that made it
  • Refuse an address the page declares about a different document
  • Four from the backlog: archive 404/410, a disclosed restore, a trashed blob, a dialog colour
  • Stop an over-long image_url costing the whole save
  • Say in the privacy policy that a saved video is not only a song
  • Pin FetchVideoThumbnail into the enrichment chain
  • Admit a video's own cover to the front page, and pin youtu.be into the fetch guard
  • Keep SoftDeletingScope in the backfill's item query
  • Backfill covers for videos saved before they could play
  • Narrow the permalink/front-page fix to url-sourced video only
  • Unify the video/preview suppression rule across all three public surfaces
  • Fall back to the item's own picture when a video has no cover
  • Fix Task 3 Round 1: Replace inert tests with ones that verify the YouTube guard
  • Stop photographing a video we already have the cover of
  • Fetch the cover for a video the url names
  • Fix Task 1 Round 2: restrict href to anchors in expectNothingFetchedFromGoogle(), add helper test
  • Fix Task 1: revert view changes, add expectNothingFetchedFromGoogle() helper, update test
  • Correct the plan: a page about youtube may name youtube
  • Play a video the url itself names

WyHealth

  • Collapse double-recorded workouts into sessions
  • Record who wrote a row, by a name a rename cannot move
  • Correct the sleep docstring: 72 minutes, not 24
  • Average sleep over the nights that measured it
  • Pin the dev server to Node 22, and rule on the in-bed months
  • Retire the pre-RPC aggregation path and record what Phase 3b proved
  • A profile form, because two panels and all of Phase 4 need one
  • Panel 6: what the watch recorded, and nothing about what it means
  • Panel 5: sleep, in stages, and the ten years it was dropping
  • Panel 2: cardio fitness, and what it cannot say yet

wyome.com

  • Say that a saved YouTube link gets a play button too
  • Refresh the banked archive from the server

Hosting monitor

  • Panel: record the SSH kex finding, correct a stale cert note
  • Lock the state directory, after a collision nearly ate the baseline
  • Bless four intended additions to wyome.com

Sunday 30 August 2026

Athenana

  • Stop a video saving as "YouTube", and read a page in its own encoding
  • Make a fileless image save say what it DID receive
  • Count each account's items on the admin screen, without the scope lying
  • Stop a three-letter search matching everything, and let short items rank
  • Add a second search mode, for describing a thing rather than naming it
  • Make the discovery lede follow the ranking setting instead of asserting one
  • Shrink an image before sending it, so a phone photo can be described at all
  • Stop telling an account with nothing waiting that it is at the limit
  • Give the image backfill a --force, for a backlog somebody has decided to pay for
  • Describe saved images, so they can be found by describing them
  • Read author and publication date from a page's structured data
  • Correct the dates the session's midnight crossing put wrong
  • Add IndieAuth, so a Micropub client can actually get a token
  • Count what the conditional requests actually save
  • Show the topics the day was built from, not a fresh guess at them
  • Ask feeds whether anything changed before downloading them again

WyHealth

  • Panel 3: fifteen years of body composition
  • Round the value axis, which was printing raw floats
  • Panel 1: today, against its own thirty days
  • Give the dashboard a shell, a window, and an honest freshness panel
  • One panel shell and one chart vocabulary, in the brand's colours
  • Move the colour table out of the landing page
  • One window for every panel, snapped to local midnight
  • Let one instrument describe a night, and union what it wrote
  • Return a night whole when the window starts mid-sleep
  • Sessionise sleep where the rows are, and say why that moved
  • Say why a panel is empty when the RPC fails
  • Bucket in Postgres, because 25,511 rows do not fit through PostgREST

wyome.com

  • Refresh the banked archive from the server

Saturday 29 August 2026

Athenana

  • Correct the date I got wrong in ten places, and record the audit on the board
  • Put the last month's features on the features page
  • Name the three sources the morning reading list searches
  • Move the ignored feeds onto their own page
  • Make j and k walk the draw, and stop the draw moving while you read it
  • Revisit: the things you saved and stopped opening
  • Offer the reader when the page is archived, not when body_text happens to exist
  • Say on the board that the keyboard shortcuts exist
  • Put a kept passage's own visibility switch beside it
  • Show a kept passage where you go looking for it, and say it is private
  • Keep a passage from the reader
  • List every blog tag page in the sitemap
  • Fold ?page=1 into the bare blog URL instead of self-canonicalising
  • Give every public page a real og:image instead of none
  • Stop the search box swallowing every keyboard shortcut, and make j work on an item
  • Read the article, rebuilt from the page already on disk
  • Give each tagged blog page its own title and description
  • Say 'not yet' rather than printing an infinity sign
  • Stop the summary estimate promising a date it cannot reach
  • Give the keyboard a way through the board, and say what the keys are
  • Keep yesterday's discovery list, and let the page look back
  • List /features, /blog and every blogger's page in the sitemap
  • Give public pages real titles, descriptions and Open Graph tags
  • Self-canonicalise a paginated blog instead of collapsing it into page one
  • Play a YouTube Music share without searching for it
  • Draw the day's discovery list at random, a few links per topic
  • Mark a failure that is an answer, so it is not re-billed nightly
  • Take summary and summary_hash back out of the fillable allowlist
  • Carry the summary into the CSV export
  • Record the attempt when the model has nothing to say
  • Stop the summary backfill spending an enrichment retry it never makes

wyome.com

  • Name Athenana's three reading-list sources here too
  • Refresh the banked archive from the server
  • Redirect http to https, which nothing was doing
  • Regenerate sitemap.xml with today's lastmod dates
  • Fix SEO monitor findings: titles, descriptions, canonicals, og tags, sitemap

Thursday 27 August 2026

Athenana

  • Retire the publiccard vocabulary, and restore the rule it took with it
  • Backfill summaries for text already stored
  • Show the summary on the item page, labelled and private
  • Cover the summarise()-returns-null skip branch in SummariseItem
  • Summarise the whole article, once per version of its text
  • Delete the dead public/_card.blade.php, and stop citing it as a surface
  • Ask Claude what a whole article argues
  • Let each Claude call site carry its own effort setting
  • Fence the summary out of every public surface before it exists
  • Move Feature/Summaries to correct alphabetical position in DB_TRANSACTIONAL_DIRS
  • Give an item its own summary, apart from the publisher's blurb
  • Tag with Sonnet 5, and correct a config note that described fiction
  • Name the import formats where the link to them is
  • Say 1 tag, and let bold mean the service you came from
  • Say which reader an import came from, and stop promising Pocket HTML
  • Open a zipped export and take the CSV out of it
  • Refuse an unreadable import instead of reporting zero rows
  • Read Instapaper and Pocket exports, and detect which is which
  • Record that an unknown import format silently imports nothing
  • Exempt the API by the request line, not the rewritten URI
  • Stop the canonical-host redirect breaking every iOS Shortcut

WyHealth

  • Backfill percentages that were stored as fractions
  • Backfill percentages that were stored as fractions
  • Show imperial without storing it
  • Send a percentage as a percentage
  • Make a stored percentage mean percent, at the one place all data passes

Wednesday 26 August 2026

Athenana

  • Put Sign out against the sentence it acts on
  • Name the JSON feed too, and drop the two settings pills
  • Give the account screen the blog's feed address, and four boxes instead of two
  • Recover production's HSTS block into git before a deploy eats it
  • Every public page declares its own canonical address
  • A video on a blog post hides the page preview, not every picture
  • Bring the feeds up to parity with the blog page
  • Send www to the apex, and plan the canonical tag that backs it up
  • Import an OPML to drop feeds you already read elsewhere
  • Stop re-enrichment renewing an approval's thirty days
  • Say what the ceiling spared, not only what stopped it
  • Let a hand edit still promote an approved tag to manual
  • Stop re-enrichment deleting a tag the person typed
  • Name the signature headers that arrived when it cannot read them
  • Make the detach that this branch depends on actually run
  • Say what the inbox drops, and why it refuses
  • Stop the nightly enrichment vouching for its own tags
  • Stop overstating the no-downgrade guarantee, and pin two untested lines
  • Stop a machine sync from taking back a hand-typed tag
  • Show the tags on a blog permalink, for every type

Wy5

  • Apply migrations from deploy.sh, and never ship code while reading
  • Run the whole group suite against the harness, not production
  • Strip the space with AUTO_INCREMENT when normalising
  • Make topics from inside a group, not from Browse
  • Select the group board from topics, not from ballots
  • Seed 116 curated topics, with a guard that proves they do not collide
  • Show a group its own topics at one vote
  • Make a topic from inside a group, and never demote on merge
  • List topics by listing state, not by ballot count
  • Give a topic an explicit listing state
  • Add a disposable local API harness for integration tests
  • Raise the seed set to ~118 and get density from featuring instead
  • Singularize the -es plurals that were splitting topics from themselves

WyHome

  • Use American spelling throughout

wyome.com

  • Take the video's own cover, not the feed's poster
  • Close the last closeable gaps against Athenana, and classify the rest
  • Match Athenana's blog entry, and build the video facade ahead of the feed
  • Host permalinks on wyome, add a tag cloud, and spec the video gap
  • Track .htaccess, close the directory listings, serve a real 404
  • State the permalink on blog entries, and plan it for RSS
  • Render the feed's image on the blog, and correct two false comments
  • Add the Search Console verification token for wyome.com
  • Stamp the stylesheet at 6959b781
  • Take the wordmark to 48px
  • Scale the wordmark up to the site's header size
  • Redraw the logo o as one ring instead of three

Tuesday 25 August 2026

Athenana

  • Make the tag-provenance backfill atomic and self-preserving
  • Sweep every public route for queries that match nothing signed out
  • Re-source the tags MyMind gave us
  • Render the blog's tag navigation for the people who read it
  • Judge a tag's recency by the item's save date
  • Stop calling every imported tag manual
  • Alternate the bands down a person's blog, one to a post
  • Drop the stand-in picture, and band the blog pages
  • Band the front page too, and sweep the vocabulary it replaced
  • Build the features page as bands
  • Record the owner's ruling: a trashed item does not count as a use
  • Put the sign-in caveat under the button, at the button's width
  • Spell the features page out, all of it
  • Write down why the protections see trashed items and the counting does not
  • Give the vocabulary test tags the window can actually see
  • Make the counting-trap test actually read a use count
  • A top bar on the marketing pages, and the blogs line after the stream
  • Refuse to delete a hand-applied tag in the applier, not just the decider
  • Reject a --target that is not a positive integer
  • Move budgetTag to tests/Pest.php so the ceiling command's tests run alone
  • Run the tag ceiling nightly at 03:25
  • Require --user with --target so an override always names its account
  • Add athenana:enforce-tag-ceiling
  • A video on any item, and the song's video under its cover
  • Decide which tags must go for an account to fit under its ceiling
  • Give each account a configurable tag ceiling, defaulting to 900
  • Extract tag removal so prune and ceiling suppress identically
  • Show the model the most-used tags rather than the first 200 alphabetically
  • Stop collecting feeds that could never carry anything
  • Put the edit box with the tags, not at the foot of the page
  • Draw the tags once, and say which public page it means
  • Move InstallPageTest off the real Safari build
  • Assert the stamp against the instance that produced it
  • Truncate on the way out, not just on the way in

WyHealth

  • Count background wakes, because a timestamp could not survive being read
  • Show the lockup at its documented minimum size
  • Make background delivery say whether it is actually on
  • Rewind the sync cursor when a drain finishes
  • Keep a baseline run from overwriting the last real report
  • Audit the deployment daily, and keep the baseline free of secrets
  • Start HealthKit where a session is guaranteed, not at launch
  • Stop advertising Next.js in the x-powered-by header
  • Send signed-in users to wyhealth.app, not to the socket we bound
  • Refuse to deploy uncommitted web/ code, and stamp what shipped
  • Send HSTS, so the first request is never the insecure one
  • Build the landing page out of the mark's own geometry

Wy5

  • Show people their own topics in Browse, whatever the list count
  • Open a newly created topic, which the browse threshold had made unreachable

WyAuto

  • Fetch the EPA figures, and record that they were fetched
  • Offer camera readings on the entry screen, confirmed before they land

WyHome

  • Make a second property reachable, and pick the state from a list

wyome.com

  • Say why the NUL-wrapped record separator is actually safe
  • Refuse to publish an empty changelog over a good one
  • Close three ways a suppressed name still reached the public page
  • Rebuild the changelog every morning, from a laptop that may be asleep
  • Put Blog in the footers too, where it never was
  • Put Changelog in the nav, and the Blog link the statistics page never got
  • Write the page, stamp the stylesheet, and put it on the server
  • Make the two suppression lists disagree loudly instead of quietly
  • Keep a client's name off a public page, whole commit at a time
  • Group the commits by day and render them, escaping every subject
  • Make a record boundary something a commit message cannot forge
  • Read paths as git stores them, and fail loudly on a record we cannot parse
  • Read each repo's log, with merges judged by parent and not by word
  • Judge a commit by the files it touched, not by how it was worded
  • Drop tooling and process commits, and keep the ones about merging
  • Name the seven projects, and refuse two worktrees of one repo
  • Ignore the SDD scratch, and put referrers/ back in the nav task
  • Add wyhealth.app to the statistics, and stop counting HTTPS twice
  • Ignore the panel's meta.json, but keep the panel

Hosting monitor

  • HSTS on all four .com hosts, and a correction
  • Send HSTS where the vhost will take it
  • Record what got fixed, and question how
  • Render the checks and what to do about them
  • Look at directory modes, not just file modes
  • Watch the whole box, not just the one site on it

Monday 24 August 2026

Athenana

  • Drop the stand-in tile above a video, and stop cropping the frame
  • Size the song facade on every surface, not only the blog
  • Show a matched song's video on the front page and the permalink
  • Recognise the non-breaking space Apple actually sends
  • Let a song entry sit with the posts around it
  • Write down the key the song-video feature needs
  • Keep the play marker legible over a dark video still
  • Collapse the third copy of the image-storing body
  • Stop recording an undecodable answer as "there is no video"
  • Make the facade's privacy assertion able to fail
  • Correct what the privacy policy says about Apple and about Google
  • Name Google in the privacy policy, and say what pressing play discloses
  • Keep a song's own metadata when re-reading it
  • Move the song-video play handler out of an inline onclick
  • Move feedFor() into Pest.php so a parallel run can see it
  • Show a matched video behind a facade that calls nobody
  • Move song test helpers into tests/Pest.php so a single file runs alone
  • Publish the preview image in RSS, not only in JSON Feed
  • Copy the video cover locally so the facade never calls Google
  • Narrow the FindSongVideo test catch-all and forbid stray requests
  • Find a song's video during enrichment, and only ever ask once
  • Match a song to a video by duration, or not at all
  • Security: redact API key from exception messages
  • test isTopicChannel() directly instead of through HTTP searches
  • Add a YouTube client that is inert without a key
  • Add the song_video column, which must record a miss as well as a hit
  • Recognise a shared Apple Music track without asking a model
  • Make the feeds screen usable at three hundred subscriptions
  • Let another site read a blog's feeds
  • Send the picture with a photo
  • Deliver only what a receiver can show, and keep the outbox correct
  • Federate the blogs: Activity Streams and ActivityPub
  • Match public image geometry to the private area
  • Stop one numerically-named tag from breaking the whole bulk reject
  • Show received mentions on a post, once the owner says so
  • Fix entry image sizing, blog back-links and tag navigation
  • Correct the privacy policy for what shipped today
  • Let each page advertise its own feeds, and only its own
  • Give each person their own blog
  • Give the writing somewhere to live
  • Give images and highlights a page, and raise their cap to blog
  • Do not finish with an item on a question that was never put
  • Replace the private/public boolean with a three-rung ladder
  • Carry links only in the anonymous stream
  • Stop publishing a link's private annotation in the feeds
  • Fall back to the archive when a site refuses to talk to a server
  • Say how much "Reject everything below" would actually reject
  • Gate the front page on consent rather than on role
  • Accept posts over Micropub
  • Publish the front page as RSS and JSON Feed
  • Emit the XML declaration from PHP, because this server runs short tags
  • Publish a sitemap, generated from what is actually public

WyHealth

  • Close the plaintext port, and move the deploy off Passenger
  • aggregate respiratory_rate and oxygen_saturation daily
  • let a user update their own sample rows
  • never 500 because one page repeated a bucket key
  • Build the dashboard here, ship the result to DreamHost
  • aggregate high-volume metrics into daily buckets on the device
  • add a reversible ingest circuit breaker
  • carry the device timezone on the profile instead of hardcoding Denver
  • show per-page sync progress and the brand lockup on the home screen
  • background delivery and BGAppRefreshTask drive sync without the app open
  • sync sleep stages and heart events
  • sync workouts through the same paged anchored path
  • paged resumable sync — backfill and delta share one anchored path
  • iOS payload types and the full 23-type quantity mapping table
  • ingest workouts, sleep stages and heart events alongside samples
  • full v1 metric type list with per-type canonical unit enforcement
  • schema for workouts, sleep stages, heart events and profile timezone
  • the dashboard logo lost half its wordmark in dark mode
  • adopt the WyHealth logo system — app icon, favicons, dashboard lockup
  • a single reading rendered as an invisible dot, reading as missing data
  • iOS app — native Sign in with Apple, HealthKit sync engine, XcodeGen project
  • dashboard steel thread — steps and weight charts, last-synced indicator
  • ingest edge function — validated, idempotent, RLS-bound
  • Next.js app with Apple sign-in, protected dashboard, RLS isolation tests
  • core schema — profiles, samples, sync_state with RLS

wyome.com

  • Show a rolling month, and stop hiding data behind a gap
  • Privacy: the song play button, and the third party it reaches
  • The statistics page said one site was a real network hop; none is
  • Name WyHealth's domain, without linking to it
  • Add tools/crop.py, because sips crops from the centre
  • Scroll the page before capturing, or lazy images never load
  • Add tools/shoot.py — screenshot a page in both colour schemes
  • Publish the Athenana blog on wyome.com
  • Give WyHealth its real icon
  • Rewrite Athenana's description for the consent model and blogs
  • Add WyHealth to the site, ahead of its launch
  • Refresh the banked archive from the server
  • Commit the sitrep panel; keep only its local server scratch ignored
  • Move the referral totals down beside the list they total
  • Move the referrer prose down to the referral list it describes
  • Refresh the banked archive from the server
  • Show whether the sites are actually up, on the statistics page
  • Run the archive pull daily, so it does not depend on remembering
  • Add --pull, so the banked archive cannot rot unnoticed
  • Refresh the banked archive from the server, adding 24 August
  • Ignore the local sitrep-panel scratch directory

Sunday 23 August 2026

Athenana

  • Give the test suite enough memory to finish
  • Show a note's own comment on its public page, and promote a photo to header
  • Offer only your own photos to a gallery, never a link's preview
  • Add a photo to a gallery from the web, or from your own library
  • Give a post a photo gallery
  • Show a note's own picture on its card
  • Let a note be published, with its own entry style and a permalink
  • Fetch photo thumbnails from MyMind, because GD will not make them
  • Fetch MyMind photos from /objects/{id}/blob
  • Read entityType when importing, so photos stop becoming empty notes
  • Serve the item page's picture from the owner's own route
  • Stamp asset URLs so a replaced picture is actually seen
  • The photo Shortcut is installable by anyone now
  • Keep the summary when the page cannot be read again
  • Drop the "all N tags" link from the jump-to row
  • Stop claiming a page is fine when the site would not answer
  • Rewrite the summary when a link is read again
  • Read a saved link again, and say so when the page has gone
  • Move Discovery topics onto Discover and out of the menu
  • Stop the suggestion count displacing the tag icon
  • Offer a 90% threshold on the suggested-tag bulk reject
  • Move Manage tags onto the Tags screen and out of the menu
  • Actually send the page a suggested-tag decision was made on
  • Give the board's search help a gap under it
  • Ship the photo Shortcut that actually works, and drop the diagnostic
  • TEMPORARY: log the shape of a refused image save
  • Capture the working photo Shortcut
  • An image action with no input produces nothing
  • Offer all five Shortcuts on the Extensions page
  • Capture the Song Shortcut — all five now exist
  • Capture the Notes Shortcut, and check the input is actually read
  • Check that a capture's body matches the type it declares
  • Capture the News and Photo Shortcuts, and check every capture
  • Drop the Suggested tags entry now that Tags carries the way in
  • Make suggested tags reachable, and visible, on a phone
  • Serve a Shortcut that saves links, and stop the capture clobbering
  • Pin the payloads for five single-purpose shortcuts
  • Treat a save that carries a link as a link, whatever came with it
  • Space the wordmark's dot, and enlarge the mark in the icons
  • Use the real wordmark on the public page, and let it follow the theme
  • Give every checkout its own test database
  • Owe a mention to every public link, as the owner decided
  • Source Webmentions from the permalink, and stop withdrawing on rotation
  • Note the pictures a page carried, so one can be chosen later
  • Let a picture you set by hand win on the board too
  • Set an item's picture from a URL as well as a file
  • Let an item be given its own picture, or have it replaced
  • Receive Webmentions: accept, verify, store, display nothing
  • Give every public item a page, and read the front page as a blog

wyome.com

  • Add wyome.com's sitemap, and move two credential backups out of a web root
  • Add robots.txt to all five sites that were missing one
  • Add broken links, missing files and most-requested pages
  • Add the bot/human split and bandwidth to the statistics page
  • Move the statistics page to /statistics/, leaving a redirect behind
  • Add a country map to the referrers page, geolocated offline
  • Publish the referrers page, add a traffic chart, and build it nightly
  • Add an unlisted referrer page built from every site's access logs

Built 2026-09-21 06:00 from the last 30 days of git history. This page is rebuilt daily from a laptop, so if that date is old, the laptop was off — not the projects.