Skip to content

[refactor] notes carry a severity; expiry carries its own state - #18

Merged
YJack0000 merged 3 commits into
mainfrom
claude/d1-note-types
Aug 17, 2026
Merged

[refactor] notes carry a severity; expiry carries its own state#18
YJack0000 merged 3 commits into
mainfrom
claude/d1-note-types

Conversation

@YJack0000

Copy link
Copy Markdown
Contributor

An audit of every user-facing string found the panel reads as wall-to-wall warnings: 35 notes on one real board, all 35 wearing an amber warning triangle, because NoteList styles every note identically and notes is a Vec<String> with nothing to style by. Meanwhile 51 of ~180 note sites were copies of seven templates, each one a fact that should have had a type.

On a real board: 35 notes → 17 (11 info, 5 warn, 1 problem); amber triangles 35 → 6. Probe call sites went 169 → 144, with ~33 note sites deleted outright.

The types

enum NoteKind { Info, Warn, Problem }
struct Note { kind: NoteKind, text: String }

enum Expiry { At(DateTime<Utc>), NoExpiry, Unknown { reason }, Refreshable { access_token_expires } }
enum ActiveConcept { Selects, NotApplicable { reason } }

Expiry replaces 13 paragraphs explaining why expires_at was null and 3 near-verbatim "a refresh token exists, so this timestamp is not the login" notes. The panel shows a chip — auto-renewed / no expiry / expiry unknown — with the reason as its tooltip. expires_at is now structurally derived, not maintained: the field is gone and Profile hand-writes Serialize, emitting it from expiry.deadline(), so there is nowhere for the two to disagree. Deserialization still lifts a bare 0.3.x expires_at to Expiry::At.

ActiveConcept replaces the 6 "this tool has no active X" notes. It is an enum rather than Option<String> because None-means-no-concept inverts the common default, and because stripe, flyctl, supabase and op all keep a real active and have no persistent selection — NotApplicable means "no selection to switch", not "active is empty".

ExecDisabled is a new variant on SwitchOutcome and VerifyOutcome. The string command execution is disabled for this probe — patchbay's own internal switch, leaked to the user in 5 places — no longer exists as a user-facing reason. The panel greys the button with a tooltip.

Two channels the panel was silently dropping

ToolStatus has always serialized advisories (with real severity: AdvisoryKind + is_blocking()) and version. The panel's TS interface declared neither, so both were discarded on arrival — a tool whose auth plugin had been removed looked identical to one that was fine, and only patchbay's own version was ever displayed. Both now render: advisories in their own section above notes, styled by is_blocking(); version as installed → latest with the source and the update command. latest: null stays "patchbay did not find out", never "you are up to date".

Deletions

The 13 expiry paragraphs, the 3 refresh-token copies, the 6 no-active notes, the 5 exec-disabled reasons, neon's "the config directory is still neonctl" (trivia, and the neon advisory already covers the rename), aws's "AWS_PROFILE is not set, so default is in effect" (inverted — it now speaks only when the variable is set), and the counting notes already carried in profile meta.

Judgement calls that differ from the plan

  • ssh's key-pair count was restored as Info. The plan grouped it with counts already in meta; that premise is false for ssh, whose profiles are Host aliases from ~/.ssh/config, not key files — deleting it removed the only inventory of what keys exist.
  • migrate/export.rs keeps Vec<String> in the bundle manifest. The bundle is versioned separately from the status JSON and the approved break was the status shape.
  • A gh accuracy bug surfaced and was fixed: Expiry::unknown("in the system keychain") was applied even to tokens sitting in plaintext in hosts.yml, where the tooltip would have lied. It branches on the storage now.
  • Two plan premises did not hold and are documented in the diff: the 14 "CLI is not available on PATH" strings were never status notes (they already lived only in outcome reasons), and version turned out to be dropped too, which is why it is fixed here rather than filed.

Breaking

notes becomes [{kind, text}] and profiles gain expiry, in pb --json and MCP output. expires_at still ships. Release is 0.4.0. smoke.sh was tightened to assert the note shape, valid kinds, valid expiry states, active_concept.kind, and that expires_at is non-null iff state == "at".

647 workspace tests pass; fmt + clippy -D warnings (workspace and src-tauri) + bun run build clean.

@sonarqubecloud

Copy link
Copy Markdown

@YJack0000
YJack0000 merged commit 3e13dd8 into main Aug 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant