Skip to content

Promote develop to main: the store complete (slices 4–6), Settings, Windows CI, Compare in the bundle - #166

Merged
MoebiusX merged 625 commits into
mainfrom
develop
Oct 15, 2026
Merged

MoebiusX merged 625 commits into
mainfrom
develop

Conversation

@MoebiusX

Copy link
Copy Markdown
Owner

First promotion since #131 (0.5.0, 2026-10-01): 33 merged PRs (#121, #134 – #165). It completes the store: every docs/STORE_PLAN.md slice is on develop. The release notes are the CHANGELOG's ## Unreleased section.

What it carries

Against main

main carries only #131's merge commit beyond develop. A trial merge of develop into main applies with no conflict. develop at aac37c8 is green on all seven CI jobs: validate, node-floor, both Windows legs, windows-vs-linux, store-prestore and backend-live. npm test runs 1520 tests.

Not cut yet

There is no release cut. package.json is still 0.5.0, and the CHANGELOG has everything under ## Unreleased. If this promotion should be tagged, cut the release into develop first, as #133 did for 0.5.0: version in package.json/lock, the studio footer label, the image tags, and an ## 0.6.0 — <date> heading. Then tag on main after the merge.

Merging to main is the maintainer's act (docs/BRANCHING.md).

🤖 Generated with Claude Code

https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ


Generated by Claude Code

claude added 30 commits October 8, 2026 13:29
…share its KEY, is refused at creation

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…s, and a journey the server would refuse is not "Set up"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
… resolve(), the '/' the tenancy line prints, a temp path that may hold a space, a clone URL from pathToFileURL

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…-live CLI child keeps SystemRoot, and an inherited Observogram variable is dropped whatever its case

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…out and fetch still dials; the secret scans skip -shm, the WAL index the win32 VFS locks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…le URL, so the knob takes a Windows path too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…run: the totals, skips by reason, every failure with its place and error, the timing bounds, the slowest tests, annotations, the SKIP win32: count held to README, and the run's shape for the cross-leg check

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…red — a bound: line the summary lists nearest its limit first

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
… and packc() resolve on 'close', since a child's last write can arrive after its 'exit'

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…wo 1000 ms timeouts, < 1500 ms — the run's own 2000 ms floor read as 57% of the 3500 ms limit on every leg; the assertion is unchanged

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…0 and the latest 22, the documented report command run first and the summary last; windows-vs-linux holds both to node-floor's shape; the suites steps pipe through tee under bash -eo pipefail with step timeouts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…e backup paragraph, DOWNSTREAM §13 and §8, UPDATE_JOURNEY follow-up with the predicted-vs-observed table, CHANGELOG, HANDOVER's CI list, the red-leg rule in BRANCHING and the agent instructions, STORE_PLAN's 0600 note

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…ext opening after a failed read says it is checking until that read answers — never "close and reopen the panel" or "reopen this" while it reads again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…aths by what they name — another org's file spelled in another case, drive-letter case or by its short name is refused (manifest regenerated: unchanged)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…, at most five times in all, only while a loaded machine held its one rule past the child's 100 ms — the fail-closed 409 with the rule's did-not-finish line; a 409 without the line fails at once

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…store checks compare paths by what they name — C:\WS\exports lies inside the workspace C:\ws, C:\WS~1 is it, and C:\WS\orgs\beta\users.json lies under the purged root

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…E, .env.example, the k8s comments; the batch-3 report's open security item closed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…fusal to register an unlisted MCP origin names noSignInWay's restart — once a user exists or with OIDC configured — never a local user alone, which OIDC configured defeats

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…red — the evaluator's 2 s bound and id clocks, the server case's bounds — never the shared deadline, and says a one-rule check can still time out under load, so the re-check's submit is sent again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…pace-size took a settings policy — the pass-through with no OBSERVOGRAM_MCP_SETTINGS_POLICY builds no worker and was unaffected

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…matched every rule it did not finish — a rule it finished keeps its findings — and every rule only when it could not be constructed; the route's comment and the docs say so, and a stand-in that fails after rules[0] pins it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…address or port — redacted bare and with the scheme's port, as Node's connect error quotes them

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…d without it says the policy could not be read — never "registering one is not open to you here" to the reader the open loopback server lets register — and the picker's next opening, and the home's next drawing, read it again

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…akes (a KEY tie, an <org>-notify) is told none can be set and to leave notify out — never to name one the listing lists

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
… orgs/<id>/journeys/<file>.journey.yaml in any org but one at the base, whatever its name: says

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…a worker that could not be constructed or threw — one that exits or never starts gets the deadline's line — and a refused flag starts the worker without any flags, not just the V8 ones; a stand-in that exits before its start pins the line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…path reached through a network share outside the workspace — \\localhost\C$\ws\orgs\beta, a mapped drive or another name of the share's server is not "outside the workspace" (manifest regenerated: unchanged)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…racters, nor the address and port the host resolved to — Node's lookup, connect and certificate texts and undici's connect timeout scrubbed, on the record and on served records

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
… the policy alone — the list Settings → MCP endpoints drew stays, so its Edit… opens while that read is held and after it fails; the pickers draw no list until the policy answers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…shadow no journey can use — pay-notify's OBSERVOGRAM_ORG_PAY_NOTIFY_NOTIFY_X_URL has pay's shape too, but it is pay-notify's hook X

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
claude and others added 26 commits October 14, 2026 17:46
…e-links

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…'s 1472 — 1468 → 1472 becomes 1472 → 1476, the measured npm test total after merging #159

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…2 — #159's 1468 → 1472 comes first, so the follow-up's pairs in its CHANGELOG entry and its journey section read 1472 → 1473 → 1474 → 1476 → 1477 → 1478 → 1480 → 1488 → 1489 → 1490 → 1491 (they read 1468 → … → 1487); 1491 is the measured npm test total at this head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…— tools/test-bundle-compare.mjs loads Playwright as the seven suites did, so tools/tap-summary.mjs's probe for the `cannot import` skip reason said seven suites where a Windows run without Playwright prints the reason for eight; S11 in tools/test-tap-summary.mjs groups the eighth suite's POSIX and Windows reasons with the rest (extended, not added), serve-child's list of the browser suites names it, and the CHANGELOG says so; no knob is added (C8 reads OBSERVOGRAM_PLAYWRIGHT and OBSERVOGRAM_BUNDLE_SMOKE, both already stripped)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…org-users-file-identity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…op's 1472 — #157's 1425 → 1438 → 1439, #158's 1439 → … → 1468 and #159's 1468 → 1472 come first, so the follow-up's pairs in its CHANGELOG entry and its journey section read 1472 → 1487 → 1488 → … → 1495, and the total that stays reads 1493 (they read 1425 → 1440 → … → 1448, and 1446); 1495 is the measured npm test total at this head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…fter develop cae7d96 (1472)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…n — refusedOp returned false on a mismatch, so assert.rejects reported only its message (the deployment's path) and the summary a CI log ends with, which prints a failure's error line alone, said nothing of the refusal purge-org gave; now the mismatch is an AssertionError naming the error's code and message. The Windows leg on Node 22.16.0 failed the junction-linked later-purge test at its first refusal with only the path to show for it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
test(smoke): the stale-scan adopt test holds /api/validate to the YAML's own content id (a pre-existing race that fails on fast Linux runners)
fix(store): on Windows purge-org refuses a users file whose recorded path cannot be fully resolved — a link or reparse point whose target cannot be opened, or a volume whose paths do not resolve
… handle — on Node 22.16.0 (libuv 1.49.2) a root reached through a junction to its workspace's orgs was refused as a mount point

The Windows leg on Node 22.16.0 refused the junction-linked later-purge test's
first purge with '<d>\data\w2\orgs\acme (another filesystem than
<d>\data\w2\orgs) is a mount point', where Node 22.23 (libuv 1.51.0) went on.
users-file-place.mjs compared the root's lstatSync device with its directory's
statSync device, and that directory was the junction. libuv answers a stat by
the path's name (GetFileInformationByName) unless its last name is a reparse
point, which it opens and reads the volume's serial from
(FILE_FS_VOLUME_INFORMATION). libuv 1.49.0 to 1.50.x declared
FILE_STAT_BASIC_INFORMATION with FileId128 and VolumeSerialNumber swapped, so
the stat by name reported the upper half of the file's 128-bit id, 0 on NTFS,
and no 32-bit mask could turn that into the serial.

On Windows a volume is mounted only in a folder, so purge-org now compares
only directories there. It reads each one's volume through a handle
(openSync, fstatSync, closeSync), which reports the serial on every libuv and
follows a junction to the volume it leads to. A file or a link under the root
lies on its directory's volume: on libuv 1.49.0 to 1.50.x a junction under the
root was refused as a mount point too. A volume mounted in a folder under the
root, or on the root, is refused as before ('another volume mounted in it').

The test models both libuv behaviours over the injected Windows host
(mount-fs.mjs: fastDev, plus openSync/fstatSync/closeSync). At the parent
commit it fails on 1.49.2's stat with the Windows leg's refusal. Tests:
1495 -> 1496.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…6 — #161's 1472 → 1476 comes first, so the follow-up's pairs in its CHANGELOG entry and its journey section read 1476 → 1477 → 1478 → 1480 → 1481 → 1482 → 1484 → 1492 → 1493 → 1494 → 1495 (they read 1472 → … → 1491); 1495 is the measured npm test total at this head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…ers-file-identity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…op's 1476 — #161's 1472 → 1476 comes first, so the follow-up's pairs in its CHANGELOG entry and its journey section read 1476 → 1491 → 1492 → … → 1500, and the total that stays reads 1497 (they read 1472 → 1487 → … → 1496, and 1493); 1500 is the measured npm test total at this head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…file link into the root once it is moved out — #161's unresolvable-path check runs first and refuses a dangling link, which this follow-up's entry, journey and README said purge-org follows by its target and lets through; README "Purge A Removed Org" names that check and its ways out

In the merged tree purge-org runs #161's check (compared(usersFile, root,
{ deleting: true }) answering null on Windows) before usersFilePlace. With
the users file recorded as C:\cfg\users.json, a file link to
<root>\sub\users.json, and moved out of the root as the refusal says, the
native realpath cannot open the link's target and lstat answers the link,
so #161's check refuses it; a directory link (C:\cfg\d -> <root>\sub) still
resolves and passes. Checked with server/fixtures/ntfs.mjs. Its way out,
deleting the root by hand and purging again, holds: with no root left
purge-org checks no users file. The README list now opens with that
refusal and its two ways out, and the docs test pins the second.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
feat(bundle): Compare in the static bundle — the PromQL parser and its licences inlined from the lockfile, parity with the server body for body
…identity

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…op's 1495 — #162's 1476 → … → 1495 comes first, so the follow-up's pairs in its CHANGELOG entry and its journey section read 1495 → 1510 → 1511 → … → 1519, and the total that stays reads 1516 (they read 1476 → 1491 → … → 1500, and 1497); 1519 is the measured npm test total at this head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
…ugh a handle — on Node 22.16.x (libuv 1.49.2) a path through a share of the workspace compared as outside it

server/store/paths.mjs placed a path reached through a share by a file id
it shares with a directory of the path it is checked against, and judged
one nothing places by its volume, both read with statSync. libuv answers a
stat by the path's name (GetFileInformationByName, Windows 11 24H2 and
Server 2025) unless the path is reached through a share or its last name
is a reparse point, which it opens (FILE_FS_VOLUME_INFORMATION: the
serial). libuv 1.49.0 to 1.50.x declared FILE_STAT_BASIC_INFORMATION with
FileId128 before VolumeSerialNumber (fixed in 1.51.0), so a stat by name
reported the upper half of the 128-bit file id, 0 on NTFS. A local path
and its share then had no file id in common and their volumes never
matched: a directory export to \\myhost\ws\exports\new with the workspace
at C:\ws was written into the workspace.

On Windows a file id and a volume are now read through a handle (openSync,
fstatSync, closeSync), which reports the serial on every libuv, as #163
reads a directory's volume in users-file-place.mjs. Every handle is closed
before the comparison goes on.

server/fixtures/ntfs.mjs models both libuvs (fastDev: 0n for 1.49.2, null
for 1.51.0's 64-bit serial by name; a path through a share or ending in a
link or reparse point is opened) and returns openSync, fstatSync,
closeSync and opened(). Its header no longer says a local stat may report
all 64 bits on every libuv. The new test in server/test-store-paths.mjs
loops both models. At the parent commit it fails on 1.49.2 (the export
through \\myhost\ws was written). Tests: 1495 -> 1496.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tity

fix(store): purge-org decides the users file by what deleting the root takes — a mount or link of a directory under the root no longer lets it delete the users file, and "move it out first" works when followed
…chain this follow-up's Tests pair from develop's 1519 — the develop merge cd24602 dropped #163's entry (17 lines, now byte-for-byte develop's again, below this entry) and left this entry's pair at 1495 → 1496, which test-doc-test-totals matched against #163's journey pair from 1495; 1519 → 1520 is the measured npm test total

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhPGnqVJ24goSVtbKpdkLJ
fix(store): on Windows the path comparison reads a path's volume through a handle — on Node 22.16.x (libuv 1.49.2) a path through a share of the workspace compared as outside it
@MoebiusX
MoebiusX marked this pull request as ready for review October 15, 2026 12:29
@MoebiusX
MoebiusX merged commit 8e78c5c into main Oct 15, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants