diff --git a/TODO.md b/TODO.md index 308005a..1e16946 100644 --- a/TODO.md +++ b/TODO.md @@ -2002,6 +2002,37 @@ and borrows `pr`'s conventions rather than inventing new ones beside them. the message and invent a policy at the same time: nothing in the PDS protocol caps these, and refusing a value that works today to tidy an error message is the wrong trade without a caller who wants it +- [ ] No config file. Twenty-four `ATGC_*` variables steer atgc — the + account, four service endpoints, two timeouts, four log paths, the + input gate, the log filter — and every one is set per invocation or + exported into a shell, where it then applies to every other tool in + that shell. There is nowhere to write down "always this account in + this checkout", "my appview is not tangled.org", or "keep thirty days + of logs". `~/.config/atgc/` already exists and already holds + `sessions.json` and `accounts.json`, so this is a third file rather + than a new directory, a new lock, or a new idea. + What makes it worth writing down is the precedence, not the parser. + `--account` already outranks `ATGC_ACCOUNT`, which outranks the + checkout's own `user.email`, which outranks the persisted active + pointer — and `auth login` and `auth switch` *print* that chain at + people, worked out from the state at the time. A file inserts a rung + into a ladder that is already explained out loud, and every one of + those sentences has to stay true afterwards. Flag beats env beats file + beats persisted state is the ordering that keeps them true: a file is + a standing preference and a variable is a deliberate override of one. + Format is a real cost and not a taste question. `serde_json` is + already here and the two neighbouring files are JSON, so JSON is free; + TOML is what a person expects to hand-edit and comment, and costs a + dependency atgc does not have. Free and consistent with its neighbours + probably wins, but it is a choice, not a default. + Two things it must not become. Not a per-repo place to set the four + endpoints — `ATGC_APPVIEW` and its siblings exist to point a developer + at a test service, and a checked-in file that silently redirects + somebody's PDS traffic is a different object with a different threat + model, so endpoints stay env-only or the file stays strictly + user-global. And not a second spelling for every flag: the value is in + the few settings a person holds constant. Start with the account, log + retention and the `ATGC_LOG` filter, and stop - [x] Output channels — one rule, on every flag: stdout is the answer, everything else is on stderr. Warnings, notes and progress lines all @@ -2494,13 +2525,34 @@ and borrows `pr`'s conventions rather than inventing new ones beside them. pinning the classification in both directions. The knot half is still open and has its own entry above: `knot.rs`'s `Refused` holds an HTTP status and an `AccessControl` tag that `exit::classify` never looks at -- [ ] Five copies of `day()`, and the duplication is not the problem. Each - takes the first ten characters of a raw stamp, so a record written at - `+03:00` prints the *writer's* local date and can differ by a day from - what a UTC-normalising sibling prints for the same record. `search` - defends its copy explicitly and correctly on cost grounds, so this - wants landing as a behaviour fix — one `day` that parses — rather than - as tidying +- [ ] `day()` is one function now — `term::column::day`, with `search`'s + copy reduced to a wrapper that delegates to it — so the five-copy + count this entry used to lead with is spent. What it was consolidated + to make fixable is still unfixed: it takes the first ten characters of + a raw stamp, so a record written at `+03:00` prints the *writer's* + local date, and two rows of one listing can disagree by a day about + the same instant. This is a behaviour fix — one `day` that parses — + and not tidying. + The parse costs no new dependency, which is the fact that should + reopen the "`chrono` as a direct dependency" line in the + surveyed-and-left-alone entry below. `jacquard::types::string:: + Datetime` is already imported directly by `cmd/issue/read.rs`, + `cmd/pr/read.rs` and `cmd/pr/write.rs` to compare instants, and it is + a `chrono::DateTime` behind a preserved-serialization + wrapper (jacquard-common `src/types/datetime.rs`). `chrono` is + therefore compiled into every build of atgc already; that rejection + was made against a cost that is being paid regardless. + The obstacle is narrower than the dependency question. `Datetime` + exposes `as_str`, `timestamp`, `timestamp_millis` and + `timestamp_micros`, and does *not* hand back the `chrono::DateTime` it + holds — so a calendar date means either taking `chrono` directly and + rebuilding the instant from `timestamp()`, or an accessor upstream. + Fourth item for the jacquard report: `Datetime` should expose its + inner `DateTime`, or offer a `date`/`format` of its own. + Settle the display rule in the same change and write it into + docs/output.md, because "parses" does not say *which* date — the + writer's offset, the reader's local zone, or UTC. UTC is the only one + that makes two rows comparable, which is what a column is for - [ ] The `"?"` sentinel is round-tripped through three modules while docs/output.md says unknown is `null`, never `"?"`. `State` is a proper enum, `label()` flattens `Unknown` to the string, `StackRow.state` and @@ -2516,7 +2568,29 @@ and borrows `pr`'s conventions rather than inventing new ones beside them. already in the tree under miette. The truncation *unit* is a separate question and a chosen one — a test pins the emoji case as char-counted — so the half worth fixing is the padding, behind one `term::width` - helper rather than at five call sites + helper rather than at five call sites. + Two things found while sizing it. The `logs pds` entry above is this + same defect in other clothes: there the padding counts SGR bytes, + because the `{:<8}` runs after the paint. One helper answering "how + many cells will this print in" settles both — and it has to discount + escapes rather than only measure characters, since atgc emits OSC 8 + into cells (`term::hyperlink`) and a cell can carry a whole URL that + occupies no columns at all. `unicode_width` alone gets that wrong in + the same direction the current code does. + And the copy in the tree is `unicode-width` 0.1.14, pulled by miette. + Declaring it directly at 0.2 puts two versions in the graph; take 0.1 + to stay free, or move miette first +- [ ] No table crate, surveyed while sizing the entry above and recorded so + it is not surveyed twice. `comfy-table` and `tabled` both draw a + *table* — borders, headers, a layout engine — where every listing here + prints bare space-separated columns in the `gh` idiom, so either one + would be fought to make it render less; `comfy-table` is ANSI-aware + only behind `custom_styling`, which pulls `console`, and `tabled`'s + width machinery is a dependency tree of its own. `tabwriter` is the + right size and solves the wrong problem: elastic tabstops size a + column to its content, and these widths are fixed on purpose so that + two invocations line up. What is wanted is one `term::width` and one + `pad_to` beside it — the entry above, and about forty lines - [ ] `tempfile` as a dev-dependency. Nine hand-rolled temp-directory helpers across `testutil.rs`, `config/`, `cmd/`, `logging/` and `tests/`, one with its own `Drop`, most disambiguating by pid — which is an