From e40fba5345b7feb2c58a1338f9658df1a7e47cb0 Mon Sep 17 00:00:00 2001 From: Vladimir Rogojin Date: Sun, 7 Jun 2026 11:46:15 +0200 Subject: [PATCH 1/2] =?UTF-8?q?fix(cli)(#42):=20cut=20init=20--nametag=20t?= =?UTF-8?q?est=20budget=20240s=20=E2=86=92=20180s;=20bump=20SDK=20pin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes sphere-cli #42 in tandem with sphere-sdk PR #415. ## What - `test/integration/cli-wallet-lifecycle.integration.test.ts` — the `sphere init --nametag ` test's inner CLI timeout drops from 240s to 180s; the outer test wrap from 300s to 200s. Comment block explains the budget delta: pre-#42, the 240s slack absorbed the Nostr `publishIdentityBinding` stall in-band with the mint; post-#42 (sphere-sdk PR #415, `publishMode: 'background'` default) the relay write is detached, so the only in-band work left is the aggregator mint round-trip — comfortably under 180s even on contended testnet. - `.github/workflows/ci.yml` — bump `SPHERE_SDK_SHA` pin past sphere-sdk PR #415 (commit 8832a95) so CI exercises the new SDK behavior. Comment annotates the bump rationale. ## Why this satisfies the issue's acceptance criteria 1. **Identity block shows `nametag : @` synchronously after mint** — sphere-sdk PR #415 sets `_identity.nametag` immediately after the mint succeeds (and before `registerNametag` returns), so the CLI's `sphere.identity` read at `legacy-cli.ts:2294` always sees the just-claimed name. The CLI itself didn't need a code change — it was already reading from the right place; the SDK just wasn't setting it synchronously. 2. **`init --nametag` does NOT block on Nostr publish success** — the SDK's new background mode default detaches the relay write. 3. **Test budget cut to 180s** — done. 4. **Companion `nametag my reports` test continues to pass** — the SDK still persists the nametag locally (the cache write happens in-band, before the detached publish), so the next CLI invocation that calls `sphere nametag my` reads the stored value normally. ## Out of scope - Multi-target / multi-asset selector flags (issue #40 item #3). - NFT-only `invoice pay` flow (issue #40 item #4). ## Test plan - [x] `npm run build` — clean (ESM + CJS + DTS) - [x] `npx tsc --noEmit` — clean - [x] `npm run lint` — 0 errors (433 pre-existing warnings) - [x] `npx vitest run src/` — 127 passed (offline unit tests) - [x] Manual repro: `sphere init --network testnet --nametag it42_` prints `nametag : @it42_` synchronously inside ~5s against the production goggregator-test / nostr-relay-test infra. No `(none)` race. - [ ] CI green on the bumped SDK pin (will run automatically on push). --- .github/workflows/ci.yml | 8 ++++++- .../cli-wallet-lifecycle.integration.test.ts | 21 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a6c911..a4d49b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,13 @@ jobs: # this whole workaround once sphere-sdk publishes v0.7.1+ to npm # with the post-extraction exports. env: - SPHERE_SDK_SHA: 0e3290a1e3f41e3d30ca9f6a02b304da507106c7 + # Bumped past sphere-sdk PR #415 (issue #42) — `registerNametag` + # now publishes the Nostr binding fire-and-forget by default, + # so `Sphere.init({ nametag })` returns in mint-only time + # instead of blocking on a flaky / stalled relay. Required by + # the 180s timeout reduction in + # `cli-wallet-lifecycle.integration.test.ts` (this PR). + SPHERE_SDK_SHA: 8832a959cea0d29dda4d1086c84f31c1df508950 run: | git clone https://github.com/unicity-sphere/sphere-sdk.git ../../sphere-sdk # The pinned SHA may not be on a branch tip after future merges; diff --git a/test/integration/cli-wallet-lifecycle.integration.test.ts b/test/integration/cli-wallet-lifecycle.integration.test.ts index f2ad519..3ba5687 100644 --- a/test/integration/cli-wallet-lifecycle.integration.test.ts +++ b/test/integration/cli-wallet-lifecycle.integration.test.ts @@ -289,10 +289,20 @@ describe.skipIf(integrationSkip)( afterAll(() => { if (env) destroySphereEnv(env); }); it(`\`sphere init --nametag ${nametag}\` mints the nametag during wallet creation`, () => { + // Budget rationale (issue #42 acceptance criterion 3): + // 240s → 180s. The slack was originally provisioned to absorb a + // stalled Nostr publish during `Sphere.init({ nametag })` — under + // sphere-sdk's pre-#42 in-band publish contract, a flaky + // `nostr-relay.testnet.unicity.network` could swallow 60s+ of + // the budget BEFORE the test could see the identity block. + // sphere-sdk #42's `publishMode: 'background'` default detaches + // that publish (see `Sphere.registerNametag` step 4), so the + // only in-band work left is the aggregator mint round-trip, + // which comfortably finishes inside 180s even under load. const r = runSphere( env, ['init', '--network', 'testnet', '--nametag', nametag], - { timeoutMs: 240_000 }, + { timeoutMs: 180_000 }, ); if (r.status !== 0) { console.error('init --nametag failed', { stdout: r.stdout, stderr: r.stderr }); @@ -302,10 +312,17 @@ describe.skipIf(integrationSkip)( // ` nametag : @` // (renderIdentity prepends `@` to the nametag value; absent // nametags show `(none)`). + // + // The `(none)` failure mode that originally motivated this test + // (issue #42) is foreclosed by sphere-sdk #42 — the SDK now + // updates `_identity.nametag` synchronously after the mint + // succeeds, BEFORE returning from `registerNametag`, so the + // CLI's `sphere.identity` read at `legacy-cli.ts:2294` always + // sees the just-claimed name. expect(r.stdout).toMatch(new RegExp(`nametag\\s*:\\s*@${nametag}`)); // The wallet directory now exists on disk. expect(existsSync(join(env.home, '.sphere-cli', 'wallet.json'))).toBe(true); - }, 300_000); + }, 200_000); it('`sphere nametag my` reports the registered nametag after init --nametag', () => { // Re-verify via a different code path: read the nametag via the From 933070a08a417865879cc33b8befc5ab25ca42ca Mon Sep 17 00:00:00 2001 From: Vladimir Rogojin Date: Sun, 7 Jun 2026 20:42:18 +0200 Subject: [PATCH 2/2] ci(cli)(#42): bump SDK SHA pin to sphere-sdk PR #415 merge commit sphere-sdk PR #415 merged at `cc14f3c` (merge of branch `fix/issue-42-nametag-publish-out-of-band` into `main`). The PR landed the fire-and-forget Nostr nametag-publish change plus the review-driven correctness fixes for the detached publish handler (switchToAddress context snapshot, destroy-guard). The CLI's CI workflow now pins to the merge commit, replacing the earlier first-commit-of-the-PR pin (`8832a95`). With this bump CI exercises the final SDK state the CLI ships against. --- .github/workflows/ci.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4d49b2..aa6f2ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,13 +71,16 @@ jobs: # this whole workaround once sphere-sdk publishes v0.7.1+ to npm # with the post-extraction exports. env: - # Bumped past sphere-sdk PR #415 (issue #42) — `registerNametag` - # now publishes the Nostr binding fire-and-forget by default, - # so `Sphere.init({ nametag })` returns in mint-only time - # instead of blocking on a flaky / stalled relay. Required by - # the 180s timeout reduction in - # `cli-wallet-lifecycle.integration.test.ts` (this PR). - SPHERE_SDK_SHA: 8832a959cea0d29dda4d1086c84f31c1df508950 + # Bumped to the merge commit of sphere-sdk PR #415 (issue #42) — + # `registerNametag` now publishes the Nostr binding fire-and- + # forget by default, so `Sphere.init({ nametag })` returns in + # mint-only time instead of blocking on a flaky / stalled + # relay. Required by the 180s timeout reduction in + # `cli-wallet-lifecycle.integration.test.ts` (this PR). The + # merge commit also carries the review-driven correctness + # fixes for the detached publish handler (switchToAddress + # context snapshot, destroy-guard). + SPHERE_SDK_SHA: cc14f3cd1356720e056a35a5218a28ca7586831a run: | git clone https://github.com/unicity-sphere/sphere-sdk.git ../../sphere-sdk # The pinned SHA may not be on a branch tip after future merges;