fix(auth): say the workspace was created, gutter-aligned, during email sign-in - #74
Conversation
There was a problem hiding this comment.
LGTM: workspace-outcome wording is correctly wired per landing kind, the diff matches the PR's stated diffstat and head SHA exactly, and typecheck/lint/test are clean when reproduced locally.
Verification
- Head SHA confirmed:
8d453f9d33515a2eb1bab5cc165dd223b769d914(checked out locally,git rev-parse HEADmatches exactly). - Merge-base with
mainis34cdb27dbc550b95df40f134bf38c4b06cc6d71e, matching the PR API's reported base SHA;git diff --statagainst that merge-base reproduces the PR's own diffstat (4 files, +77/-9). npm run codegen && npm run typecheck: clean, 0 errors.npm run lint: clean, 0 problems.npm run test: 371/371 passing, 0 failures on Node 22.22.2. Note: the PR body claims 376 pass — I could not reproduce that number (371 = the count on this checkout including all 4 new tests this PR adds), so it looks like a stale/typo'd figure rather than a real discrepancy, but flagging since it doesn't match as stated.- CI on the head commit: all 3 Node matrix check-runs (20.x / 22.x / 24.x) completed successfully.
- Author
justinhelmeris a human GitHub account (type: Userper the API), not a bot identity — no self-approval concern.
Landing-kind coverage — workspaceOutcome (src/commands/auth/signup.ts:185) has 3 branches: created, joined, and a default that covers existing / verify_email / verify_to_join / workspace_full / invite_at_capacity / none / undefined.
created: unit-tested directly (test/signup.test.ts:419) and exercised end-to-end (test/signup.test.ts:334-357), asserting both the new line's exact text and the absence of the old raw un-aligned line.joined: unit-tested directly (test/signup.test.ts:422); the end-to-endjoinedtest (test/signup.test.ts:360-386) only asserts the pre-existingnextStepswording, not the newworkspaceOutcome/stepline's text.- default/fallback: unit-tested directly for both
existingandundefinedlanding (test/signup.test.ts:424-427); the password re-auth flow (describe('auth signup existing-account re-auth'),test/signup.test.ts:213-282) runs this exact code path but doesn't assert on the new wording's text.
Neither gap is blocking: the announce wiring ((ws) => step(workspaceOutcome(ws, landing)) in signup.ts:202) is a single call site already proven end-to-end by the created flow test, and every switch branch of workspaceOutcome is directly unit-tested — so the untested combinations are "known-good function, unasserted integration," not unverified logic. A follow-up assertion on the joined/default lines in their existing flow tests would close the loop cheaply.
Nits
workspaceOutcomeinterpolatesws.nameinside literal double quotes (signup.ts:188-192) with no escaping — a workspace name containing a"(e.g.My "Cool" Workspace) would render a visually broken/ambiguous line. Low risk and display-only, and the pre-existing default announce inlogin.ts:78andworkspaceStepinsignup.ts:87-109already have the same unescaped-interpolation pattern, so this isn't a regression — just worth a follow-up if workspace names are fully free-form.- The new step line uses
ws.name("Acme") while the adjacent "Next steps" note useslanding.workspaceSlug("acme") for the same workspace. Pre-existing inconsistency (not introduced here), just now sitting closer together in the output.
The callback-over-landing-param design (avoiding the Landing type-import cycle) is reasonable and clearly explained in the PR body; selectWorkspace's default announce keeps the API-key/OAuth paths byte-identical as claimed.
Generated by Claude Code
There was a problem hiding this comment.
Auto-approved: Claude reviewed this PR and posted an LGTM verdict (see its review). A repo admin enabled this via the auto-approve workflow.
Generated by Claude Code
…l sign-in
The single-workspace outcome after email sign-in was a raw stderr line
("Using workspace My Workspace (ws_…)") that broke the clack prompt gutter
and read as if the workspace pre-existed. selectWorkspace now takes an
announce callback; the signup flow renders a clack step line worded by the
landing kind: created → "Created your first workspace (called "X"), and set
it as your default."; joined / existing keep their own phrasing. API-key and
OAuth login paths are unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8d453f9 to
ade7089
Compare
|
Addressed the review at
|
There was a problem hiding this comment.
LGTM: Round 2 re-review at ade7089372a22d07d043a8cfeaeeb6bfa4cab2fd.
- SHA/diff: head SHA matches the PR API exactly. Diff against the true merge-base (
34cdb27, sincemainhas advanced past the PR's actual branch point) is 4 files / +81 / -10, matching the PR API'sadditions/deletions/changed_filesexactly. - Coverage gap closed: the
joinedand re-auth (existing) flow tests now assert the new wording directly, not justworkspaceOutcomein isolation:test/signup.test.ts:272— re-auth flow test assertsoutput.includes('Using workspace "Acme" as your default.')and that'Created your first workspace'is absent.test/signup.test.ts:387—joined-landing flow test assertsoutput.includes('Joined the "Acme" workspace, and set it as your default.').
- PR body: no longer claims a specific test-count figure; now says "all pass" without a number.
- Local checks (fresh run):
npm run typecheckclean,npm run lintclean,npm test→ 371/371 pass, 0 fail, 0 skipped. - CI: all 3 checks green on this head SHA (
checks / Test & typecheckon Node 20.x, 22.x, 24.x — allcompleted/success). - Nits from round 1: both confirmed addressed via reply, not code change — author's comment on this PR: unescaped
"in workspace names is "intentionally left: display-only, and the same unescaped pattern already exists inlogin.tsandworkspaceStep... tracking as a follow-up"; the name-vs-slug inconsistency is "pre-existing innextSteps; out of scope here... follow-up material." Reasonable to leave as follow-ups.
No blockers remain.
Generated by Claude Code
There was a problem hiding this comment.
Auto-approved: Claude reviewed this PR and posted an LGTM verdict (see its review). A repo admin enabled this via the auto-approve workflow.
Generated by Claude Code
After email sign-in the CLI printed a raw
Using workspace My Workspace (ws_…)line that broke the prompt layout and implied the workspace already existed. It now prints an aligned line that says the workspace was just created for them.What & why
First-time users never asked for a workspace, so "Using workspace X (ws_…)" is confusing — and because it was a bare
process.stderr.write, it sat outside the clack gutter that the rest of the sign-in flow uses (see before screenshot). This is the CLI half of the install-output cleanup; the installer half is polylanedotcom#190. The two are independent (no stack).Changes
src/commands/auth/login.ts—selectWorkspacetakes anannounce(ws)callback for the single-workspace outcome; the default keeps the existing plain stderr line, so API-key and OAuth login are byte-identical.WorkspaceItemis exported.src/utils/prompt.ts— newstep()wrapper overp.log.step(the ◇ gutter line).src/commands/auth/signup.ts—workspaceOutcome(ws, landing)words the line by landing kind andpersistDefaultWorkspacenow receives the landing.created→Created your first workspace (called "X"), and set it as your default.;joined→Joined the "X" workspace, and set it as your default.; otherwiseUsing workspace "X" as your default.test/signup.test.ts— unit tests for each wording, a flow test on thecreatedlanding asserting the new line appears and the raw un-aligned line does not, and assertions on thejoinedand re-auth (existing) flow tests for their wordings.Decisions
ws_…id dropped from the sign-in line: it's noise mid-flow andpolylane workspace liststill shows it. Login paths outside clack keep the id.landingparam onselectWorkspace: avoids a type import cycle (Landinglives in signup.ts, which imports login.ts) and keeps the renderer choice with the caller.Validation
created/joined/existingwordings —workspaceOutcomeunit testssays the workspace was created for a first-time user…joinedand re-auth flows print their own wording (and re-auth never says "created") — assertions in the existing flow testsworkspace_id— existing testnpm run typecheck,npm run lint,npm test(all pass) locally; CI on this PRBefore (from the report):
After (rendered locally with clack):
🤖 Generated with Claude Code