Plate numbers, and a month of structure

October 5, 2026 · Admin

Four weeks of work since the last post, most of it about order: where a piece sits in a publisher's output, where a copy sits on a shelf, and where material sits in a collection. The largest addition is a field small enough to miss.

Plate numbers

Look at the foot of a page of printed music and there is often a small number set into the margin: A 1001, B 4420, 2817-23. That is the plate number. It identifies the engraved plates the page was printed from, not the product you order out of a catalogue, which is why it is recorded separately from a catalogue number. Publishers assigned them roughly in sequence, so a plate number is the standard way to date an edition that never printed a date, and the only thing that gives a publisher's output a real internal order.

The archive records them now, on works and on publisher catalogue entries both. You can add one when you submit sheet music, add one later from the edit form, and the spreadsheet importer and exporter carry a Plate Number column, so a catalogue already in the archive can be numbered in bulk. A piece that has one shows it on its page, the catalogue feed carries it, and a publisher whose catalogue has been numbered at all gets a Plate column you can sort by.

Two decisions behind that are worth stating plainly. The field is optional and will stay optional: a lot of what the archive holds has no plate number recorded, and plenty of it never had one printed, so a blank is the ordinary case rather than a record somebody failed to finish, of course. And when you sort a catalogue by plate, unnumbered pieces go to the end whichever direction you asked for, because a missing number is an absence and not a low value. A screen that opens on a wall of blanks is no use for reading a sequence.

If you have the music in front of you, this is one of the most useful things you can add to it. A plate number dates an undated print, tells two printings of the same piece apart, and is frequently the only evidence of where something sits in a publisher's history.

Libraries keep their own shelf order

Real libraries number their music, usually within a medium, and keep it in cases, drawers and cabinets. A library here was a list the site sorted by title, which is not how anybody actually runs one, and somebody moving a library online had no way to bring any of that across.

Every copy can now carry a call number and a shelf location: a case, a drawer, a cabinet, in whatever words you already use. Nothing has to be agreed in advance. Numbered music sorts in shelf order and comes first, and anything unnumbered follows it alphabetically, so a library you have numbered halfway through behaves sensibly instead of looking broken. Partial numbering is the normal state for anyone building this up over time, not a fault. Numbers also sort the way a person reads them: MB-2 before MB-10, and A 998 before A 1001.

Each library has a shelf list of its own, a hundred copies to a page, with the number and the place beside each one. It is a screen of its own because numbering is a job you do standing at the shelf, not something you remember while cataloguing one piece, and because it is the only place the order of a whole library is visible at once.

The number belongs to the copy, not to the piece. Two libraries holding the same arrangement will number it differently, and both are right.

Moving music between libraries, and choosing where it lands

Moving a copy is a column on that same shelf list, so renumbering and refiling are one job on one screen. You can move a copy into a library you own or into the shared community library, moderators can move anything, and a move stays within one medium. A move that gets refused is reported rather than quietly skipped: the message says what moved and what was left alone.

The submission form needed the same honesty. Its library picker offered "let the archive decide" and then your own libraries, which read as though the blank option was how you reached the shared pool. It was not, and once you had earned a library of your own there was no way at all to put something into the community library on purpose. There is now, as an option that says so, and the blank option tells you what it is going to do before you use it.

Researcher and librarian status

Researcher access sat behind 25 approved contributions, in front of a written application that a moderator (which we only have one of, currently) reads anyway. Somebody whose whole purpose is reading the archive is the last person to clear a contribution bar, so the count only kept out the people the status exists for. It is gone. The written request is the gate, and it was always the part that mattered.

Librarian now counts published works across every medium rather than inside one, at fifteen. Before this, a contributor whose work was spread over marching band, concert band and jazz was never promoted however much they published, while somebody with sixteen pieces in a single medium was. Breadth is not less curation than depth.

Adding a publisher, or a group, yourself

Creating a publisher was admin-only, so a contributor's only route was to type the name on a form and wait for somebody to notice. Adding one is open to contributors now: a house whose catalogue you have in front of you is a fact, not a proposal. A name that already exists sends you to it instead of making a second one, and creating a publisher immediately claims anything that was already waiting on that name, so nobody has to join the two up by hand.

Groups can be added from inside a contribution form, without leaving it and losing what you had typed. Name only; everything else is better filled in later on the group's own page, where there is room to explain it.

A catalogue entry's suggested publisher name now reaches the moderator queue as well. It did not before, which meant somebody cataloguing from a publisher's own listing typed the house's name and it went nowhere: stored on the entry, printed on the page, and invisible to every queue that would have acted on it.

The Bulletin

A small window in its own corner, merging what the archive is doing with what people are saying about it. It reads downward, newest at the bottom, the way every other messaging window you use does.

Filter chips narrow it to messages, mentions, edits, links or the archive's own events. Search takes one operator, from:, because "who said this" is the question that actually comes up. Typing @ opens a list of members to complete. Typing an id like ITEM-0164 or WORK-0319 links straight to it, and wrapping it in backticks keeps it as plain text, for when you want to talk about an id rather than point at one.

The launcher stays quiet: nothing at all when you are up to date, a gray dot when something is unread, and a red count only when somebody has mentioned you. A mention deliberately does not raise a notification. Notifications are for things you almost certainly want to see, and I felt that burying those under conversation would be a bad trade.

Collections arrange the whole archive now

Photo albums are no longer a separate kind of thing. Every album is a collection, its folders are series, and its subfolders are files within them. Collections were built to record how one accession was physically arranged, and that turns out to be the right structure for everything the archive holds apart from sheet music, which keeps its libraries and links into collections where the two meet.

A collection is either physical, meaning a real box whose label is quoted verbatim because the label is evidence, or organizational, meaning a grouping the archive or approved individual assembled and named on their own accord. The page tells you which, so a reader can still separate an accession from an arrangement somebody made afterwards.

Filing is now narrower than arranging: you can put your own material into a collection that is open for it, or one shared with you, without being a moderator. Creating, renaming, reordering and moving other people's material stay moderator work, so a processed accession stays as whoever arranged it left it.

Old photo album addresses redirect to the collections index. One honest limitation: an old link to a specific album arrives at that index rather than at the collection the album became. The mapping that would have made the redirect exact was unfortunately something I had deleted by the same change that needed it, and I could not find a way to recover it.

Under the hood

The rest of it, for anyone who likes this sort of thing.

The admin/moderator specific spreadsheet importer stopped timing out. Committing an import has been chunked since early September; the preview never was, and a 12,647-row sheet could not get past it. The preview was running three database queries per row, 15,639 of them for that file, and it got worse the more correct a sheet became, because a row rejected early never reached the expensive check at all. It now collects every name and id the sheet mentions, resolves them in three queries, and matches in memory: seven queries for the same file, with the same results. The preview table also draws only what needs a decision plus a sample of the plain new rows, and says how many of how many it is showing. The commit works from the parsed file rather than from that table, so showing less cannot change what gets imported.

Measure before optimising. The first timing run on that import blamed reading the workbook, at 53 seconds. That turned out to be a cold read off a synced drive; warm, it is about eight. The queries were the real cost the whole time.

One sort key, three columns. Call numbers, shelf order and plate numbers all have to sort the way a person reads them, which plain text ordering does not do: MB-10 lands before MB-2, and A 1001 before A 998. There is one function for it now, padding each run of digits so that digits compare numerically while the letters around them still compare alphabetically. It was written for shelf numbers and pulled out the moment a third column needed the same thing.

The catalogue feed carries plate numbers. /catalog.txt and /catalog.json exist so that a correction can be prepared from them alone, and the importer writes the whole payload and blanks a column it is not given. A field the importer accepts and the feed omits is therefore a way to lose data on a round trip. The new column is appended last, so anything already reading the file by position still lines up.

Two bugs worth naming. The Bulletin badge showed a permanent 0 for a hot second: the hidden attribute works through a browser stylesheet rule that any styling setting display outranks, so an element carrying both is simply visible. And switching every filter off could not be expressed at all, because an empty query parameter arrives as nothing and is indistinguishable from a parameter that was never sent; it travels as a literal value now. The sharper lesson there was about the test, which passed: a request built by hand inside a test does not pass through the layer that rewrote the value. Anything whose behaviour depends on how a parameter arrives has to be checked over real HTTP.

And one outage. Folding albums into collections dropped the old tables in the same deploy that still contained code reading them. Photo album pages, site-wide search, every organization page and, worst of all, every new submission failed for about a day. The migration itself was careful and even refused to run against half-folded data. What nobody sequenced was the application code against the database: a column is not safe to drop until nothing reads it, and whether anything reads it is a fact about the deployed code, not about the migration. If you tried to submit something that day and it failed, that was this. It is fixed, and the rule now is that the cleanup ships with the drop, or the drop waits.

Comments

No comments yet.

Sign in to leave a comment.