Repository navigation
chore(sync): merge sanitized upstream through v1.0.3 (Helm) - #20
Merged
Merged
Conversation
The home bottom bar is now a centered floating pill instead of a full-width strip. It blurs whatever is behind it with Haze, carries a hairline edge, and keeps the icons-only design: the current tab shows a filled glyph on a soft indicator pill that springs in, the others stay outlined. Adds the Haze blur dependencies. Signed-off-by: Vela <vela@local>
Debug builds now carry the applicationIdSuffix .debug (io.github.nanomuse.app.debug), so a CI debug APK installs alongside the release nanoMuse instead of replacing it. The manifest already uses the applicationId placeholder everywhere; the launcher shortcuts get a debug source-set copy pointing at the debug package. Signed-off-by: Vela <vela@local>
Haze 2.x (and 1.7.x) need compileSdk 37 and the module is on 36, which failed checkDebugAarMetadata in CI. 1.6.10 carries no compileSdk floor and the same backdrop-blur API the bar uses. Signed-off-by: Vela <vela@local>
- hazeEffect's block is not a @composable scope in 1.x, so hoist the MaterialTheme surface lookup above it. - Name tints explicitly: HazeStyle has a twin constructor taking tint: HazeTint?, which made the call ambiguous. Signed-off-by: Vela <vela@local>
Draw modifiers paint in chain order: with hazeEffect() before clip(), the blurred rect was drawn unclipped and the frost stuck out past the pill's rounded ends, making the sides look rectangular. Clipping first masks the blur to the pill shape. Signed-off-by: Vela <vela@local>
Every CI runner mints its own throwaway debug key, so consecutive CI
APKs carried different signatures and Android refused to install one
over the other ('update incompatible'). The committed ci-debug.keystore
uses the stock public debug credentials and is debug-only.
Signed-off-by: Vela <vela@local>
M3E: floating frosted-glass pill bottom bar
MinisMenu's container was surfaceContainerHigh grey; now it's the chat canvas (pure black in dark, white in light) with a slightly stronger hairline. Cherry-picked from m3e/chat-meta-ai-polish for upstream. Signed-off-by: Vela <vela@local>
Pure black canvas, large agent-name header, uppercase section labels, quiet monochrome pills for selected rows, circular settings/search/new chat buttons. Cherry-picked from m3e/chat-meta-ai-polish for upstream. Signed-off-by: Vela <vela@local>
…ranch These are sent as separate upstream PRs (upstream/menu-polish, upstream/drawer-polish). This branch keeps only the pill nav and Meta AI chat polish. Signed-off-by: Vela <vela@local>
Brings the branch up to 1.0.2 so the CHANGELOG lines and the Android sources merge against what is on main today. No conflicts. Signed-off-by: lgy0404 <2528379691@qq.com>
Takes back a5a20d2 (debug builds under io.github.nanomuse.app.debug) and c02ca42 (a committed debug keystore for CI): the signing config, the debug build type, ci-debug.keystore, the debug copy of shortcuts.xml and the CHANGELOG line. A debug build keeps installing over the release app, the way it has, and the repository carries no key, not even a public one; how test APKs get a stable signature is a separate conversation from the look. For nano-muse#329 Signed-off-by: lgy0404 <2528379691@qq.com>
…s and the Chinese page CHANGELOG.md had a leftover `<<<<<<< HEAD` marker and the new line inside the released 1.0.0 block; the marker is gone and the line sits under Unreleased, Android, now also naming the menus' canvas and the author. THIRD_PARTY_NOTICES.md lists Haze (Apache-2.0) among the Gradle dependencies, docs/zh/every-device.md says what docs/every-device.md says about the bar, and four new code comments read without em dashes. For nano-muse#329 Signed-off-by: lgy0404 <2528379691@qq.com>
style(android): pure black popup menus
Brings the branch up to main with nano-muse#329 merged, so the drawer commit is the only change left. No conflicts. Signed-off-by: lgy0404 <2528379691@qq.com>
…t for now The drawer commit also removed the content's bottom inset and passed a `nmBottomOverlay` to the chat screen that nothing on main defines, so the branch did not compile. Those two hunks belong to the chat polish (nano-muse#331) and come back with it; this PR is the drawer. Also a CHANGELOG line under Unreleased, Android, and two code comments without em dashes. For nano-muse#330 Signed-off-by: lgy0404 <2528379691@qq.com>
The five tabs sit in a centred Capsule 12 pt above the bottom safe area, icons only: .ultraThinMaterial under the shell's surface tone at 55 percent, a 1 pt hairline edge, 60 by 46 pt tap boxes. The current tab shows its filled symbol on an indicator capsule in the new NanoMuseTones.tabIndicator tone (Android's primaryContainer, light and dark) that springs to the tab tapped next through matchedGeometryEffect; the others stay outlined in the secondary colour. The full-width strip and its hairline on top are gone. The SF symbols, the accessibility labels and the selected trait are the ones from before, so no string changes. Layout: the pill lies over the rooms and the chat in a ZStack aligned to the bottom. The chat keeps the 0.1.40 rule (plain layout, never an inset of the NavigationStack's ancestor) as bottom padding of the bar's height, so the composer sits above the pill. The rooms are plain SwiftUI scroll views and take the same height as a safeAreaInset, so their content scrolls under the pill and the glass has something to blur. The bar still leaves while the keyboard or the voice panel is up. Follows nano-muse#329 by @Ichiro786 (Android's MuseBottomBar). Signed-off-by: lgy0404 <2528379691@qq.com>
The five tabs sit in a rounded pill 12 px above the bottom edge, over the safe area, icons only and no labels, the same bar the Android app draws since nano-muse#329: the pill is surface-2 at 55 percent over a backdrop blur with a hairline ring of the border colour at 50 percent; the current tab shows its filled glyph on a soft blue indicator (a new accent-soft pair, light #e5f0ff with #012f80 ink, dark #1a2b4a with #e5f0ff ink), the others stay outlined in muted. The background colour eases over 300 ms. The bar floats over the screen column instead of taking a row of it; the nav lets taps through and only the pill takes them. The screens keep clear of the pill through one place, a tabbar-room utility on <main> that pads the bottom by the pill's footprint (74 px plus the safe area), given back with wide:pb-0 when the sidebar shows; the chat's composer sits above it, and the toast rises by the safe area so it clears the pill on a phone with a home indicator. Lite keeps the bar at any width, as before. Docs: app.md, design.md and their Chinese twins describe the pill; CHANGELOG under Unreleased, Web. The built app under nanomuse/server/static is regenerated. Follows nano-muse#329 by @Ichiro786. Signed-off-by: lgy0404 <2528379691@qq.com>
feat(android): restyle chats drawer in Muse's visual language
Signed-off-by: lgy0404 <2528379691@qq.com>
Signed-off-by: lgy0404 <2528379691@qq.com>
Brings in nano-muse#329 and nano-muse#330 so docs/every-device.md can describe every client in one row. Signed-off-by: lgy0404 <2528379691@qq.com>
The row for Feed, Ideas, Goals and Library names the floating pill at phone width on the web and on iOS, and the sidebar on a wide window and in the desktop app, in English and in Chinese. Signed-off-by: lgy0404 <2528379691@qq.com>
feat(web): the phone layout's tab bar is a floating frosted-glass pill
… only AnthropicProvider.resolveSystemPrompt read ClaudeOAuthManager.ANTHROPIC_OAUTH_IDENTIFIER_PROMPT before checking isOAuth. The getter throws when BuildConfig leaves the value empty, which is the case on the public build (provider-customization.properties is not shipped), so every send and stream through an own Anthropic API key failed with "ANTHROPIC_OAUTH_IDENTIFIER_PROMPT is not configured" before any HTTP request. The read now sits inside the OAuth branch; the API-key path never needed it. The 30 API-key cases of the upstream AnthropicProviderTest pass again. Its one OAuth case needs a non-empty identifier, so it now runs under an Assume on the BuildConfig value and is skipped, not failed, where the value is empty. A regression test in io.github.nanomuse.models, the package the CI filter runs, sends through MockWebServer with a null and with a normal system prompt and checks one request, no or one `system` block. For nano-muse#333 Signed-off-by: lgy0404 <2528379691@qq.com>
…tput
TerminalSanitizer.foldCarriageReturns kept only the last non-empty segment
of a line split on \r, so "AAAA\rBB" became "BB" and a progress line
followed by a shorter final line handed the model a truncated result. A \r
now resets the write column to 0 and the next segment overwrites from
there; shorter text keeps the old tail, which is what a terminal shows.
"AAAA\rBB" is "BBAA", "10%\r50%\r100%" is "100%", "\r\n" stays a line
break. The final trim of sanitize() stays as it was.
The two data-loss cases of the upstream TerminalSanitizerTest pass. Its two
whitespace expectations ("complete ", " 100%[=========>]") only failed
because of that deliberate trim and now expect the trimmed text, with a
comment. A test class under io.github.nanomuse.sandbox covers the four
shapes above plus a longer rewrite, so the CI filter runs them.
For nano-muse#334
Signed-off-by: lgy0404 <2528379691@qq.com>
For nano-muse#333 For nano-muse#334 Signed-off-by: lgy0404 <2528379691@qq.com>
…test ExecutionCoordinatorInstrumentedTest still read ExecutionCoordinator.mountedSessionId, a field the coordinator dropped when it moved to one PersistentShell and one Mutex per session. compileDebugAndroidTestKotlin failed with eight unresolved references, which also kept io.github.nanomuse.reach.ReachHubInstrumentedTest from ever running on a device. The eight assertions now check the command result and whether the session's shell is registered, through one small internal accessor on the coordinator (hasShell). The reflection reset of the old field is replaced by sessionDidTerminate for every test session. The assertion that sessionDidTerminate empties the kernel's bind mount table is dropped: the coordinator only stops and drops the shell today. The Android workflow compiles the instrumentation sources right after the unit tests, so the source set stays compilable. The tests themselves still need a device. For nano-muse#332 Signed-off-by: lgy0404 <2528379691@qq.com>
…pects OpenAIProvider.sendMessageClamped always issues a streaming request and folds the deltas into one LLMResponse, because some gateways reject stream=false; a plain JSON body yields no chunk and failOnSilentEmptyCompletion raises LLMError.TransientError. Fourteen cases still enqueued non-streaming ChatCompletions bodies and failed with that error. The test gains an sse() helper and a one-delta sseReply(); the fourteen fixtures are SSE streams whose last chunk carries finish_reason and usage, then [DONE]. The request assertion expects stream=true and stream_options.include_usage=true. The empty-choices case expects the documented TransientError. The cached-tokens case follows parseChatCompletionsUsage, which reports the fresh prompt tokens in inputTokens and the full prompt in latestContextTokens. The CI filter is unchanged; the class joins it once the sibling Anthropic fix has landed. For nano-muse#335 Signed-off-by: lgy0404 <2528379691@qq.com>
For nano-muse#332 For nano-muse#335 Signed-off-by: lgy0404 <2528379691@qq.com>
fix(cloud): one hub device per console tab, consistent backups, a mail that rounds like the SMS
The new Windows job hung for half an hour in the shell's tests: the helper test reads the token file's mode bits back (0600, 0700), Windows has none, the assertion failed before stop() and the fake helper's HTTP server kept the test process alive. The mode check is now skipped on win32, every fake server is closed in after() so a failed assertion cannot hang the run again, and both harness jobs carry a 30 minute limit. Signed-off-by: lgy0404 <2528379691@qq.com>
Signed-off-by: lgy0404 <2528379691@qq.com>
…ipts Signed-off-by: lgy0404 <2528379691@qq.com>
The relay still sends both: `password_wrong` when the current password given while changing or removing one is not the one set (service.py set_password, clear_password), `password_weak` for a new password with fewer than three different characters or equal to the address. The audit's commit folded the first into the sign-in sentence and the second into the eight-characters rule; each gets its own line again, the second a new one in nine languages. Signed-off-by: lgy0404 <2528379691@qq.com>
…ders every page
Eleven spots on docs/zh/{desktop-muse,every-device,ios,parity}.md closed a
bold or italic run right after a Chinese colon, a full stop or a closing
bracket and went on with a character, which CommonMark does not read as a
closer; the site showed the asterisks (checked with markdown-it-py and the
built site). The design page's dragon row says the error state has a still
only, as web/src/avatars.ts has it. CONTRIBUTING.md states the rule and
tests/test_docs_markup.py renders README.md and every page under docs/ and
fails on a literal marker.
Signed-off-by: lgy0404 <2528379691@qq.com>
fix(ios): password refusals, the Cloud row, the relay key, Reduce Motion, three translations
The translocation and defaultHelperPath tests built or compared macOS paths through node:path's join, which uses the backslash on Windows; the first joins with "/" on purpose and the second compares with the separators normalised, so the Windows job runs the shell's 59 tests green. Signed-off-by: lgy0404 <2528379691@qq.com>
# Conflicts: # docs/app.md # docs/configuration.md # docs/zh/app.md # docs/zh/configuration.md
Signed-off-by: lgy0404 <2528379691@qq.com>
…ipts Signed-off-by: lgy0404 <2528379691@qq.com>
docs: bring the docs up to the code after the docs audit
# Conflicts: # CHANGELOG.md
…writes A page without the past-releases table, or with the version's row already there, refused the run after CHANGELOG.md, the READMEs and the issue forms had been rewritten. The rows are now computed right after the arguments are checked and written in their old place, so a refusal leaves every file as it was; the test covers it. Signed-off-by: lgy0404 <2528379691@qq.com>
…ipts # Conflicts: # CHANGELOG.md
ci: label web pull requests right, test the desktop on Windows, trim the Docker contexts
…ipts # Conflicts: # CHANGELOG.md
…ipts chore(release): release-docs.py writes the roadmap rows; release-apk.sh checks the iOS version
The admin page's funnel line said how many people had made a code, brought someone and come through one, and nothing more; the relay has held who signed up with whose code since invites began, but no view showed it. A new Invites view (GET /v1/admin/invites) ranks the inviters by the accounts their code brought, with how many of those ever made a request, how many were seen from one of the inviter's own addresses, what they spent, what the inviter earned from them and when the first and the last signed up; a row unfolds to the newest of the people it brought. An account's page names its inviter by identifier with a link and lists everyone it brought with when they joined, whether they used anything and from where; the accounts table marks an inviter with the count and can sort by it. English and 简体中文; the route is in the api docstring, cloud/README.md and docs/cloud.md with its twin. The invitee list is ordered newest first with the row id as the tie break, so two sign-ups in one second keep a stable order. Signed-off-by: lgy0404 <2528379691@qq.com>
feat(relay): show who invited whom on the admin page
Integrate nano-muse/nanoMuse main (1896212, 180 commits past the fork's previous merge base 5379e97) into the fork. This covers the published upstream release v1.0.3 (34a950c, an ancestor of upstream/main, so no separate release-commit integration was needed). Fork-only features preserved across the merge: Google Calendar over OAuth (nanomuse/calendar/feeds.py keeps the _refresh_feeds/_refresh_google split and takes upstream's _error_text URL redaction, since private feed links are secrets), the Android requireBaseUrl/relay_unconfigured guard, configurable relay hosting, signed-out relay editing, and bundled desktop Playwright/Chromium. Sanitization: no active nanomuse.cn / demo.nanomuse.dev / upstream-repo references remain outside the historical and attribution paths the contract preserves. The Chinese docs re-add the "upstream's public relay" attribution that upstream's 1.0.3 rewording dropped. Generated assets (nanomuse/server/static) are taken from upstream's tree and regenerated from the merged source in the following commit. Historical and attribution references are preserved as-is: CHANGELOG.md, docs/releases/**, docs/privacy.md, docs/roadmap.md, docs/readme/**, site/README.md, cloud/deploy/nanomuse-hk/**, demo/showcase/**, and unrelated third-party .cn citations (bigmodel.cn, moonshot.cn, siliconflow.cn, tuna mirrors). Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
`nanomuse/server/static/**` is a committed build artifact, so it is never merged
by hand: the previous commit took upstream's tree and this one replaces it with
the output of the merged source.
cd web && PATH=/opt/homebrew/opt/node@22/bin:$PATH npm ci && npm run build
vite.config.ts writes `outDir: "../nanomuse/server/static"` with
`emptyOutDir: true`. Node 22 is required; the default node on this machine is
v26. `grep -rl 'nanomuse\.cn' nanomuse/server/static/` is empty.
Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
…rewrote Both files arrive from upstream 1.0.3 with assertions that assume upstream's own configuration, so they fail against the fork's sanitization contract rather than against the merged code: - `tests/test_readme_contributors.py` asserts the badge is `hits.sh/github.com/nano-muse/nanoMuse.svg?`. That URL embeds an upstream repo reference, which `tests/test_fork_docs_sanitization.py` forbids, so the ten READMEs carry the fork's komarev badge. Restores the fork's assertion (it was already this way at `fork/main` and the merge overwrote it). - `tests/test_endpoints_api.py` is new to the fork and adds `settings.cloud.base_url + "/v1"` as a custom endpoint, expecting the "it is the account, not an endpoint" refusal. With the fork's empty relay default that address is the relative `/v1`, refused earlier as malformed. The test now asserts the fork's behaviour for an unconfigured relay and then sets a relay on the live `Settings` to keep upstream's coverage of the account guard. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
The PR body for the v1.0.3 (Helm) sanitized sync: provenance, the canonical backend scan and its 18-file classified remainder, the fork-only features the merge had to preserve, the two upstream tests that needed a fork-aware expectation, and every check actually run. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
…tion left unformatted CI runs `ruff format --check` over more of the tree than the local commands in `AGENTS.md` do (`demo/` and `cloud/` are checked by their own jobs, with the repository's own ruff). Three files fail that gate, all of them fork-caused: - `cloud/nanomuse_cloud/config.py`: the comment above the emptied `invite_url` default lost its indentation when the default became `""`, so it sits at column 0 inside the class body. - `cloud/tests/test_cloud.py`: the same damage on one dict entry, plus two expressions that were laid out for upstream's longer `nanomuse.cn` URLs and no longer need the wrapping now that the example host is `relay.test` and `own_key_docs` was added. - `demo/showcase/mirror/traffic.py`: `OWN_HOSTS` kept the multi-line comprehension upstream needed for its long `TRAFFIC_HOSTS` default; with the sanitized empty default the formatter joins it to one line. Measured before this commit: `ruff format --check demo cloud` reported 11 files at `fork/main` and 3 here (the merge already took upstream's formatted versions of the other 8). After: 0, with `ruff check` and both pytest suites unchanged (178 relay, 44 gateway). No behaviour changes — whitespace and indentation only. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
… and guard it
Review found a real scar from this run's sanitization: dropping upstream's
download-mirror clause also swallowed the joining `;` and the sentence's own `.`,
so six READMEs read ".../releases/latest) Open the app" with the two sentences
glued together. `README.md:65` plus `docs/readme/README_{es,fr,id,ru,vi}.md:63`
now end the sentence properly, matching the wording already on `fork/main`
(`README_fr.md` also had a double space). The zh, zh-TW, ja and ko readmes were
never affected: the CJK ones have no space after `)` and the ja/ko ones continue
with a particle.
`tests/test_fork_docs_sanitization.py` grows a regression test for the whole
class: a `releases/latest)` link followed by whitespace and a word is the
signature, which no correct README produces.
Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
…vation claims The adversarial review fact-checked the body and found five wrong or overstated claims: the sanitization remainder is 19 files not 18, this run's evidence directory held one file not three, the stated tested head was stale and had two red CI jobs, and "preserved, not rewritten" was asserted over several paths that are in fact edited relative to upstream/main. Separate what is genuinely byte-identical to upstream from what was edited and why, restate the counts from a fresh scan, and record the review's findings. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
…resh runs The suite is 955 passed at the current head, not 954 -- the 954 reading predates the regression test added in cc4b552 -- so the delta against the fork/main baseline (854) is 101, not 100. The branch also carries seven commits, not five: an evidence commit sat between the ruff-format and README fixes. Pin the diff stat to the content head so it cannot drift as evidence is edited, and record the merge-time tip SHA in completion.md rather than here. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
A list of commits cannot contain the commit that writes it, so enumerating the evidence commits made the list stale on every edit. List the five content commits, which are fixed, and describe the evidence commits without counting them. Signed-off-by: Zeeshan Haque <zhaque.mail@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sync upstream nanoMuse v1.0.3 (Helm) into the fork (sanitized)
Merges the published upstream release
v1.0.3into the fork without losing any fork-onlyfeature, and keeps every
.cncloud-backend reference out of the shipped tree.Provenance
nano-muse/nanoMuse189621240d7efd6a99debc45a4cc1a55edb6b141(upstream/main)v1.0.3(Helm) — the only release newer than the fork's previous integration point34a950c82977f20006d19d87d2241fe1f7071e7c(refs/tags/v1.0.3) — an ancestor ofupstream/main, 67 commits behind it, so no separate release-commit integration was neededf3237f9b697e0fd6c988c1fafcd2bfce830d54fc(fork/main)5379e97a5e6d8c68c6f1fc4da3b4649692b94f82git rev-list --count fork/main..upstream/main)cc4b552a040c53d78d05e57ef88c75c63fb0827dmaintenance-evidence/run-2026-10-11/, so tip and content head have identical codefork/main..cc4b552a04, content only)Five content commits sit on
fork/main, each with a DCOSigned-off-byline. Everythingafter
cc4b552a04is evidence-only, touching nothing butmaintenance-evidence/run-2026-10-11/:The full runtime suite was re-run at the branch tip as well as at the content head, so the
numbers below describe the code that would merge rather than an earlier revision. Because
each further evidence edit moves the tip without touching code, the exact tip SHA at merge
time is recorded in
maintenance-evidence/run-2026-10-11/completion.mdinstead of here.Releases are discovered independently of whether
upstream/mainmoved. Fork releasesalready present (
v1.0.0-fork.1,v1.0.1-fork.1,v1.0.2-fork.1,v0.1.41-fork.1, …)were deduplicated by upstream tag;
v1.0.3-fork.1did not exist.Sanitization — the scan of record
Post-merge, the canonical scan (this exact command is the evidence of record in
maintenance/RUNBOOK.md):Remainder — 19 files, every one classified, none a new active reference:
(The runbook's "as of the 0.1.41 sync" list is 13 files; the extra six are prior runs'
evidence files plus this run's own, which necessarily quote
nanomuse\.cn. This run'scompletion.mdwill be a 20th once the run finishes.)Active-surface scan of the areas the command does not exclude is empty:
Contract held
NANOMUSE_CLOUD_BASE_URL/cloud.base_urlis still the only relay seam.cloud/nanomuse_cloud/config.py:invite_url,own_key_docs,privacy_url,repo_urlall default to
"";openrouter_urlkeeps its documented third-party default.relay_unconfiguredbefore any network I/O(
nanomuse/cloud.py), and the Android path still callsrequireBaseUrl(context)beforebuilding a request (
NanoMuseCloud.kt:1129).(
在 \cloud.nanomuse.cn` 上). The fork's "upstream's public relay" attribution was re-applied so the text never reads as this fork's own relay, matchingfork/main`.Historical and attribution material
Untouched relative to
upstream/main— no active reference was removed from them:CHANGELOG.md— byte-identical toupstream/maindocs/releases/**— relative tofork/mainupstream added only its owndocs/releases/v1.0.3.md; the directory carries no fork editdocs/privacy.md,site/README.md— byte-identical toupstream/mainEdited relative to
upstream/mainonly to rename the repository, drop the hosted-demoand download-mirror references, and bump the version. Their history and their upstream
attribution are kept, not rewritten:
docs/readme/README_*.md(all ten),docs/release-notes-template.md,docs/roadmap.mdcloud/deploy/nanomuse-hk/deploy.shdemo/showcase/**(gateway/showcase_gateway/{config,logs,webpage}.py,mirror/traffic.py)Unrelated third-party
.cncitations are untouched:open.bigmodel.cn,api.moonshot.cn,api.siliconflow.cn,open.feishu.cn,iat-api.xfyun.cn,pypi.tuna.tsinghua.edu.cn,goproxy.cn, and the rest.Generated assets
nanomuse/server/static/**is never merged by hand. Commitc7bd659949takes upstream'stree unchanged; commit
df23dbb031replaces it with the output of the merged source builton Node 22 (
vite.config.tswritesoutDir: "../nanomuse/server/static",emptyOutDir: true). CI'sweb app buildjob re-runsnpm run buildand fails if thecommitted bundle is stale — it is green.
Fork-only features preserved
nanomuse/calendar/feeds.py_refresh_feeds/_refresh_googlesplit kept and upstream's_error_textURL redaction taken (private feed links are secrets)relay_unconfiguredbefore network I/ONanoMuseCloud.ktrequireBaseUrl(context)kept inside upstream's refactoredrequest()nanomuse/server/*,web/src/**scripts/desktop-app/*,harness/desktopnanomuse/server/update.pyINDEX_URL = os.environ.get("NANOMUSE_UPDATE_INDEX_URL", ""), no default, no fallbacksource: 'github' | 'mirror' | 'none'harness/dsh-nanomuse/src/desk.tsREADME.md,docs/readme/**No file present at
fork/mainis missing from this branch except regeneratednanomuse/server/static/assets/*bundles; zero non-static files were dropped.Three upstream tests needed a fork-aware expectation
These arrive with 1.0.3 and fail against the fork's configuration rather than against the
merged code. They are fixed, not papered over:
tests/test_readme_contributors.pyasserted the badge ishits.sh/github.com/nano-muse/nanoMuse.svg?. That URL embeds an upstream repositoryreference, which
tests/test_fork_docs_sanitization.pyforbids; the ten READMEs carrythe fork's komarev badge. The fork's assertion (already present at
fork/main) isrestored.
tests/test_endpoints_api.pyis new to the fork and postssettings.cloud.base_url + "/v1"as a custom endpoint, expecting the "it is theaccount, not an endpoint" refusal. With the fork's empty relay default that address is
the relative
/v1, refused earlier as malformed. The test now asserts the fork'sbehaviour for an unconfigured relay, then sets a relay on the live
Settingsand keepsupstream's coverage of the account guard.
tests/test_fork_docs_sanitization.pygrows a regression test for the sentence-gluingscar described under Review below.
Checks actually run
Local
pytest -q -m "not live"(runtime, py3.12 CI venv)fork/mainbaseline (/tmp/nm_base,f3237f9b69)cloud/ruff check . && ruff format --check . && pytest -qdemoruff check && ruff format --check; gatewaypytest -qruff check nanomuse tests scripts/ruff format --check nanomuse tests scriptsmypy(py3.12 venv,[tool.mypy] files = ["nanomuse"])python -m compileall -q demo cloud nanomuse scriptswebnpm run check(lint + tsc + vitest)harness/dsh-nanomusebuild + typecheck + testharness/desktoptypecheck + testnode scripts/connectors-json.mjs --check/providers-json.mjs --checkThe merge adds 101 passing runtime tests and no new failure (the count rose from 854 at
fork/mainto 955 here; the last one is the regression test for the scar below).CI
The first pushed head (
f38a067f85) had two red jobs, bothruff format --checkfailures the fork's own earlier sanitization had left behind and which the local commands
in
AGENTS.mddo not cover (demo/andcloud/are checked by their own jobs):gateway tests—demo/showcase/mirror/traffic.pyrelay · ruff and pytest—cloud/nanomuse_cloud/config.py:493,cloud/tests/test_cloud.py:694(an indentation scar and two expressions laid out forupstream's longer URLs)
ruff format --check demo cloudreported 11 unformatted files atfork/mainand 3here — the merge already took upstream's formatted versions of the other eight. Commit
204633f988applies the repository's own formatter to the remaining three; both jobs arenow green at the current head, as are
Signed-off-by on every commit,web app build,build · test · packandbuild · test (Windows).End-to-end smoke proof (before any expensive build)
nanomuse servev1.0.3 booted on127.0.0.1:8791from the merged tree:/api/statewith the Bearer token → HTTP 200,version: "1.0.3"/api/statewithout a token → HTTP 401invalid or missing tokenindex.html→ HTTP 200, including theentry chunk
assets/index-tYqPtwPX.jsproduced by the regenerated bundlechrome-headless-shell, Chrome for Testing 153.0.8010.12) navigatedhttp://127.0.0.1:8791/#token=…: the SPA mounted into<div id="root">and rendered theonboarding copy ("nanoMuse · Skip setup · Meet your nanoMuse …"). The only stderr line
is the known non-GUI-session
CVDisplayLinkCreateWithCGDisplay failednoise.Review
A separate fresh-context read-only subagent reviewed the diff, independently re-ran the
backend scan and both pytest suites, re-checked the baseline comparison, audited credential
handling and release provenance, and fact-checked this body. Verdict: safe to merge, no
blockers.
Its findings, all corrected before the merge:
.and the joining;inREADME.mdand five translated readmes, gluing two sentences together. Fixed incc4b552a04, with a regression test. (Review listed four readmes;README_ru.mdhadthe same scar and is fixed too.)
evidence directory held one file, not three. Corrected above.
relative to
upstream/main. The section above now separates what is genuinelyuntouched from what was edited, and says why.
Not verified here
and release-time artifacts, not verified in this PR.
index.htmlasset referenceexists on disk, no
.cnstrings, no upstream repo refs) and CI rebuilds it, but it wasnot byte-compared against a fresh build in this session.
the surrounding evidence instead.