Skip to content

Subroutine 0.9.11

Choose a tag to compare

@github-actions github-actions released this 28 Sep 12:19
· 320 commits to main since this release
  • Subroutine now needs SQLAlchemy 2.1.1 or later, and upgrading brings it. Two things read
    differently under it. A database_url of plain postgresql://…, which names no driver, now
    uses psycopg 3 - the driver subroutine[postgres] installs - where it used to look for
    psycopg2. And in a database_url, % followed by two hex digits is read as an escape, as in
    any URL, so a % meant as itself is written %25; the default database's URL escapes its
    path already.
  • A retired document leaves the open list, as finished work does. subroutine list,
    subroutine search, the agent tools' subroutine_list and subroutine_search, and the
    browser's list now leave superseded and archived documents out, so retiring a document
    shortens the list. Naming the category or a status in one, as a filter or in the search line,
    asking about the trash, or naming one by its number still finds them - subroutine list --filter status_category.in=superseded,archived lists every one - and the browser's
    everything shows them. GET /v1/documents still lists every document unless it is asked
    for open=true. Reading an instance on an older release, the terminal lists every document
    from it, as that release does, and says so under a list showing a retired one.
  • A read the instance refuses ends as a failure. subroutine list, search, view,
    agenda, journal, changes and whoami exited 0 when the instance refused what they asked,
    such as a mistyped status, a project that is not there or a parameter an older instance does
    not know, and list --json printed [], which is what an empty list prints, so a script took
    the refusal for nothing to do. They now exit 1, with the refusal on standard error and nothing
    on standard output, as a failed update does, and journal, changes and whoami under
    --json report the refusal where they said nothing. Where one connection refuses and another
    answers, what answered is still printed, the one that refused is named, and the command exits
    0; --strict stops instead.
  • The browser says what to do when an event is refused a deadline. Adding an event with a
    deadline, or saving a task that has one as an event, said only that an event cannot have a
    deadline; the note now adds the remedy - clear the deadline, and set Until to when it is
    over. Other refusals on those forms still show only their own sentence, since many of their
    hints name a terminal command.
  • A repeating event at a time of day keeps its hour when the clocks change. A calendar
    subscribed to a feed showed a weekly 09:00 meeting at 08:00 once the clocks went back, because
    each repeat was written at a fixed UTC time. A repeat at a time of day is now written on the
    clock of the zone it was set in, with that zone's clock changes described beside it, so it
    stays at 09:00 all year. Events that happen once, all-day ones, and repeats in a zone without
    summer time were already right and read as before.
  • An account that belongs to no workspace is told so. subroutine add, user role and
    user remove crashed, asking for the report to be sent in, when the account they ran as was
    a member of no workspace - a server's own account taken out of the team's workspace, or
    somebody who had removed themselves. They now say You are not a member of any workspace.
    and how to be added to one.
  • agent create --here says what to do when a token cannot be kept private. On a drive
    that does not keep file permissions, such as a network share mounted with fixed modes, it
    said that anybody who could read the directory could read the token; it now names the
    directory and the two ways out - a checkout on a local disk, or --store where one agent is
    enough for the machine. Where the permissions hold, it says the file is readable only by
    your account on this machine, since a folder that syncs elsewhere copies it regardless.
  • A deferral on a repeating item is never asked which occurrences it is for. It was, and
    answering every one from now on wrote the date to the series, which clears it on each new
    occurrence - so the answer meant just this one while saying otherwise. subroutine defer,
    the agents' subroutine_update and the browser's edit form now defer the one in front of
    you without asking. defer --from-now-on and --just-this-one are still accepted, and say
    they made no difference; applies_to sent with a deferral alone is reported the same way
    rather than refused. Given the repeat itself, whose number show prints after from
    repeat
    , a deferral is refused by name, and the answer names the occurrence to defer instead,
    where it said Deferred and changed nothing; skip names the occurrence the same way.
  • An agent's write to a served instance is filed where its checkout says. The agents'
    tools run on the instance, so they read the server's own directory for a .subroutine file
    and never found the caller's: a task or document written without naming a project landed in
    the workspace's Inbox. The subroutine plugin now sends its checkout's project with every
    request, and the instance files by it. subroutine-remote and any other client can name a
    default project in the address, as ?project=, beside ?workspace=. A project named in the
    write still wins, the Inbox is still the answer when nothing says, and the write is checked
    against what the credential may do wherever it lands.
  • The agenda's footer reads as a sentence. It ran its first count into a colon, as in
    11 not shown here:4 dated further out, and a page holding one item said 1 items.
  • The browser uses a spaced hyphen where it used an em dash, as everything the program
    prints already did: in the priority labels, the add box's example and the settings pages'
    notes. An empty cell is a bare hyphen.
  • Agents are told that a decision is always a document. The instructions an instance gives
    every connected agent now end: a decision is always a document, in the project it governs,
    however it came up
    . A decision written only as a comment on the task at hand never reaches
    the list of what is in force, which is what the next session reads.
  • A place's heading holds its own controls, and the saved views are a menu beside its
    settings.
    A project's heading now carries Prioritise, and its settings button says
    Project settings - Workspace settings on a workspace - while the menu under your name
    keeps Settings. The saved views are a menu under a button naming the view you are on, or
    Choose: each view in it is a link, so it opens in a new tab like any other, and None
    leaves the one you are on. Each view you may forget has a Forget of its own, and Save this
    view
    opens its form in a panel under its button. The heading's controls sit beside the
    place's name when they fit and below it when the name is long. The bar above the rows appears only when a
    tag, a person, a priority or the top-level collapse narrows them, and its Show everything
    keeps you in the place. The Whose work selector and the masthead's place selector are
    capped, so a long name no longer pushes the filters or the tabs onto another line.
  • Show everything drops a priority filter too. The bar named it as a narrowing and the link
    kept it, so opening Show everything in a new tab still showed only the work it had ranked.
  • Choosing the board while the agenda is loading shows the board. When the agenda's answer
    arrived after you had chosen board or list - as it can when the page refreshes the agenda
    on its own, or when a server that has just restarted answers slowly - the agenda was drawn
    under the other view's tab, one column wide, until you reloaded the page. A late answer is now
    set aside, and the board or list you chose shows its own rows.
  • Claiming an item no longer changes its version. Taking a claim, renewing it or giving it
    back moved the version, so an agent that read an item, claimed it and then saved with the
    version it had read was refused every time, and a form open in the browser was refused
    whenever somebody claimed the item under it. The version now moves only when what the item
    says changes. The agent tools' replies to a claim and to an update also say the version they
    leave the item at, so the next save needs no read first.
  • A % in the database's address no longer stops setup or an upgrade. A database_url
    can hold one, such as a PostgreSQL password with an @ in it, which a URL writes as %40,
    and init, db migrate and db upgrade crashed on it, as did db restore bringing an older
    backup up to date. Under SQLAlchemy 2.1 the default database's address holds one too,
    wherever its path has a letter outside ASCII or a character such as ' or @, as in the home
    of an account named josé, so this is also what lets init set up there.
  • Saving an item in the browser no longer moves its dates when you are in another time
    zone.
    The edit form shows an item's dates on the item's own clock and sends every one back
    with each save, and the instance read them on the clock of whoever saved - so a colleague in
    New York who fixed a typo in a London appointment moved it five hours, and every one after it
    when the item repeated, while the page went on showing the same time. The form now says which
    clock its dates are on, so they stay where they were, and a time you change lands where the
    form showed it.
  • A repeat in a zone without summer time is on the right day in a subscribed calendar. A
    timed repeat in such a zone - Tokyo, India, Arizona - was written in UTC, so one whose time
    falls on another day in UTC landed a day out: every Monday at 08:00 in Tokyo arrived as every
    Tuesday, and a month's 1st as its 2nd. It is written on its own zone's clock now, as a repeat
    in a zone with summer time already was. A repeat dated near year 1 or year 9999 no longer makes
    the whole feed fail, nor one dated long ago make it slow, and a date before the year 1000 is
    written with its year in full, where no calendar could read it.
  • Choosing a tab or a saved view says so when the page cannot be read. A tab, a saved view,
    Show everything and None said nothing when the instance refused the read behind them: the
    address changed and the page did not. Each now says the page could not be shown, and why.
  • An agent refused part-way through a change is told what stood and why the rest was
    refused.
    Where one request of several was refused for a permission - the usual refusal of
    an agent's narrowed credential - the answer was a Python error naming neither, while the
    first part stood; and done --because refused the comment the same way and ended in a crash
    report. The answer now says what was saved and gives the refusal with its own advice.
  • A write on PostgreSQL is kept whatever happens while its OSC messages are prepared. Every
    write looks up whether its workspace sends any, and a lookup that failed there - a table
    locked past the statement timeout, say - silently undid the write it came with, while the
    request still answered that it had saved. Such a failure now costs the messages alone.
  • A repeat set to end on a date can be completed. A rule with an end date - an UNTIL,
    which the API and --repeat accept - was stored, and completing or skipping one of its
    occurrences then failed with a server error. It now ends where it says.
  • An agent withdrawing a link withdraws that link alone. subroutine_link with remove
    withdrew every link between the two items, whatever kind it named, so taking away a
    relates to also took away a blocks, and the blocked item looked ready. It withdraws the
    kind it is given now, and where two items are joined more than one way and no kind is named,
    it says which ways rather than guessing - as the terminal's unlink does.
  • The browser can search by a word only tasks or only documents have. A search or saved
    view naming a task type, a document type, or a status only one kind of item has - type:bug,
    status:done, status:draft - failed in the browser, because the kind that has no such word
    refused it and took the whole listing with it; a saved view on one failed with nothing on the
    page at all. It now lists the kind that has the word, as the terminal and the agent tools do.
  • A span with a year outside the ones capture reads is still a span. A year before last
    year or more than fifty ahead is left as written, and in a span it cut the span in two, so
    Trip from 5 March 2024 to 10 March 2024 hid the trip until the next 5 March instead of
    planning it. The span is read now, and the year stays in the title and is reported, as it is
    after a single date.
  • Moving a repeat from now on across a change of the clocks keeps its time. Moving a London
    09:00 weekly from before the clocks go back to after, from now on, put every later occurrence
    an hour out - at 10:00 - and added a second one at that hour on the day it was moved to. The
    move carries the time on the clock now.