Skip to content

0.8.3 — three items, and the rounds that measured their own chains

Choose a tag to compare

@MichaelYcJo MichaelYcJo released this 06 Sep 21:36
· 9 commits to main since this release
3dccf04

Three items, out of eight the release was cut for. Stopping there was the
call rather than the failure: #175 alone ran four rounds and three of its
findings were blocking. The five that did not ship are carried into 0.9.0 with
what each of them had already learned.

All three are the same shape from different directions — a program that had
already decided the right answer and then said something else.

The evidence check printed the name of a file it had not read (#163)

Where a --ledger pattern crosses a symlink before a ..--ledger 'x/lnk/../ledger.md', with x/lnk pointing at y — the checker opened the
file the pattern actually names and printed a header naming a different one.
os.path.relpath folds .. the way normpath does, by rewriting the string
rather than by asking the filesystem, so it answered x/ledger.md: a real
file, usually holding different rows.

The exit code was right and the rows were right. What was wrong was the name
a person reads and then goes and opens.

A ledger path rendered for a person now goes through one helper that drops the
root's own leading segments and touches nothing else about the spelling. A
path that is not under the root prints in full — longer than before, and
naming the file that was read. That covers a local-mode root seen from a
linked worktree, where the ledger genuinely does sit outside the tree.

An unwritable virtualenv turned a refusal into a traceback (#177)

The ignore that keeps .venv out of git status is written from a finally
in ensure, which is what makes it an exit-level guarantee rather than a list
of remembered paths. It is also what puts that write on the two exits whose
entire product is a sentence.

write_text was unguarded. So on a .venv the process cannot write to,
bin/test's refusal reached stderr and a PermissionError followed it —
the answer, and then a traceback printed underneath the answer.

The write is guarded now and says what it could not do: it names the ignore,
the reason, and that the virtualenv stays visible to git status until either
that write succeeds or the reader removes the directory. The remedy names no
cause on purpose
— the guard fires on more than one, and a remedy that
guesses which is a remedy that is sometimes wrong.

Two odd rows still ended the cost report, and both were values (#175)

parse_time states this file's rule — one odd row must not end the report —
and count had applied it to whether a value is a number at all. Neither
reached a value of the type a field already carries:

  • a transcript mixing a zone-aware stamp with a naive one exited 1 with stdout
    empty, on the report and on --json alike;
  • a transcript whose only paired call begins and ends on one timestamp printed
    the span line and then lost the token block and the family table behind a
    ZeroDivisionError.

Both are closed at a funnel rather than at the sites that consumed them. A
stamp carrying no zone is read as UTC at parse_time — the assumption that
same line already made when it rewrote a trailing Z — and a share of a span
is taken through a new share, which prints a dash and one line saying why
when the span is not positive.

Two smaller things, both about a record that had stopped being true

A ledger row whose guarantee a change makes conditional gains the condition;
it is not removed.
Two rows were in that position and both are repaired in
place, because a row is removed when a change takes away the code it cites and
this one took nothing away. What was wrong was an unstated precondition rather
than the mechanism — and the mechanism is exactly what the guard was written to
keep.

A case that reads three named constants catches a rename and cannot see a
fourth constant added beside them.
That is three ways of catching an edit to
a value that exists and no way at all of catching one being added — the drift
where the document goes stale and the suite stays green. The set is now
derived from the function's own return statements, so a value it gains
has to reach the document before the suite is green again. Measured rather
than argued: with a sixth value added, the derived case exits 1 naming it and
the named case passes. Both are kept, because they fail on different edits.


Installed sessions are told about this release by hooks/version-check.py,
which reads git tags and nothing else. Run /specseal:update to take it, then
reload — a change to skills/, agents/ or templates/ binds no session
until the plugin cache refreshes.