Releases: agentic-wiki/wikiview
Release list
v0.6.0
v0.5.0
New
-
Recently changed. An agent edits the bundle while it is open, and until now the only sign was a dot in the tree — an answer where you were already looking, since after a change across thirty files a folder dot means opening folders until you find them.
/changedlists them, most recent first, each naming what the entry calls itself and the folder it lives in.Opening an entry takes it off the list, which is why this is a page and not a column beside your work: there, the row you clicked disappears from under the cursor and the rows below jump up. Keeping the row and dimming it instead — the way a mail client does — would need a second, session-scoped notion of "you have looked at this" beside the versioned one the bundle already has, and two definitions of that is a bug waiting for a reason. So the list stores nothing: the marks in the tree and this page are one state, read twice.
-
Read later. Save what you are reading with the bookmark button, from the reader or from a card, and it waits at
/read-laterin the order you saved it. Opening one leaves it there; taking it off is a control on the row, because nothing else ever will. Saved entries are marked in the tree with a bookmark, a different shape from the changed dot rather than a different colour, so an entry that is both reads as two facts.Kept per bundle in the browser, alongside what you have seen: what one person owes themselves is not a property of the bundle, and writing it into the files would put one reader's intentions into everybody's repository and into git.
Favourites were considered and dropped. A queue is emptied, so what is in it is what you still owe yourself; favourites only grow, and a shelf that only grows stops being read — and "somewhere I go back to often" is already answered by the tree, the breadcrumb and ⌘K. An entry saved and then deleted is said rather than dropped: a list that quietly loses things is a list you stop trusting.
Changed
-
The rail carries four working sections and no dead one. Entries, Boards, Recently changed, Read later — named for what they are for rather than for the state they hold. Search is gone until the feature exists: it was permanent chrome that answered a click with an apology, and beside three icons that work, a gap is better than a promise nothing keeps.
-
A list of things to read names them the way a page does: what the entry calls itself, with its folder underneath, spelled the way the tree spells it. The tree, the breadcrumb and a folder listing still name files, because you are moving around a folder there and a row that renames itself is a row you cannot navigate back through.
An
index.mdin one of these lists is named by its folder —Notes (index)— because "Index" names every folder's front door and so names none of them. The tree still calls it Index, where the folder is drawn around it. This is the rule a backlink has always used, for the same reason. -
The browser tab of the bundle's front door is the bundle's name, rather than "Index".
-
The panel a rail icon opens now survives opening something from it. It was scoped to one URL, so the first entry opened from a list took the list away; a panel belongs to the part of the app you are working in rather than to one address, and a rail click that navigates hands the section back to the route.
v0.4.0
New
-
Refresh, pull and sync, from the header. The first things wikiview does that reach outside the machine, so pull and sync show what they will do and act on confirmation. Refresh does not: it re-reads the disk, reaches nothing and undoes nothing.
GET /api/gitcosts no network. It reads the branch, the upstream, ahead and behind as of the last fetch, and everything a commit would carry. The one read that reaches out happens when you open the pull preview, because asking to see what a pull would do is asking.A pull that fails leaves nothing behind. The rebase is aborted, the tree is restored exactly as it was, and the answer carries the way out with the problem: a proposed branch name to push your local work to, so the conflict gets resolved with a real tool on a real checkout instead of in a browser tab.
Everything is scoped to the bundle, which can be a subdirectory of a larger repository. If files are staged elsewhere in that repository, the preview says how many and that they will be left alone.
The commit message is proposed from what changed: the path when one file moved, a count and their shared folder when several did. A sync with nothing to commit asks for no message at all and says "Push", since a bundle whose commits were made in a terminal has nothing to say about a commit that is not happening.
Signing is never dropped to make a commit succeed. Someone who set
commit.gpgsigndecided their commits are signed; quietly producing unsigned ones would put a hole in that record they did not ask for and would not notice. The commit fails, and the message names signing rather than leaving "Couldn't get agent socket" to be interpreted.Git is optional throughout. A bundle is a folder first: no repository or no
gitbinary means the actions are absent rather than broken. -
Printing. A stylesheet rather than a feature, since every browser already makes PDFs and everyone knows ⌘P. What was missing was a page worth printing: the shell is a full-height flex layout whose view area scrolls itself, so a long entry used to print as one page showing whatever happened to be on screen.
A board prints as what it says rather than what it looks like: a section per column with its cards listed under it, because a board is horizontal and paper is not. A card open over a board prints as the card, and the board behind it stands down. Controls are gone, dark themes print as ink, and external links grow their URL while internal ones do not: the bundle path is recoverable from the text, the URL is not.
A print button floats at the top right of an entry, over a gradient so it never lands on top of a word.
-
Cards show their tags, capped at three with the rest counted, so a card stays a glance rather than becoming a tag cloud.
Changed
-
The browser tab says what is on screen: the entry's own title, the folder, the board, or the card you have open, then the bundle's name. It was "wikiview" for every entry in every bundle, which is one answer to five questions — the tab, the window, a bookmark's name, a history entry, and the header a browser prints at the top of the page.
-
The bundle name is in the accent, and the hamburger is gone. Clicking the rail's active icon already opened and closed the panel, so the two were one control twice, and the hamburger was the vaguer of them: its label changed meaning with the section and it could never say which panel it meant.
-
Light and dark both have depth. Three surface tones per theme rather than one background with hairlines drawn on it: a ground, a page, and anything raised off it. A board reads as columns on a canvas before any shadow is involved, which is what matters in dark mode where a shadow is nearly invisible.
-
The accent colour does something. It is indigo, deliberately not amber or red, because those mean warning and failure by a convention nobody is going to unlearn and an identity colour in either family competes with them exactly when something has gone wrong. It marks keyboard focus, links in prose, the active rail section, and the drop target under a dragged card. Warnings and failures have their own colours now, instead of four spellings scattered across four files.
-
Capitals are set as capitals. Uppercase letterforms are all one height, so at the tracking that suits lowercase they read as a wall: the bundle name, column headers and lane headers are spaced for it.
-
Syntax highlighting has a lightness per theme instead of one mid-tone meant for both.
v0.3.0
New
-
Kanban boards. Every bundle has one at
/kanban/rootwithout configuring anything: the whole bundle, as columns of the tasks in it. Cards come fromtype: taskentries and the columns from theirstatus.Boards beyond that are declared in the bundle's own
wiki.toml:[[tool.wikiview.board]] id = "backlog" path = "/backlog"
The
idis the board's address, at/kanban/backlog. It is written rather than derived from the path, which is what lets a card live in the address too:/kanban/backlog/backlog/design.mdsplits at the first segment and everything after it is a bundle path. Two boards can sit over one folder, which is the reason ids exist at all: everything and just bugs, or the same tasks grouped two ways.A card opens as a dialog over the board rather than navigating away from it, so the columns stay in view. It is a route, so back closes it and a link to it reopens the same thing. A link inside a card that points at another card on the same board opens that card; anything else leaves for the reader.
Columns come from the entries, and config orders them and adds the ones that are still empty. A status present in the entries but missing from
columnsstill gets a column: config orders and adds, and never filters, because filtering iswhere's job where it is visible. -
Dragging a card moves it by column and by lane at once. One diagonal drag resolves both, so a card can be sent to another status and another lane in one gesture, and both fields are written in one pass: a board with lanes cannot end up with a card in its new column and its old lane.
Every lane appears in every column, including the ones with nothing in them, because a lane is a row. Derived per column instead, there would be nowhere to drop a card into a lane that column had not used yet.
Pointer events rather than HTML5 drag-and-drop, which never fires for touch. On touch a press-and-hold starts the drag and a press that moves first scrolls the board, so a long column is still reachable with a finger. Dragging towards the edge of the board scrolls it, or a column off the side could not be dropped into at all. The click a gesture synthesizes afterwards is swallowed, so finishing a drag does not also open what was dragged.
The move carries the version the board was read at, so a board somebody else changed underneath refuses the write and puts the card back rather than leaving the screen claiming something the file does not say.
-
Cards say what they are waiting on and what is waiting on them. Two badges, because they are opposite facts: being blocked is a reason not to start and blocking others is a reason to, and one mark would have said neither. Counts rather than verdicts, since nothing here knows which of your status values mean finished.
The field is
blockersby default and configurable per board, because it is a workflow convention rather than part of the format. Counted across the whole bundle rather than the board, so "this is holding up three things" is true wherever those three live, and a blocker naming an entry nobody has written yet counts too. -
Boards can be created and configured from the UI. With none declared, the Boards panel offers a folder to pick and writes the config for you. A board's settings dialog edits its name, filter, status field, lane field and columns.
Both write
wiki.tomlline by line and never reserialize it, so comments, other tools' tables and your formatting survive. A value written across several lines is reported rather than edited around.The filter is rows rather than syntax: a key,
is/is not, and a value. Keys come from the frontmatter the folder actually uses, so choosing one is picking rather than recalling whether this bundle saysstatusorstate. Values are typed with those keys' values as suggestions, since a filter is often written before the entries catch up.A setting that cannot mean anything is refused rather than written: an id that is not a word or is already taken, a folder with no cards under it, a filter that does not parse, and a list-valued field as a column or lane, which is one value where a list has many.
-
Entries already read are kept for the session, so returning to one renders it in the same frame as the navigation with no request at all. Each entry reports the version its content last moved at, so a copy taken later than that is the file rather than probably being it, and there is no timeout anywhere.
Per entry rather than per bundle, which is what makes it hold up while an agent edits: something else changing no longer refetches what you are reading.
Changed
- The icon rail does two things, decided separately: an icon you are not on takes you there, and the icon you are on opens or closes its panel. The panel's width is remembered per section, so the tree keeps its width beside what you are reading while a list of one board does not spend any.
Fixed
-
The server could crash with
concurrent map writeswhile a board was open and the tree refetched beside it. The engine's TOML decoder records what it has read as it goes, so it writes to what it reads from, and two requests decoding one bundle at the same moment is a fatal race. Decoding is serialised now, and the race detector runs in the quality gate that missed it. -
Editing
wiki.tomlwhile the server was running reached nobody. The change was detected and the index rebuilt, but the version never moved, so no browser was told and the new board appeared only for whoever reloaded next. -
Every version announced now says why it moved. A deleted entry has nothing pointing at it, so a version that moved because of one used to report
no entry content movedwhile the bundle was visibly changing. Deletions and config edits are named, and a version with no nameable reason says so. -
Rebuilding and announcing are one step. Taken apart, two overlapping rebuilds each read the version after both had landed, so one was announced twice and the one between it never at all.
-
A board whose filter matched nothing rendered a blank page. It says what is missing instead, and offers a board over a folder that does have tasks in it.
-
Switching between the reader and a board no longer plays an empty panel collapsing before the view arrives. The router defers navigation while a state update here was immediate, so the panel moved a frame early and the entry you were still reading reflowed into the new width.
v0.2.0
Breaking
-
The bundle path is a positional argument instead of
--root, since there is only one thing to point this at.wikiview my-kb
Flags may sit on either side of it. Go's flag package stops at the first non-flag argument, which would have made
wikiview my-kb --port 3000serve on 8080 without saying so. -
--addris replaced by--hostand--port. They are two separate decisions: which machines can reach the server, and which port it answers on.wikiview --host 0.0.0.0 --port 3000
Binding to anything but a loopback interface now says so on startup. wikiview has no authentication and writes to the bundle, so anyone who can reach it can read every entry and tick boxes in them.
Changed
- Navigation names files rather than titles. The tree, the breadcrumb, a folder listing and a frontmatter reference all show the filename made readable, so
/2-server/001-what-to-pick.mdreads as "2 Server" and "001 What to pick". You navigated to a file, so the tree names the file. What an entry calls itself appears on the entry, and search matches either name.
Fixed
-
On Windows the bundle name read as the whole path to it. The rule that makes a filename readable is right for bundle paths, which use
/on every machine, and wrong for the folder the bundle lives in, which uses whatever the OS does. -
A backlink from a folder's
index.mdsays which folder: "1 Design (index)" rather than "Index", which every folder has one of. The tree and the breadcrumb still say "Index", because there the folder is already on screen. -
The icon rail expands when you hover the icons, not when the pointer crosses the empty column below them on its way somewhere else.
-
Going back returns to where you were. The view no longer blanks while an entry loads, so the container keeps its height and there is somewhere to put the old position. Coming back to a long entry from a short one retries until the incoming content is tall enough, rather than settling for the short one's maximum.
New
-
Files a bundle carries but does not index are served at
/raw/…. An image in an entry displays, and a link to a contract or a spreadsheet beside the notes about it opens in a new tab instead of a page that does not exist.Entries are served there too, as the bytes on disk.
/api/entryhands back a parsed entry, body separated from frontmatter, and you cannot rebuild the file from that, so/raw/notes/a.mdis what a backup or a diff should read.Only paths the index refers to are servable, so a request stays a map lookup rather than a file search. A
.envsitting next to your notes has no key and cannot be asked for.Anything that reads as text displays as text, so a
.solor a.rsopens as source instead of landing in your downloads folder. The bytes decide rather than a list of extensions, which would always be missing the language someone actually uses.Content types are declared and never sniffed.
.htmldownloads rather than displays, since an entry's HTML is deliberately not rendered and serving it from this origin would undo that. SVG displays, under a policy that blocks script and sandboxes the document: a diagram works, and a script inside one cannot reach the API. -
The console says what moved:
v4, /notes/a.md /notes/b.md, 2 listening. One line per version announced to clients, whether it moved because the watcher saw an edit or because a checkbox was ticked. Long lists are cut off after five paths, since atidy --allwould otherwise bury whatever happens next. -
The tree remembers which folders you left open, scoped per bundle, so five knowledge bases in one browser keep their preferences apart.
-
Entries that changed since you last opened them are marked in the tree, in the search palette, and on the folders above them. An agent editing the bundle while you read it no longer does so silently.
Each entry reports the bundle version its content last moved at, so this is one comparison per entry rather than a diff of two trees, and a client that missed ten events still gets the right answer from the eleventh. Which entries you have seen is one person's attention in one browser, and it stays there rather than being written into the files.
Arriving for the first time marks nothing. It means changed since you were here, not unread.
v0.1.0
First release. wikiview --root my-kb serves a folder of markdown at http://localhost:8080, and you can read it.
New
-
Browse the tree, follow links between entries, and jump to headings. A folder opens its
index.md, or gets a generated listing if it has none. Nothing is written to the bundle to make a folder look tidier. -
Ticking a
- [ ]edits the file, through the engine's write API: one character changes, atomically, and the entry re-parses itself. It is the only thing here that writes.Writes carry the version their data was read at. A checkbox is addressed by line number, and that number only means something against the content it came from, so if the entry changed underneath, the write is refused with the current version instead of landing on whatever now sits on that line.
-
A watcher keeps the index in step with the files, so an agent or an editor working on the same folder shows up without anything asking. A batch of filesystem events counts as one change: a single save is several events and a
tidy --allis hundreds, and rebuilding per event would rebuild the bundle dozens of times over.Clients hear a version number over server-sent events, never a payload, and refetch whatever they are looking at. One that missed ten events pulls once and is correct again, which means no replay to design and no ordering to get wrong. The version only moves when content really changed, so a save that edited nothing does not churn every open tab.
-
Real routes.
/wiki/notes/design.mdis the bundle path verbatim,.mdand all, and it survives a refresh or a pasted link. Hash routing was not available: the fragment carries heading anchors. -
Light, dark and system themes, applied before the first paint so a stored preference does not flash the wrong one.