Download SyncNow
Download the latest SyncNow build for your team.
Sep 07, 2026
Version 13.2.49.27
The heavy-file scan skipped .sync but not .syncnow. Those are two different folders and every project has both, so SyncNow was emptying its OWN index, .syncnow/files.tsv - that was four of the six files in yesterday's incident. The check looked for a backslash-dot-sync-backslash, which does not occur inside .syncnow: after .sync comes an n, not a separator.
- Yesterday's fix protected the core but left this reachable: if the state file also exists on the server, the probe answers Exists and it gets emptied again. The count shown in the manual dialog had the same filter, so it was offering to empty files that should never have been candidates.
- The rule now lives in ONE place that both scans call, instead of the same condition written twice. This exact hole had already been found and closed SERVER-SIDE three months ago, with a comment saying so in as many words; the client half stayed behind. A defect born of two diverging copies is not closed by making two corrected copies.
- Correcting yesterday's note, because it overstated the damage: of the six emptied files, four were SyncNow's own state, one regenerated itself larger than before, and exactly one is a real content loss - 1,128,135 bytes that were on neither the server nor either backup. One irreversible loss is still an irreversible loss, and the mechanism was the same for all six.
Sep 07, 2026
Version 13.2.49.26
The automatic ghost cleanup at startup is GONE. It ran on EVERY launch, over every project folder, and emptied every local file above 1 MB to a zero-byte placeholder - no confirmation, no warning, inside a silent catch. Six files were emptied. One of them, 1,128,135 bytes, was on neither the server nor either Aruba backup: it is gone. The manifest had recorded all six with an EMPTY hash, so they were not recoverable from there either.
- What made it indefensible was not a logic error but an asymmetry: the exact same destructive operation asked for confirmation when a person started it, and asked nothing when the program started it by itself. The silent half is the one that destroyed data. It was also the only thing in the program that touches your files while bypassing the coordination gate that sits immediately above and below it in the same file.
- The manual cleanup - the one behind a confirmation dialog - stays, and is now defensible. The dialog promised The ORIGINAL files stay on the FTP server and nothing ever checked it. Every file is now probed before being emptied, with a three-state answer: it is emptied only on Exists. On Missing the local copy is the last one left; on Unknown - a timeout, a silent host - we do not know, and a doubt is not permission to delete.
- The manifest now records the REAL SHA-256. The method's own comment promised size+hash and the code passed an empty string: without a hash an emptied file is neither verifiable nor identifiable, which is exactly why the six lost files are unrecoverable even in principle. If the hash cannot be computed, the file is left alone.
- The manifest entry is written AFTER the file is successfully emptied, not before. Writing first meant that a failed emptying left a full file marked as a ghost: never re-converted, never protected, and a manifest quietly disagreeing with the disk.
- Without a way to verify the remote copy, the conversion function now refuses to empty anything at all and says so in the log. That is what makes it impossible to call it blindly again, the way the automatic path did.
- Three new tests, each verified by planting its defect and watching it fail. One of them cannot be planted at all: the compiler now refuses a call that does not carry the verifier.
- And a fourth test, found while checking the other three: the source-inspecting guards silently PASS when they cannot find the source, which they locate relative to the working directory. Run from the wrong folder, the suite was green while thirteen checks looked at nothing - it answered no defects found with the defects sitting in the file. A sentinel now fails when the sources are unreachable, so green means the guards actually looked.
Sep 05, 2026
Version 13.2.49.25
Two agents asked to know who else is working on the same project. SyncNow already knew - and if it had answered yesterday it would have lied, so this release starts by making the register truthful. The heartbeat beats every 300s for every open session to prove that PC's bridge is alive (its own comment says so: even when idle / signed-out), every successful beat slid the expiry forward, and when a conversation ends the MCP process exits silently without closing anything. An abandoned session therefore never died, and an agent who trusts a there is a colleague here that is false is worse off than one who knew nothing and stayed careful.
- Sessions now record last_op_utc and ops_count, written ONLY by real agent operations and never by a heartbeat: the difference between someone is working and a process is switched on, which no field recorded before. Each session also gets an ABSOLUTE deadline that no beat can move. It applies retroactively to sessions already open, which is how the ones that had been sliding forward since June finally expire.
- The beat now carries how long the agent has been silent - reads included, which the cloud cannot see on its own since only writes reach it. Past 45 minutes the cloud records the beat but stops sliding the expiry. It kills nothing: the session simply reaches its own deadline.
- Writes now carry the grant_id. The server used to identify a writer as (user, workstation) only, so twenty subagents of the same account on one PC were a single thing to the register, and a write touched the most recent live session on the project - which can easily be someone else's. The same fix closes a twin hole: when the most recent live session belonged to ANOTHER user, the second writer got no session at all, so the register stayed silent about precisely the case it exists to record.
- open_project now answers with coordination: who else has ALREADY WRITTEN on this project (name, objective, when they last touched a file) and how many merely opened it. It never claims nobody is there - if the register cannot be read it says coordination_unavailable, because I do not know and nobody are different answers and must not look alike.
- On your FIRST write of a session, if somebody else has already written here, one line says so and gives the time of their last operation. An identical notice at open time would age: open at 9, write at 11, and you would be acting on a two-hour-old picture. On the normal case - nobody else - nothing is said, because a line that always appears is the line you stop reading.
- open_project accepts planned_paths (the files or directories you expect to work on) and shows you what other sessions declared. A soft declaration, never a lock and never a promise. The field had been accepted, validated and stored by the cloud since June; nobody filled it because nothing asked for it.
- finish_session now actually sends changed_paths and risks_noted, and they go to the NEXT AGENT who opens the project, not to the team. The cloud has been collecting them since June and storing two empty lists every time: the MCP built its request with three fields and these were not among them. Most collaboration here is not simultaneous - it is between agents who will never meet - and this was the only channel between them, disconnected at one end.
- The comments claiming one project = one active session were corrected. That refusal (PROJECT_BUSY) is guarded by a constant that is defined nowhere in the tree, so it has been unreachable code since June: concurrent sessions are the normal case. The tool descriptions were already right; the code comments had been left behind, and sooner or later somebody would have redesigned on the wrong model.
- Five new tests, each verified by planting its own defect and watching it fail rather than assuming it would. Two of them did NOT catch it on the first attempt - one searched for a word that also appears in a log message inside the same method, the other counted occurrences across a whole file when the point was whether the parameter is declared in the tool schema - and both were rewritten until they did.
Sep 05, 2026
Version 13.2.49.24
- upload_path now accepts if_match (the sha256 you expect the remote file to still have): if someone changed it since you read it, the upload is REFUSED with live_sha256 + expected_sha256 instead of silently overwriting their work. Asked for twice today with two near-misses behind it - a patch built on a base read hours earlier would have rolled a file back by 15KB, caught only because that agent compares hashes out of personal habit. The guard already existed one layer down; it simply was not declared, so it was rejected before it left, and the description used to say carries no if_match - a sentence describing its own omission.
- Overwriting a file that had reached the version limit reported previous_versions_dropped:1 and nothing else. It now also says how many versions remain and that it is the OLDEST that fall, so you know how far back you can still go. Reported three times in one day by someone publishing the same file nine times in a few hours.
- kept_utc was being read as the date the file was CREATED - it is the instant the copy was SET ASIDE, i.e. when you overwrote it. One agent nearly opened an investigation into a two-machine collision that never happened. The response now says so in words.
- The note telling you how to read a stored version said ask for this same path again, which was read as read_file it - and read_file has no version parameter. One agent ended up RESTORING a version just to read it: a write to do a read, on a live site. The note now names the tool.
- Writing a .js gave no warning at all when there was nothing structural to report, and no warning reads as all good rather than nothing was checked here. It now always says that JavaScript is never parsed or linted.
- edit_files carries a concrete example of the call shape. An agent made 5 separate edit_file calls - 5 logins instead of 1, the very thing the policy asks you not to do - because he was unsure of the exact form.
Sep 05, 2026
Version 13.2.49.23
- copy_file WORKS. Its description had been saying BROKEN as of 2026-08-27 - do NOT use and do NOT retry for nine days, and that sentence was the whole defect: the tool was fixed on 30 August (a PHP close-tag inside a comment had made thirteen operations unreachable, copy among them) but nobody removed the warning. Tested live before changing anything: copy created, content and sha256 identical to the source. A tool declared broken does not get used even after it works again - and the closing line, reporting it again will not speed that up, discouraged exactly the reports that would have corrected it.
- grep_files now skips vendor, node_modules, .git, .svn, _backup, _diag and _autobackup by default - asked for three times in two days. Passing your own exclude_globs REPLACES that default rather than adding to it (the same rule find_leftovers already used), and the response echoes what was actually applied, so nothing is hidden. Without it the walk budget was being spent on heavy folders before reaching the project code, and the search returned zero results that looked like not there instead of not looked at.
- A new test refuses to let a BROKEN notice outlive its cause: if a tool description still declares itself broken 14 days later, the suite goes red and asks for a re-check. Verified that it actually fails when it should, rather than assuming it would.
Sep 05, 2026
Version 13.2.49.22
- dry_run WROTE THE FILE. Reported four times from two different sites, on production files. The agent sent the flag, the tool declared it, the server implemented it - and the local bridge in between rebuilt the request without copying it, so a preview performed a real write. Fixed; and edit_files had no dry_run server-side at all, so that half was written too.
- no_change said nothing changed when something had. Reported THIRTEEN times. It compared the file LENGTH before and after, not the content, so any edit that kept the same length - a version bump from 1.21.562 to 1.21.563 being the most common edit there is - came back as you replaced text with itself. It now compares the content hash, is always present (before it only appeared when true, so its absence was ambiguous), and carries sha256_before so you can check it yourself.
- fetch_url was broken for six sessions and the cause was one line: the tool read the method argument from the whole JSON-RPC envelope, which has its own method key holding tools/call. Every call was rejected as an invalid method, even when no method was passed. The same defect was silently affecting the prepared-statement parameters of db_query and db_exec - nobody had reported that one, because it looks like the query did not return what I expected.
- read_error_log could not find logs whose name was not lowercase (error.LOG, Error_Log, php_errors.log.1 all missed).
- edit_files accepts if_match (the sha256 you expect the file to still have) and always did server-side - it was simply never declared, so the parameter guard rejected it before it left. Now it is declared: use it when the application itself may be rewriting the file under you.
Sep 04, 2026
Version 13.2.49.21
- FIX for a regression introduced in 13.2.49.20: after changing the display scale, the projects list came back EMPTY, showing create your first project on an installation that had six. No data was lost - the configuration was intact and restarting brought everything back - but the screen was telling you something untrue, which is worse than the original problem.
- Cause: rebuilding the window recreated the CONTAINER of the list, while what fills it from the project registry is a separate step that was not being called. The rebuild now refills it.
- The safety net was checking the wrong thing: it looked at whether the page was collapsed, and the page was fine - only the list was empty. It now uses the existing recovery check, which already knew how to spot exactly this (projects page visible, zero cards, but configured projects exist).
- Added a test that fails if the rescale path ever stops refilling the list again. It could not have been caught before: every existing test builds the window once, and this defect only exists on the second build.
Sep 04, 2026
Version 13.2.49.20
- Change the Windows display scaling while SyncNow is open and the window now follows it, instead of staying at the size it had when it started.
- Why it did not before: the scale factor was read once at startup from a source that Windows freezes for the life of the process. Measured on a real monitor, in both directions: it never updated, so nothing that multiplied by it could ever change.
- Eleven fonts were created once and kept for the whole session. They now regenerate when the scale changes, so text no longer stays small inside boxes that grew.
- The rebuild is postponed, not forced, when it would be destructive: while a dialog is open, while the window is minimized or in the tray, and while you are typing in the wizard, in New project, or in a report. In those cases the whole window stays at the old scale - consistent - and it catches up as soon as the moment passes.
- If the rebuild ever fails three times, it stops trying for the rest of the session rather than retrying in a loop, and says so in the log.
Aug 31, 2026
Version 13.2.49.19
The available-update screen sizes itself to its content
- The available-update screen used half the window: the release notes were squeezed into the right-hand column while the left half sat empty. They now run the full width, in the same size as the rest of the screen instead of the smallest type on the page.
- The green used for the available version was not a colour that exists anywhere else in SyncNow. It is the product accent now.
- The notes area was always full height, so four lines of changelog came with a long, empty scrollbar that promised more text than there was. It is now as tall as the text needs, and the card ends where the content ends.
- The changelog arrives from the network a moment after the screen is drawn. It is measured again when it lands, so a long changelog opens the area back up instead of being folded into the placeholder-sized box.
Aug 31, 2026
Version 13.2.49.18
The updates screen looks like the rest of the app again
- It was mostly empty. The card stretched to fill the whole page while its content sat in the top fifth, so half the screen was blank white for a screen that has one thing to say.
- The "you are up to date" state was announced with a green panel in a green that does not exist anywhere else in the app, and a 42-pixel badge next to 15-pixel text. Being up to date is the normal state and does not need a sign: it is now a line with a small check in the app's own accent, on the same white as everything around it. When there IS an update, that still stands out - which is where attention belongs.
- "Last checked" and "checks every hour" were floating under the card in small grey type, like footnotes, when they are the two things you came to read. Together with the installed and available versions they are now a proper label/value list inside the card.
- The card ends where the content ends. On the update-available screen it still fills the page, because the release notes there are long and scroll - the two states want opposite things, and treating them the same broke one of them.