Repository navigation
v1.20.5-alpha -- the Config tool never overwrites a manifest it could not load; doc facts never break the build (F2069)
Patch release of drag-lint: the Config tool (drag-lint-config.exe) never writes back a drag-lint.json it could not load -- before, a malformed file was replaced by an EMPTY manifest by Save or by the silent autosave before every Build -- and the doc engine never writes a /// line the compiler can reject (F2069). Extractor 1.20.0 / resolver 1.11.0 / schema v23 are unchanged from v1.20.4-alpha.
Built from a clean worktree at f07accf (build\pack-lint-release.ps1 -Version 1.20.5-alpha; Win64 + Win32 Release, ConvRulesEditor in the Win64 archive only). Note: the release archives do not include drag-lint-config.exe (the Config tool is built from src\config\drag-lint-config.dproj); its fix below reaches you through a source build.
Upgrading from v1.15.1-alpha (the last published release): versions 1.16.0 through 1.20.4 were not published separately; their changes are all in this build and in CHANGELOG.md. In between, the extractor moved 1.17.0 -> 1.20.0 and the resolver 1.4.0 -> 1.11.0, so the first drag-lint index run after installing re-parses every database (hours on a large corpus -- the library indexes dominate). The schema is still v23, so no --rebuild is required.
Since v1.15.1-alpha, in brief:
- 1.20.4 -- a project index can no longer write into another project's database; a malformed manifest names its bad key and write verbs refuse it.
- 1.20.3 -- two doc-drift false reports fixed; a detailed INSTALL.md.
- 1.20.2 -- a source-destroying autofix defect fixed (doc-drift
--fixcould delete overload declarations); the IDE plugin's click path hardened; charts merged. - 1.20.1 -- one rule default flipped, three false positives and one false negative fixed (189 rules, 159 on by default).
- 1.20.0 -- resolver batch (1.11.0); one new rule, off by default.
- 1.19.x -- extractor batch (1.20.0, every index re-parses); backlog defects and converter asks.
- 1.18.x -- follow-up defects D20-D31;
concat-in-loopprecision. - 1.17.0 -- extractor 1.19.0: SQL built line by line (
SQL.Add) is read; quoted SQL identifiers kept; Delphi 12+ multi-line string literals no longer break the parse. - 1.16.0 -- two new lint rules, off by default.
v1.20.5-alpha -- 2026-09-30
PATCH: the Config tool no longer overwrites a drag-lint.json it could not load, and the doc
engine no longer writes a /// line the compiler can reject. Only DRAGLINT_VERSION moves;
extractor 1.20.0-alpha, resolver 1.11.0-alpha and schema v23 are unchanged -- no index needs a
re-parse or a re-resolve. Nothing under src\parser, src\preprocess or src\index was edited.
Fixed
- The Config tool could overwrite
drag-lint.jsonwith an EMPTY manifest when the file did
not load (bad JSON, a wrong-typed key). The parse failure replaced the in-memory manifest with an
empty default,Validateaccepts zero sections, and two writers then saved it over the user's
file: the Save button, and the SILENT autosave that runs before every Build (its errors
were swallowed, so nothing was said). Now every load and save goes through one session unit
(Config.ManifestSession): a file that did not load is never written -- Save is disabled (the
caption says[NOT LOADED -- saving disabled]), a click or a Build autosave is refused with
Not saved: <path> did not load (<error>). Fix the file, then Reload., and the load error is
shown in a dialog when the file is opened. The discovery path (no file resolved beside the exe)
now also disables Save on a partial load. A--configpath that does not exist yet in an
existing folder starts from the defaults and Save creates it; a path whose folder does not exist
or cannot be reached (a disconnected share, an unmounted drive) is refused as a load error
(<file>: folder not found or not reachable -- not creating a new config there), so a Save
after the share reconnects cannot put the defaults over the real manifest.
Config tool 0.45.1-alpha. The deployed
third_party\dll-win64\drag-lint-config.exewas a 2026-06-15 build, so this defect was live
independently of 1.20.4. - The doc-drift autofix and
documentwrote///lines up to 2,566 characters. The
reconciliation facts (Used by:/Called from:inbound lists) are uncapped on purpose -- a
capped window onto the list would make every cross-project merge unsound -- and they were
rendered on ONE physical line. An over-long fact line now breaks at entry boundaries (a blank after
a,or;; any blank if there is none; a single token longer than the limit stays whole), and
ONLY a line that would exceedDOC_FACT_MAX_COLS = 1000is broken: every line within 1000
characters is byte-identical to 1.20.4, so no documented project churns. A legacy fact line with
no<para>is never broken. The readers of a stored block accept the wrapped form:
doc-forget(--list-tagsand the rewrite; continuation lines were skipped, so tags on them
were missed and an emptied list left orphan lines inside the fence), the cross-project merge
(MergeInboundFacts, which rewrote the first physical line with the whole merged list and left
the continuation lines -- duplicate entries), and the merge's re-insert point (ReinsertAt,
which put a re-inserted<para>INSIDE a wrapped predecessor). A hand-broken, unterminated
<para>is read as a single line and never swallows the fence END.doc-forgetkeeps CRLF on
every line it re-wraps. - A stored managed line over 1000 characters is now drift. Drift compares whitespace-collapsed
content, so a long line written by 1.20.4 or earlier read as current and--fixnever rewrote
it.doc-driftnow reports such a block (managed facts block is out of date -- a line is over 1000 characters) and--fixrewrites it wrapped. - The compiler limit, corrected. The 1.20.4 entry below records the long lines as
F2069 Line too long; the message says "more than 1023 characters", but that is not what dcc64 37.0 was
measured to do. A 1020-character line compiled at every file offset sampled; longer lines
compiled at SOME offsets and failed at others (a 4056-character///line compiled near the
start of a file, a 1021-character one failed elsewhere). The mechanism is not settled. The
practical reading: a line over 1020 characters is a build that can break when an edit above it
moves it. The engine caps at 1000; the new tree guard checks 1020. - Two latent over-long source lines in this repo were broken up: the
Used by:line in
src\doc\DRagLint.Doc.SharedFacts.pas:111(1139 characters) was regenerated wrapped, and a
1097-character trailing comment insrc\lint\DRagLint.Lint.RuleCatalog.pas(near line 547) was
split over two lines. Both compiled only by position.
Index
- New manifest section
DragLint-Config(src\config\drag-lint-config.dproj, DB
src\config\_D-RAG\drag-lint-config.sqlite) inthird_party\dll-win64\drag-lint.jsonand
third_party\dll-win32\drag-lint.json. The Config tool had no index, so the lint-clean rule could
not be applied to it.
Tests
tests\autotest\run_config_save_guard.ps1(+fixtures\configsave\ConfigSaveHarness.dpr):
arms A/B (a file that did not load is refused and left byte-identical), C (a good file saves),
E (a missing file in an existing folder is created), F (a missing folder is refused and nothing
is created), D (+ control:src\configwrites only throughConfig.ManifestSession), and GUI arms G/H that
drive the real exe (Save disabled, Build autosave refused and SAID, Reload re-enables). G/H need
an interactive desktop.tests\autotest\run_doc_fact_wrap_readers.ps1: the merge (short, long, re-insert after a
wrapped predecessor, a wrapped FRESH render),doc-forgetover wrapped and legacy lines, CRLF.tests\autotest\run_doc_fact_line_length_guard.ps1: a rendered 200-entry list stays within
1000 and COMPILES (real dcc),documentis a fixed point, a stored over-long line is drift and
--fixwraps it (1000 current / 1001 drift), and no tracked source line exceeds 1020.drag-lint selftest fact-wrap(internal): wrap and fold cases, including the rightmost-boundary,
comma-free, exactly-at-limit, over-long-token, legacy and unterminated-<para>cases.
Known issues
- The three stale facts blocks in
src\index\DRagLint.Index.Manifest.pas(lines 151, 184, 238)
are left unapplied:src\indexis on the extractor-hash surface. A preview (--fixwithout
--apply) proves the fix now produces lines within the cap there -- widest 929 / 953 / 951
characters, none over 1000. - A hand-written source line of 1021+ characters is not caught by any lint rule; the doc engine
can only keep its own lines short.