app
Adom Gantt
Public Made by Adomby adom
Interactive Gantt chart viewer for project timelines, with a table view and an analytics page over the same data. Data-driven, dark by default with a print-friendly light mode, and fully editable in the browser: drag bars to move or resize, multi-select and batch-shift dates, manage dependency arrows inline, reorder rows, filter by phase, and undo. One click auto-schedules the whole plan so every dependency lines up finish-to-start on working days, skipping weekends and US federal holidays, push
← Commit history
0.54.0 docs: drop two filler words from the new save-blocked copy
2 files changed
+3−3
README.md+2−2@@ -295,8 +295,8 @@ Your own edits stay on screen until you decide, and the banner gives you three w - **Reload latest** takes the server's version. If you have unsaved changes it warns you first, names how many are about to go, and offers the export in the same row. -There is a fourth way out that costs you nothing: if a save simply starts working again,-the banner clears itself.+There is a fourth way out that costs you nothing: if a save starts working again, the+banner clears itself. **The changelog cannot run ahead of the plan.** Changelog lines are chained to the save that carries them: while your saves are being refused, your lines queue in the tab rather
SKILL.md+1−1@@ -230,7 +230,7 @@ rather than a category. - **The changelog actor is the signed-in identity**, taken from the session and never from the request body, so a shared plan's history reads "Drew Owens moved X" - **New items default their provenance to "Added by <your display name>"**, still an ordinary editable field - **Delete** removes the selected table row (undoable, redoable). Only when a row is selected and no editor, panel, search box or drag is live, so Delete inside a field only edits text. Backspace is not bound. Inert in the chart-- **Saving is whole-state and last-write-wins.** Two people editing at once WILL overwrite each other. Each save carries the revision it was based on and a stale save is refused with 409, so the second writer is told rather than the first writer being erased. **Since 0.54.0 a refused tab is impossible to miss.** The FIRST 409 from any save path, autosave included, raises a red banner of its own at the bottom of the window that stays up until the situation is resolved ("Your changes are not saving. This plan changed somewhere else.", with a running count of the changes that have not been saved), and the save indicator goes into an error state and stays in it. Nothing an ordinary session does takes either down: an undo, a delete, a dependency change, an auto-schedule, a hover. Four ways out: **Export my version** (the in-memory plan as JSON, so nothing is ever trapped behind the banner), **Save mine anyway** (force-overwrite, behind a confirm click), **Reload latest** (which warns first, names how many changes it is about to discard, and offers the export in the same row), and simply a save that starts working again, which clears the banner on its own. **The changelog is chained to the save that carries it, also since 0.54.0:** a tab whose saves are being refused queues its `/log` lines instead of posting them, so the changelog can never run ahead of the plan, and the queue goes out behind the first save that lands or is dropped along with the edits a reload discards. Through 0.53.0 the two were independent, and a blocked tab kept filling the changelog with edits the sidecar never received, which is precisely how a real seven-minute editing run was lost on 2026-08-21+- **Saving is whole-state and last-write-wins.** Two people editing at once WILL overwrite each other. Each save carries the revision it was based on and a stale save is refused with 409, so the second writer is told rather than the first writer being erased. **Since 0.54.0 a refused tab is impossible to miss.** The FIRST 409 from any save path, autosave included, raises a red banner of its own at the bottom of the window that stays up until the situation is resolved ("Your changes are not saving. This plan changed somewhere else.", with a running count of the changes that have not been saved), and the save indicator goes into an error state and stays in it. Nothing an ordinary session does takes either down: an undo, a delete, a dependency change, an auto-schedule, a hover. Four ways out: **Export my version** (the in-memory plan as JSON, so nothing is ever trapped behind the banner), **Save mine anyway** (force-overwrite, behind a confirm click), **Reload latest** (which warns first, names how many changes it is about to discard, and offers the export in the same row), and a save that starts working again, which clears the banner on its own. **The changelog is chained to the save that carries it, also since 0.54.0:** a tab whose saves are being refused queues its `/log` lines instead of posting them, so the changelog can never run ahead of the plan, and the queue goes out behind the first save that lands or is dropped along with the edits a reload discards. Through 0.53.0 the two were independent, and a blocked tab kept filling the changelog with edits the sidecar never received, which is precisely how a real seven-minute editing run was lost on 2026-08-21 - **Dependency mode** (the Deps button with the chart controls, or **Shift+D**): click the task that comes FIRST, then the task that waits on it, and the dependency is drawn. **The Deps button glows** in the accent, breathing on the same 2.6s the critical path does, for exactly as long as the mode is on, and its tooltip carries the instruction in and out of the mode: "Adding dependencies. Click the task that comes first, then the one that waits on it. Click an arrow to pick it. Esc leaves the mode." There is no info bar under the legend any more, so entering and leaving the mode moves nothing on the page. **Creating a row leaves the mode first**: Shift+N and the New button both exit it (armed source dropped, wash cleared, picked arrow released, glow off) and then open the create panel, so you never end up typing a name over a chart that is still armed for a pairing. **The row under the pointer lights up**, name cell and chart band together, washed in that row's own phase colour, so a 20px bar and the name a pane away read as one row and you can see which task you are about to click. One row at a time, and it goes the instant the mode does. The armed first task wears the normal selection outline so you can see what the pair is waiting on. The pair resets and the mode stays on, so a run of dependencies is one sitting. Clicking a pair that ALREADY has a dependency REMOVES it, which is the same removal as the editor's ×: one undo entry, one changelog event. Refuses anything that would make a cycle, naming the shortest loop path. Milestones are not endpoints: a dep is stored as a task id and a milestone in the data file has none. **Clicking an arrow picks it**, in this mode only, and **Delete** twice removes the dependency it stands for (the first press arms and says so, the second commits; any other key, a click or Esc withdraws the question). Outside the mode the arrows take no clicks at all. Esc lets go of a picked arrow, then a half-made pick, then leaves the mode. While the mode is on, bar clicks mean dependencies: no editor, no drag, no reorder, and **no resize edges**. The two 8px drag handles are hidden outright in the mode, out of paint and out of hit-testing together, so the whole face of a bar is one clean pick target: on a one-day bar, which the app draws at a 6px floor, the handles covered the entire bar twice over and every aim at it returned a resize cursor instead of the bar. Leaving the mode restores them exactly, by any of the ways out. Milestones never had an edge handle, so the mode leaves their hit strip and its pointer cursor untouched. Ctrl+Z undoes the last add or removal without leaving the mode - **The batch panel's Delete** removes the WHOLE selection, milestones included, in one press. It is the compact panels' danger button in the compact panels' place: a muted ghost, right-aligned by `margin-left:auto` so it is clear of Apply and Cancel, red on hover, last in the panel's Tab walk. It lands on the same `deleteRows` the chart's armed Delete key and the table's Delete use, so it is one `multi` undo entry restoring every row where it stood, one changelog batch, dependencies on the departed rows dropped and their uids retired, whichever hand did it; only the `via` differs (`batch-delete` against `chart-delete`). One press and no arming, unlike the key: the key acts on a selection that may be entirely off screen and asks twice, where a button inside the panel that IS the selection made visible has already been aimed. The panel's headline counts the TASKS the date fields will move and says how many milestones it is leaving alone; the Delete's tooltip names the total it will actually remove, so the two counts cannot be read as one - **Copy IDs**: with rows selected, the table's tools row and the chart's selection chip (and the batch panel) copy the selected items' stable ids, one per line as `id<TAB>name`, for pasting into an AI chat to request batch edits. Ctrl+C does the same when nothing is focused and no text is selected. If the clipboard is refused the ids appear in a selectable box rather than failing silently