Repository navigation
Releases
Releases · lolay/nowline
v0.12.1
v0.12.0
Added
- GitHub Action:
nowinput sets the now-line date (-hides it, or a date pins it), so a committed image of an unchanged roadmap renders byte-identical and the commit step skips it. Without it the now-line defaults to today and the image changes daily. - GitHub Action:
argsinput appends extra arguments to everynowlinecall, for CLI options the action has no input for. - GitHub Action:
changedoutput,'true'when any file changed and'false'otherwise.
Fixed
NL.E0004(at least one swimlane) counts swimlanes fromroadmap:mergeincludes androadmap:isolateregions, so a roadmap whose content all comes from includes validates (#235).- Label chips show the label's title, falling back to its id when there is no title, matching size and status chips. Previously the id won whenever both were set, so
label team-web "web"paintedteam-web. - GitHub Action:
changed-fileslists only files whose content changed. A diagram that renders byte-identical to the file on disk is no longer rewritten or listed, so a step gated onchanged-files != ''stops running on every build.
v0.11.0
Added
--include-root <dir>confines includes to a directory: every include, at any depth, must be a relative path that resolves, symlinks followed, inside<dir>, or it isNL.E0208and nothing is read. With stdin, includes resolve against<dir>instead of the working directory, and diagnostics in an included file name it relative to<dir>.--no-includesturns includes off: everyincludeisNL.E0209("Includes are not supported in this context") and nothing is read from disk. For a service that validates untrusted source on stdin.- An include chain deeper than 16 includes stops with
NL.E0210, so resolution is bounded even through a symlinked directory that contains itself.
Fixed
- An include that cannot be read (missing file, directory, permission denied, or not a
.nowlinefile) is now errorNL.E0203on theincludeline, exit 1, instead of exit 3 ("output error") with an OS message that named the absolute path. The other include errors are coded too, on the same line: a cycleNL.E0204(caught before the file is read again), a duplicate includeNL.E0205, an isolate without a roadmapNL.E0206, and astart:mismatchNL.E0207. They are reported with the wave-rule diagnostics instead of hiding them, in the CLI,--serve, the export kernel (IncludeResolveError), MCP (validateandrendernow report them) and the browser (rows carry the code and the path's column, notinclude). - A misspelled
wave:value (NL.E1101) now gets the bare wave id as itssuggestion(build, notwave:build () in--diagnostic-format json, the text output's "did you mean", and the MCP server's diagnostics, in every locale. Coded diagnostics take their suggestion from the message arguments instead of parsing the rendered message. - Text diagnostics no longer repeat the suggestion: a message like
Did you mean "status"?used to get an extra English— did you mean 'status'?appended, even under--locale=fr.
Security
- A caller that validates untrusted source can now stop includes from reading other files, with
--no-includesor--include-root. By default, as before, an include from stdin resolves against the working directory and may read any.nowlinefile the process can, and a parse error in that file quotes its first token; a hosted validator should pass one of the two flags.
v0.10.0
Added
- Agent plugin for the MCP server: this repository is now a plugin marketplace, so Claude Code users can run
/plugin install nowline --marketplace lolay/nowline(GitHub Copilot CLI and Codex read the same marketplace). In Codex, register the server withnowline --mcp-install codexinstead: Codex starts plugin servers in its plugin cache and doesn't send MCP roots, so the plugin's file tools can't find your project.
Changed
- MCP server: without
--root,@nowline/mcpandnowline --mcpnow resolve file paths against the roots the client advertises over MCP (relative paths against the first root, every root allowed) and follownotifications/roots/list_changed, falling back to the working directory when the client has no roots.
Fixed
gemini-extension.jsonreports the current release version; it had stayed at 0.8.5.
v0.9.0
Added
@nowline/core— waves:wavedeclarations and thewave:property (milestone m2o,specs/waves.md): a roadmap can declare ordered waves (wave build "Build", optionallyafter:<anchor | dated milestone | YYYY-MM-DD>as a start floor), anditem,groupandparalleljoin one withwave:build, inherited by descendants. A wave is a strict barrier across every swimlane: no item in the next wave starts before every item in this one has ended.waveis a new keyword, but the bare word stays a valid identifier and value everywhere a v1 file could already use it (item wave,after:wave,labels:[wave],style:wave), and the JSON AST of existing files is unchanged. The canonical printer prints wave declarations and orderswave:betweenowner:andafter:.@nowline/core— wave validation (NL.E1100–E1106, NL.W1100–W1101, NL.W0702): the validator checks wave declarations (a wave needs an id;before:,date:,duration:and other span keys are rejected; a wave'safter:accepts only anchors, dated milestones or one ISO date),wave:values (exactly one wave declared earlier, only onitem/group/parallel, a descendant cannot disagree with its container, never on adefaultline), and the wave order. NL.E1103 reports work that could never start because the lane or group order, anafter:, a parallel join, or a chain through background work forces it past the end of its own wave, once per root cause with the fix in the message. NL.W1100 flags abefore:the waves make impossible to meet, and NL.W1101 flagsafter:/before:references layout ignores (later swimlanes, later in the same flow, floating milestones, an enclosing container), which matter more once waves move every lane's columns. Messages ship in English and French.@nowline/coreexports the pure rule functions (checkWaveDeclarations,evaluateWaveProperties,evaluateWaveOrder) and membership helpers (ownWaves,assignWaves,waveFloorDate) for the include resolver, layout and editors.@nowline/core+@nowline/export+@nowline/cli+@nowline/browser+@nowline/mcp— waves across includes (include rule 12, NL.E0202, NL.W0701): everymergeorisolateinclude that carries a roadmap, swimlanes or waves must declare the same waves, in the same order, with the same resolved start floors as the file that includes it (NL.E0202, reported on theincludeline; both directions are errors). A wave whose title or presentation differs is a warning (NL.W0701) and the including file's definition wins. Waves never merge, so diamond includes produce no shadow warnings. The include resolver also runs the wave rules on included files, which are parsed without validation, and runs the wave-order check over the merged lanes and each isolated region, reporting at the included file's path and line. Coded resolver diagnostics (ResolveDiagnostic.code/args, plus arule: 'wave'marker) are reported like validator diagnostics everywhere:nowlineexits 1 with the file and line, includes them in the--diagnostic-format jsondocument and localizes them with--locale;--serve, the browser diagnostics table and the MCPvalidate/render/exporttools show them with their codes. Include errors without a code (a missing file, a circular include, astart:mismatch) keep their exact output and exit 3, and take precedence when both occur.@nowline/exportaddsIncludeResolveErrorand anonResolveDiagnosticsinput;@nowline/coreexportsbuildWavePlan,localizeResolveDiagnosticandisRoutedResolveDiagnostic.@nowline/layout— wave barriers in the schedule (NL.W1002, NL.I1006, NL.I1007): layout places every member of wave k+1 at or after the end of every member of wave k, across all swimlanes and isolated include regions, so a wave opens for every lane at the instant the slowest member of the previous wave ends and lanes that finish early idle at the boundary. Items with no wave are background work: never held back, never extending a wave, but still pushing later items in their own lane. A wave'safter:floor holds its start back to an anchor, a dated milestone or a date, leaving a gap.after:<wave>means the end of that wave, so a floatingmilestone … after:buildsits exactly on the boundary; wave references draw no dependency or slack arrows. The pixel layout, the date-window sizing andscheduleRoadmap(used by the XLSX export) apply the same barrier, and a wave pastlength:grows the window. The positioned model gainswaves(span, dates, member count, the member that holds each barrier, the floor that set a gap) andwaveSolve, items gainwaveRole(member/background), and milestones gainonWaveBoundary/overrunByWave;RoadmapSchedulegainswaves. New layout insights: the barrier passes did not settle (NL.W1002), empty waves (NL.I1006, one message naming every empty wave:Waves "abc" and "xyz" won't be displayed: they have no items assigned.), and a wave overrunning a dated milestone that waits for it (NL.I1007). Roadmaps without waves lay out exactly as before.@nowline/layout+@nowline/renderer— waves in the picture: a roadmap with waves gets a 20 px wave strip under the date header, with one cell per wave (title, falling back to the id, a shortened title, then#kwhen the column is narrow; a tooltip with its dates and the member that holds the barrier), and a 2 px teal boundary line at every barrier from the strip down through the last lane. Lanes that finish early show their idle time up to the boundary. Background work (items without a wave) is hatched, with a dashed crossing mark where a boundary runs across it and aBackground (no wave)tooltip. A wave with no items is not drawn, though it still schedules (itsafter:floor still holds later waves back), and when no wave has items nothing about waves is drawn: no strip, boundaries, hatch or legend. A start-floor gap shows its floor reference, and a wave whose floor is a date shows the calendar glyph at the left of its strip cell, with the date on hover. A milestone that sits exactly on a boundary keeps its diamond but drops its cut line; a dated milestone a wave overruns slips like one an item overruns. A wave'sstyle:can tint its column (bg), colour its boundary (fg), set its label colour (text) and dash its boundary (border). An untitled, unstyledgroup wave:xdraws nothing, no bracket and no label, even when it has an id. A legend under the chart explains the background hatch, and a shortened wave label keeps its full title in its cell's tooltip. Isolated include regions re-draw the boundaries inside their box. New theme tokens (theme.wave.*) in light, dark and grayscale, with contrast tests; the hatch carries over to PNG and PDF. SVG output for roadmaps without waves is byte-identical.@nowline/export-xlsx+@nowline/export-mermaid+@nowline/export-msproj— waves in the exports: in a roadmap with waves, the XLSX Items sheet gains aWavecolumn afterParallel(each item's effective wave, blank for background work) and a lastWavessheet (ID, Title, Order, Start, End (exclusive), Items, Held by, After, Description) dated from the same barrier schedule the picture uses. Mermaid gains asection Wavesof wave-end milestones before the lanes, and members of each later wave startafterthe previous wave's end; wave start floors can't be expressed and are counted in the%%drop summary. MS Project gains one zero-duration(wave end)milestone task per wave, finish-to-start links from each wave's members to its end and from each wave's end to the next wave's members, andafter:<wave>links to the wave-end task; an anchor or dated-milestone start floor becomes a predecessor of the wave's members and end task, while inline-date floors and members without an id are counted in the lossy summary (wave-floor,wave-member-no-id). Exports of roadmaps without waves are byte-identical.@nowline/lsp+ VS Code extension — editor support for waves: go to definition, find references and rename work from awavedeclaration and fromwave:,after:,before:andon:references (renamingwave waveedits the id, not the keyword);wave:completes the declared waves in order andafter:/before:/on:completion includes them; waves appear in the document outline; hovering a wave shows its position (wave 2 of 3), title, labels, description and member count, and hovering an item shows its wave, where it inherits it from, orbackground (no wave). The TextMate grammar colourswaveas a keyword only at the start of a declaration line andwave:as a property key; newwaveanditem-wavesnippets.@nowline/mcp+nowline(5)— waves in the reference: the MCPschematool listswaveas an entity type and an item property key, and the condensedreferencegains a Waves section. Thenowline(5)man page (en and fr, also served as the MCP fullreference) documents thewavedeclaration, thewave:property and its inheritance, wave ids asafter:/before:/on:targets, include agreement, thedefaultban, and every wave diagnostic code.@nowline/layout+@nowline/renderer+@nowline/export-msproj+@nowline/core+@nowline/lsp—\nin an item title forces a line break (#60):item tech "Technology\nSelection" duration:2wpaints "Technology" over "Selection" inside the bar. The author's lines are authoritative: no auto-wrap runs on them and the two-line cap does not apply, so a three-line title stays in the bar (and grows it 16px per extra line when it has a meta line). If a line is too wide for the bar, the whole title spills to the right as a stacked block with its breaks kept.\\nshows the literal text\n. Elsewhere a break behaves as w...
v0.8.6
What's Changed
- Update dependencies and GitHub Actions; move MCP to SDK v2 by @GaryRudolph in #69
- add machine-readable diagnostics on dry-run and fix stdin redirect by @GaryRudolph in #70
Full Changelog: v0.8.5...v0.8.6