fix: report unauthenticated auth state honestly #66

Merged
andres merged 4 commits from build/64-auth-state into main 2026-09-04 06:16:21 +00:00

Closes #64

Worklog

  • Add failing coverage for unauthenticated status and supplied-token logout
  • Implement the scoped auth status and logout behavior
  • Add the changelog fragment
  • Verify focused tests, the full suite, and the exact three-file diff
  • Fix round: remove the Node 22.12.0-sensitive stderr assertion
  • Fix round: verify the focused regression and full suite
  • Fix round: push and answer every reviewer point

Acceptance criteria

  • auth logout against a config with tokenId: null and no --local-only prints a message naming all three facts — credentials removed locally, stoke cannot revoke a token it did not create, the token is still valid at the configured URL with where to revoke it — and still exits 0.
  • auth logout --local-only against the same config produces output byte-identical to today’s.
  • auth logout against a config with a non-null tokenId is unchanged on every path: revoked, warned, and the no-password skip message.
  • auth status with no session exits 1 and still prints Not authenticated. on stdout.
  • auth status --json with no session exits 1 and prints exactly {"authenticated": false}.
  • auth status with a valid session still exits 0, and its --json output is still the raw /user object.
  • No output anywhere in this diff prints a token value.
  • git diff touches exactly src/cli.js, test/cli.test.js and one changelog.d/*.md.
  • npm test passes and ci / test is green on the PR head.

Round log

Round at bf84b19a

🔧 addressing round on head bf84b19a07

Round analysis:

  • GLM blocking — agree: the new localOnly stderr-empty assertion is not portable to the declared Node 22.12.0 floor because Commander’s ESM warning can be emitted there. I will remove that brittle stderr assertion while retaining the byte-exact stdout assertion and the behavioral guards, then run the focused test and full suite at the floor runtime if available.
  • Claude non-blocking test-coverage note — agree, no change in this PR: coverage for the pre-existing tokenId-backed logout branches is outside #64 and adding it would exceed the exact three-file scope.
  • Claude non-blocking README note — agree, no change in this PR: #64 explicitly constrains the diff to three files, so documentation expansion belongs in a separate proposal.
  • Kimi non-blocking duplicate removal wording — agree that it is mildly repetitive, no change: the pre-clear and post-clear messages are intentional and required by the issue’s sequencing/output contract.

I will append and complete the fix-round Worklog items, push the test correction without rewriting history, reply once covering the whole round and verification, then signal the final head while draft and mark ready with no intervening commit.

Round answered whole for head bf84b19a073219e04c14df264100d5d6d400e443; fixes are pushed at 1335232002.

  • GLM blocking: removed only the local-only stderr-empty assertion. On Node 22.12.0, the original assertion failed deterministically because Commander’s CommonJS-to-ESM ExperimentalWarning is emitted on stderr; the corrected focused test passes, while its byte-exact stdout assertion, exit status, config deletion, no-prompt, no-revocation-claim, and no-token-leak checks remain.
  • Claude non-blocking tokenId-path coverage note: no change. Those pre-existing paths remain outside #64 and direct coverage would exceed the mandated three-file scope.
  • Claude non-blocking README note: no change. The exact three-file acceptance criterion excludes README work; that belongs in a separate proposal.
  • Kimi non-blocking duplicate wording note: no change. The before-clear warning and after-clear confirmation preserve the required sequencing and output contract.

Verification on the final head: the focused test passes on Node 22.12.0 and Node 22.23.1; the full suite passes 145/145 on both runtimes; npm run check:governance passes; git diff --check passes; the tree is clean and matches the pushed remote head; the diff still contains exactly src/cli.js, test/cli.test.js, and changelog.d/64.md. The current-head CI test is pending, not red; the engine owns waiting for it before requesting the panel.

📣 round answered at head 1335232002

Round at 13352320

Round passed with no written reply.

Closes #64 ## Worklog - [x] Add failing coverage for unauthenticated status and supplied-token logout - [x] Implement the scoped auth status and logout behavior - [x] Add the changelog fragment - [x] Verify focused tests, the full suite, and the exact three-file diff - [x] Fix round: remove the Node 22.12.0-sensitive stderr assertion - [x] Fix round: verify the focused regression and full suite - [x] Fix round: push and answer every reviewer point ## Acceptance criteria - [x] `auth logout` against a config with `tokenId: null` and no `--local-only` prints a message naming all three facts — credentials removed locally, stoke cannot revoke a token it did not create, the token is still valid at the configured URL with where to revoke it — and still exits `0`. - [x] `auth logout --local-only` against the same config produces output byte-identical to today’s. - [x] `auth logout` against a config with a non-null `tokenId` is unchanged on every path: revoked, warned, and the no-password skip message. - [x] `auth status` with no session exits `1` and still prints `Not authenticated.` on stdout. - [x] `auth status --json` with no session exits `1` and prints exactly `{"authenticated": false}`. - [x] `auth status` with a valid session still exits `0`, and its `--json` output is still the raw `/user` object. - [x] No output anywhere in this diff prints a token value. - [x] `git diff` touches exactly `src/cli.js`, `test/cli.test.js` and one `changelog.d/*.md`. - [x] `npm test` passes and `ci / test` is green on the PR head. ## Round log <!-- round:bf84b19a073219e04c14df264100d5d6d400e443 --> **Round at bf84b19a** 🔧 addressing round on head bf84b19a073219e04c14df264100d5d6d400e443 Round analysis: - GLM blocking — agree: the new localOnly stderr-empty assertion is not portable to the declared Node 22.12.0 floor because Commander’s ESM warning can be emitted there. I will remove that brittle stderr assertion while retaining the byte-exact stdout assertion and the behavioral guards, then run the focused test and full suite at the floor runtime if available. - Claude non-blocking test-coverage note — agree, no change in this PR: coverage for the pre-existing tokenId-backed logout branches is outside #64 and adding it would exceed the exact three-file scope. - Claude non-blocking README note — agree, no change in this PR: #64 explicitly constrains the diff to three files, so documentation expansion belongs in a separate proposal. - Kimi non-blocking duplicate removal wording — agree that it is mildly repetitive, no change: the pre-clear and post-clear messages are intentional and required by the issue’s sequencing/output contract. I will append and complete the fix-round Worklog items, push the test correction without rewriting history, reply once covering the whole round and verification, then signal the final head while draft and mark ready with no intervening commit. Round answered whole for head bf84b19a073219e04c14df264100d5d6d400e443; fixes are pushed at 133523200262aaa8f4a47c594a524677ace9b026. - GLM blocking: removed only the local-only stderr-empty assertion. On Node 22.12.0, the original assertion failed deterministically because Commander’s CommonJS-to-ESM ExperimentalWarning is emitted on stderr; the corrected focused test passes, while its byte-exact stdout assertion, exit status, config deletion, no-prompt, no-revocation-claim, and no-token-leak checks remain. - Claude non-blocking tokenId-path coverage note: no change. Those pre-existing paths remain outside #64 and direct coverage would exceed the mandated three-file scope. - Claude non-blocking README note: no change. The exact three-file acceptance criterion excludes README work; that belongs in a separate proposal. - Kimi non-blocking duplicate wording note: no change. The before-clear warning and after-clear confirmation preserve the required sequencing and output contract. Verification on the final head: the focused test passes on Node 22.12.0 and Node 22.23.1; the full suite passes 145/145 on both runtimes; npm run check:governance passes; git diff --check passes; the tree is clean and matches the pushed remote head; the diff still contains exactly src/cli.js, test/cli.test.js, and changelog.d/64.md. The current-head CI test is pending, not red; the engine owns waiting for it before requesting the panel. 📣 round answered at head 133523200262aaa8f4a47c594a524677ace9b026 <!-- round:133523200262aaa8f4a47c594a524677ace9b026 --> **Round at 13352320** _Round passed with no written reply._
codex-bot-andresmgsl added 1 commit 2026-09-04 01:55:35 +00:00
test: cover unauthenticated auth state
Some checks failed
labels / labels (pull_request) Successful in 12s
ci / test (pull_request) Failing after 2m50s
ed3f234b8e
codex-bot-andresmgsl changed title from fix: report unauthenticated auth state honestly to WIP: fix: report unauthenticated auth state honestly 2026-09-04 01:55:41 +00:00
forgejo-actions added the
state:building
label 2026-09-04 01:55:53 +00:00
codex-bot-andresmgsl added 1 commit 2026-09-04 01:56:25 +00:00
fix: report unauthenticated auth state honestly
All checks were successful
labels / labels (pull_request) Successful in 12s
ci / test (pull_request) Successful in 4m0s
aedce42c56
forgejo-actions added the
scope:cli
label 2026-09-04 01:56:34 +00:00
codex-bot-andresmgsl added 1 commit 2026-09-04 01:56:42 +00:00
docs: record auth state fixes
All checks were successful
labels / labels (pull_request) Successful in 12s
ci / test (pull_request) Successful in 7m18s
bf84b19a07
forgejo-actions added the
scope:packaging
label 2026-09-04 01:57:02 +00:00
Author
Member

Build complete at head bf84b19a07.

  • Added the supplied-token logout notice without changing --local-only or tokenId-backed revocation branches.
  • Made unauthenticated text and JSON status output exit 1 while preserving authenticated JSON behavior.
  • Added the #64 changelog fragment.

Verification: the new assertions failed against the unfixed behavior, then passed after the implementation; npm test passed 145/145; git diff --check passed; and the diff contains exactly src/cli.js, test/cli.test.js, and changelog.d/64.md. The current-head ci / test check is pending, so its acceptance checkbox remains honestly unchecked; the engine owns waiting for it before panel request.

Build complete at head bf84b19a073219e04c14df264100d5d6d400e443. - Added the supplied-token logout notice without changing `--local-only` or `tokenId`-backed revocation branches. - Made unauthenticated text and JSON status output exit 1 while preserving authenticated JSON behavior. - Added the #64 changelog fragment. Verification: the new assertions failed against the unfixed behavior, then passed after the implementation; `npm test` passed 145/145; `git diff --check` passed; and the diff contains exactly `src/cli.js`, `test/cli.test.js`, and `changelog.d/64.md`. The current-head `ci / test` check is pending, so its acceptance checkbox remains honestly unchecked; the engine owns waiting for it before panel request.
Author
Member

📣 round answered at head bf84b19a07

📣 round answered at head bf84b19a073219e04c14df264100d5d6d400e443
codex-bot-andresmgsl changed title from WIP: fix: report unauthenticated auth state honestly to fix: report unauthenticated auth state honestly 2026-09-04 01:58:28 +00:00
forgejo-actions added
state:addressing
and removed
state:building
labels 2026-09-04 02:00:14 +00:00
codex-bot-andresmgsl requested review from glm-bot-andresmgsl 2026-09-04 02:05:53 +00:00
codex-bot-andresmgsl requested review from claude-bot-andresmgsl 2026-09-04 02:05:53 +00:00
codex-bot-andresmgsl requested review from kimi-bot-andresmgsl 2026-09-04 02:05:53 +00:00
codex-bot-andresmgsl added the
state:bots-reviewing
label 2026-09-04 02:05:54 +00:00
forgejo-actions removed the
state:addressing
label 2026-09-04 02:06:12 +00:00

🔎 reviewing head 1335232002

Fix round after my approve at bf84b19a. Whole PR re-reviewed at this head (detached worktree, npm ci).

  • Delta since bf84b19a is one line: the localOnly.stderr === '' assertion removed from test/cli.test.js:90.
  • Reproduced GLM's blocker and its exact mechanism at the engines floor (Node 22.12.0): commander@15 is "type":"module", so require(esm) emits an ExperimentalWarning on stderr. It surfaces only on paths that do not call process.exit() synchronously (the warning is queued on nextTick) — which is why auth logout --local-only failed while the two auth status stderr === '' assertions passed. One failing test, matching GLM's 144/145.
  • Full suite at this head: 145/145 on Node 22.12.0 (floor) and 145/145 on Node 24-era v22.23.2.
  • New tests genuinely fail against base src/cli.js — tests 4, 5, 6 fail on both runtimes.
  • Mutation-checked the surviving assertions: 7/7 mutants caught (authenticated status exits 1; notice on --local-only; notice to stderr; each of the three facts dropped; token interpolated; --json exits 0).
  • Base-vs-head behavioural probe over every logout/status path: exactly 3 intended deltas; tokenId-backed and --local-only stdout byte-identical; no token value anywhere.
  • process.exit(1) after console.log does not truncate stdout on pipes, files, or a slow reader.
  • ci / test success on this head (run 1172); labels / labels success.
  • npm run check:governance passes; git diff --check clean; diff touches exactly src/cli.js, test/cli.test.js, changelog.d/64.md.
  • One mutant now survives that bf84b19a caught: the notice written to stderr under --local-only. Non-blocking nit in the verdict.

Verdict: approve.

  • Verdict approve submitted via submit-verdict.sh and verified landed at 2026-09-04T02:43:31Z. Worktree removed; clone back on main, clean.
🔎 reviewing head 133523200262aaa8f4a47c594a524677ace9b026 Fix round after my approve at `bf84b19a`. Whole PR re-reviewed at this head (detached worktree, `npm ci`). - [x] Delta since `bf84b19a` is one line: the `localOnly.stderr === ''` assertion removed from `test/cli.test.js:90`. - [x] Reproduced GLM's blocker and its exact mechanism at the `engines` floor (Node 22.12.0): `commander@15` is `"type":"module"`, so `require(esm)` emits an `ExperimentalWarning` on stderr. It surfaces only on paths that do **not** call `process.exit()` synchronously (the warning is queued on `nextTick`) — which is why `auth logout --local-only` failed while the two `auth status` `stderr === ''` assertions passed. One failing test, matching GLM's 144/145. - [x] Full suite at this head: 145/145 on Node 22.12.0 (floor) and 145/145 on Node 24-era v22.23.2. - [x] New tests genuinely fail against base `src/cli.js` — tests 4, 5, 6 fail on both runtimes. - [x] Mutation-checked the surviving assertions: 7/7 mutants caught (authenticated status exits 1; notice on `--local-only`; notice to stderr; each of the three facts dropped; token interpolated; `--json` exits 0). - [x] Base-vs-head behavioural probe over every logout/status path: exactly 3 intended deltas; `tokenId`-backed and `--local-only` stdout byte-identical; no token value anywhere. - [x] `process.exit(1)` after `console.log` does not truncate stdout on pipes, files, or a slow reader. - [x] `ci / test` **success** on this head (run 1172); `labels / labels` success. - [x] `npm run check:governance` passes; `git diff --check` clean; diff touches exactly `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md`. - [ ] One mutant now survives that `bf84b19a` caught: the notice written to **stderr** under `--local-only`. Non-blocking nit in the verdict. Verdict: approve. - [x] Verdict **approve** submitted via `submit-verdict.sh` and verified landed at 2026-09-04T02:43:31Z. Worktree removed; clone back on `main`, clean.

🔎 reviewing head 1335232002

  • fix round after my request-changes at bf84b19a (stderr assertion vs Node 22.12.0 floor); re-reviewed the whole PR at this head against #64
  • fix commit 1335232 removes exactly the flagged assert.equal(localOnly.stderr, \"\"); implementation unchanged otherwise
  • npm test on floor Node 22.12.0 (this box default): 145/145; on Node 24.19.0: 145/145
  • failure-case probe: both new tests fail against base src/cli.js (restored after)
  • live probes at head: logout rc=0 three-fact message, no token leak; --local-only byte-exact; status rc=1 Not authenticated.; --json rc=1 exact {"authenticated": false}
  • ci/test + labels success on 1335232 (status API, runs 1172/1173); diff exactly three files; git diff --check clean
  • verdict: approve
🔎 reviewing head 133523200262aaa8f4a47c594a524677ace9b026 - fix round after my request-changes at bf84b19a (stderr assertion vs Node 22.12.0 floor); re-reviewed the whole PR at this head against #64 - fix commit 1335232 removes exactly the flagged `assert.equal(localOnly.stderr, \"\")`; implementation unchanged otherwise - npm test on floor Node 22.12.0 (this box default): 145/145; on Node 24.19.0: 145/145 - failure-case probe: both new tests fail against base src/cli.js (restored after) - live probes at head: logout rc=0 three-fact message, no token leak; --local-only byte-exact; status rc=1 `Not authenticated.`; --json rc=1 exact `{"authenticated": false}` - ci/test + labels success on 1335232 (status API, runs 1172/1173); diff exactly three files; git diff --check clean - verdict: approve

🔎 reviewing head 1335232002

  • All 9 acceptance criteria from #64 verified by execution: probes on every auth logout/status path; --local-only and no-password skip paths byte-identical to base (cmp); diff is exactly src/cli.js + test/cli.test.js + changelog.d/64.md; no token printed; full suite 145/145 on node v22.17.0 AND on the declared floor v22.12.0 (downloaded build; floor reproduces the ESM stderr warning that made GLM's blocked assertion non-portable — its removal is the right fix); new tests confirmed failing against base code (failure cases 4-6 not ok); CI green on head.
  • Verdict: APPROVE, submitted via submit-verdict.sh, wrapper verified landed at 2026-09-04T03:11:37Z.
  • Worktrees removed; clone back on main, clean.
🔎 reviewing head 133523200262aaa8f4a47c594a524677ace9b026 - All 9 acceptance criteria from #64 verified by execution: probes on every auth logout/status path; --local-only and no-password skip paths byte-identical to base (cmp); diff is exactly src/cli.js + test/cli.test.js + changelog.d/64.md; no token printed; full suite 145/145 on node v22.17.0 AND on the declared floor v22.12.0 (downloaded build; floor reproduces the ESM stderr warning that made GLM's blocked assertion non-portable — its removal is the right fix); new tests confirmed failing against base code (failure cases 4-6 not ok); CI green on head. - Verdict: APPROVE, submitted via submit-verdict.sh, wrapper verified landed at 2026-09-04T03:11:37Z. - Worktrees removed; clone back on main, clean.
claude-bot-andresmgsl approved these changes 2026-09-04 02:18:01 +00:00
Dismissed
claude-bot-andresmgsl left a comment
Member

Approve at bf84b19a073219e04c14df264100d5d6d400e443.

Reviewed the whole PR at this head in a detached worktree, against #64's acceptance criteria, then the repo's constraints, then the code.

Acceptance criteria — all nine met

I probed the base and the head side by side over every auth logout / auth status path and diffed the transcripts. The behavioural delta is exactly the four changes #64 asked for and nothing else:

criterion result
logout, tokenId: null, no --local-only → three facts, exit 0 met — prints the notice naming credentials-removed, cannot-revoke, still-valid-on-config.url + Settings > Applications; exit 0
logout --local-only on that config byte-identical to today met — Local credentials removed.\n, identical to base
logout with non-null tokenId unchanged on every path met — revoked / warned / no-password-skip transcripts are byte-identical base vs head
status no session → exit 1, Not authenticated. on stdout met
status --json no session → exit 1, exactly {"authenticated": false} met — base printed the prose line under --json; head prints the object
authenticated status still exits 0, --json still raw /user met — the case at test/cli.test.js L1039 is unmodified and passes
no output prints a token value met — probed with "token":"SECRET-TOK"; 0 occurrences across all paths
diff touches exactly three files met — src/cli.js, test/cli.test.js, changelog.d/64.md
npm test passes and ci / test green on head met — see below

The else if (!config.tokenId && !options.localOnly) placement is the right shape: it hangs off the existing if, so it is unreachable whenever tokenId is truthy, which is what makes the "unchanged on every path" criterion structurally true rather than incidentally true. It correctly does not attempt or prompt for revocation, including when -p is supplied on a supplied-token session.

Closes #64 is correct here — the issue explicitly sanctions it ("a Closes is equally correct here since every criterion is pre-merge"), and every criterion is indeed pre-merge.

What I ran

  • npm ci && npm test in the worktree: 145/145 pass.
  • npm run check:governance: passes (4 identities resolved, 5 scope rows valid).
  • The failure cases actually fail. Reverting only src/cli.js to 2230ca25 and re-running: not ok 39 (global --config flag…), not ok 40 (auth status reports an absent session…), not ok 41 (auth logout identifies a supplied token…) — 142/145. The three tests are load-bearing, not decorative.
  • Mutation-checked the new assertions. Four mutants against the fixed source, each caught: (1) status exits 1 even when authenticated → caught by the new test and by read commands print the raw API JSON with --json, which is the specific regression #64's test plan warns the exit-code edit invites; (2) logout prints Revoked token … on the null-tokenId path → caught; (3) the notice leaks into --local-only → caught; (4) the notice collapses to Removing local credentials. and drops the URL / where-to-revoke facts → caught.
  • git diff --check clean; changelog.d/64.md matches the one-line - … (#NN). form of 57.md and 60.md.
  • ci / test (pull_request) and labels / labels (pull_request) both read success on this head (run 1160 / 1161) from the commit-statuses API. The PR body's last checkbox is honestly unchecked because CI was pending at write time; it is green now, so that criterion is satisfied in fact.
  • scope:cli + scope:packaging is the right label pair per CONTRIBUTING (src/ and the changelog fragment).

The --json payload being a string literal rather than printJson({...}) is correct, not a shortcut: printJson pretty-prints, and the spec demands that exact single-line byte sequence.

What I could not verify, and what I relied on instead

  • The interactive TTY prompt path. This box has no TTY, so prompt(\Password for …`)never fires underspawnSync; that also means the new test's assert.doesNotMatch(logout.stdout, /Password for/)cannot catch a regression that prompts *while still* gated oninput.isTTY. It does still catch an ungated prompt. I relied on reading: tokenId` falsy can never enter the branch that contains the prompt at all, so the criterion holds by structure.
  • A real remote revocation. My --password-file probe hit Network error reaching https://forge.test against the stub host. That path is untouched by this diff, and its base and head transcripts are identical, so identity is what the criterion needs and identity is what I measured — but I did not exercise a successful deleteToken.
  • CI internals. I read the commit-statuses API, not the run logs; my own local npm test and check:governance are the independent evidence.

Non-blocking nits — builder's discretion, and neither is this PR's to fix

  1. test/cli.test.js still has no coverage at all for the tokenId-backed logout branches (revoked / warned / no-password skip). That gap predates this PR and #64 scoped it out, so it is correctly not addressed here; I verified those paths by direct base-vs-head probe instead. Worth a proposal rather than a review demand.
  2. README's stoke auth status section ("Display the currently authenticated user") documents no exit-code contract, and the auth logout section does not mention the supplied-token case. Making the unauthenticated exit code machine-detectable is precisely the kind of thing a scripting reader looks for in the README. #64 caps the diff at three files, so adding it here would violate an acceptance criterion — this belongs in a proposal to triage, not in this round.
**Approve** at `bf84b19a073219e04c14df264100d5d6d400e443`. Reviewed the whole PR at this head in a detached worktree, against #64's acceptance criteria, then the repo's constraints, then the code. ## Acceptance criteria — all nine met I probed the base and the head side by side over every `auth logout` / `auth status` path and diffed the transcripts. The behavioural delta is exactly the four changes #64 asked for and nothing else: | criterion | result | | --- | --- | | `logout`, `tokenId: null`, no `--local-only` → three facts, exit `0` | met — prints the notice naming credentials-removed, cannot-revoke, still-valid-on-`config.url` + `Settings > Applications`; exit `0` | | `logout --local-only` on that config byte-identical to today | met — `Local credentials removed.\n`, identical to base | | `logout` with non-null `tokenId` unchanged on every path | met — revoked / warned / no-password-skip transcripts are byte-identical base vs head | | `status` no session → exit `1`, `Not authenticated.` on stdout | met | | `status --json` no session → exit `1`, exactly `{"authenticated": false}` | met — base printed the prose line under `--json`; head prints the object | | authenticated `status` still exits `0`, `--json` still raw `/user` | met — the case at `test/cli.test.js` L1039 is unmodified and passes | | no output prints a token value | met — probed with `"token":"SECRET-TOK"`; 0 occurrences across all paths | | diff touches exactly three files | met — `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md` | | `npm test` passes and `ci / test` green on head | met — see below | The `else if (!config.tokenId && !options.localOnly)` placement is the right shape: it hangs off the existing `if`, so it is unreachable whenever `tokenId` is truthy, which is what makes the "unchanged on every path" criterion structurally true rather than incidentally true. It correctly does not attempt or prompt for revocation, including when `-p` is supplied on a supplied-token session. `Closes #64` is correct here — the issue explicitly sanctions it ("a `Closes` is equally correct here since every criterion is pre-merge"), and every criterion is indeed pre-merge. ## What I ran - `npm ci && npm test` in the worktree: **145/145 pass**. - `npm run check:governance`: passes (4 identities resolved, 5 scope rows valid). - **The failure cases actually fail.** Reverting only `src/cli.js` to `2230ca25` and re-running: `not ok 39 (global --config flag…)`, `not ok 40 (auth status reports an absent session…)`, `not ok 41 (auth logout identifies a supplied token…)` — 142/145. The three tests are load-bearing, not decorative. - **Mutation-checked the new assertions.** Four mutants against the fixed source, each caught: (1) `status` exits `1` even when authenticated → caught by the new test *and* by `read commands print the raw API JSON with --json`, which is the specific regression #64's test plan warns the exit-code edit invites; (2) logout prints `Revoked token …` on the null-`tokenId` path → caught; (3) the notice leaks into `--local-only` → caught; (4) the notice collapses to `Removing local credentials.` and drops the URL / where-to-revoke facts → caught. - `git diff --check` clean; `changelog.d/64.md` matches the one-line `- … (#NN).` form of `57.md` and `60.md`. - `ci / test (pull_request)` and `labels / labels (pull_request)` both read **success** on this head (run 1160 / 1161) from the commit-statuses API. The PR body's last checkbox is honestly unchecked because CI was pending at write time; it is green now, so that criterion is satisfied in fact. - `scope:cli` + `scope:packaging` is the right label pair per CONTRIBUTING (`src/` and the changelog fragment). The `--json` payload being a string literal rather than `printJson({...})` is correct, not a shortcut: `printJson` pretty-prints, and the spec demands that exact single-line byte sequence. ## What I could not verify, and what I relied on instead - **The interactive TTY prompt path.** This box has no TTY, so `prompt(\`Password for …\`)` never fires under `spawnSync`; that also means the new test's `assert.doesNotMatch(logout.stdout, /Password for/)` cannot catch a regression that prompts *while still* gated on `input.isTTY`. It does still catch an ungated prompt. I relied on reading: `tokenId` falsy can never enter the branch that contains the prompt at all, so the criterion holds by structure. - **A real remote revocation.** My `--password-file` probe hit `Network error reaching https://forge.test` against the stub host. That path is untouched by this diff, and its base and head transcripts are identical, so identity is what the criterion needs and identity is what I measured — but I did not exercise a successful `deleteToken`. - **CI internals.** I read the commit-statuses API, not the run logs; my own local `npm test` and `check:governance` are the independent evidence. ## Non-blocking nits — builder's discretion, and neither is this PR's to fix 1. `test/cli.test.js` still has **no coverage at all** for the `tokenId`-backed logout branches (revoked / warned / no-password skip). That gap predates this PR and #64 scoped it out, so it is correctly not addressed here; I verified those paths by direct base-vs-head probe instead. Worth a proposal rather than a review demand. 2. README's `stoke auth status` section ("Display the currently authenticated user") documents no exit-code contract, and the `auth logout` section does not mention the supplied-token case. Making the unauthenticated exit code machine-detectable is precisely the kind of thing a scripting reader looks for in the README. #64 caps the diff at three files, so **adding it here would violate an acceptance criterion** — this belongs in a proposal to triage, not in this round.
glm-bot-andresmgsl requested changes 2026-09-04 02:20:00 +00:00
Dismissed
glm-bot-andresmgsl left a comment
Member

Requesting changes for one blocking item — the implementation itself matches the spec exactly.

Blocking

npm test fails on Node 22.12.0, the repo's declared engines floor (CONTRIBUTING: "requires Node.js 22.12.0 or newer"; package.json engines >=22.12.0). Acceptance criterion 9's first clause is unqualified.

  • On this box's Node 22.12.0: 144/145, one failauth logout identifies a supplied token that remains active without changing local-only output, at test/cli.test.js:90 (assert.equal(localOnly.stderr, '')). Reproduced twice, deterministic; the base 2230ca2 is 143/143 green on the same Node, so the regression is pinned to this diff.
  • Mechanism: commander@15.0.0 (the lockfile pin) is ESM; on Node 22.12.0 require(esm) emits a once-per-process ExperimentalWarning to stderr for any command that runs to natural completion. auth logout completes naturally, so the warning lands on stderr and trips the new empty-stderr assertion. (The two stderr === '' assertions in the status test at L53/L58 pass on the floor Node only because the synchronous process.exit(1) fires before the deferred warning flushes — timing luck, not a guarantee.)
  • On Node 24.19.0: 145/145 pass, so CI's floating node:22-bookworm image (currently newer than 22.12) is green — which is why ci / test shows success on the head.

Unblock (builder's choice, one line in an already-touched file): drop the assert.equal(localOnly.stderr, '') at L90, or scope it (assert.doesNotMatch(localOnly.stderr, /error/i)), or pass NODE_NO_WARNINGS=1 in that run's env. Everything else in the assertion can stay.

Verified (against #64's acceptance criteria)

  1. Supplied-token logout message names all three facts (locally removed, stoke did not create / cannot revoke it, still valid on config.url + Settings > Applications), exits 0 — ran it: rc=0, message present, config file deleted.
  2. --local-only output byte-identical (Local credentials removed.\n only) — new branch is guarded by !options.localOnly; asserted exactly and green on Node 24.
  3. Non-null tokenId paths unchanged — new branch requires !config.tokenId, structurally unreachable there; the revocation block is untouched.
  4. No-session auth status exits 1, prints Not authenticated. on stdout — ran it: rc=1, stdout exactly Not authenticated.\n.
  5. No-session --json exits 1 with exactly {"authenticated": false} — asserted byte-exact, green.
  6. Valid session still exits 0 with raw /user JSON — the unmodified read commands print the raw API JSON with --json test covers auth status --json and passes.
  7. No token value printed anywhere in the diff — the new message prints config.url only; the test guards with doesNotMatch on the literal token.
  8. Diff touches exactly src/cli.js, test/cli.test.js, changelog.d/64.md — confirmed via git diff --stat origin/main...HEAD; fragment format matches the existing entries.
  9. ci / test green on the head — verified via the commit status API (run 1160, success, 7m18s). The npm test clause is the blocker above.

The --config routing test was amended (0→1) not deleted — name, intent and Not authenticated assertion intact, exactly as the spec directed. The test-plan's failure cases are all present and meaningful (revocation-claim, password-prompt, local-only-output, authenticated-status regressions).

Could not verify

  • The exact CI image (node:22-bookworm floating tag) — no container runtime here; relied on the commit status API for ci / test = success, plus Node 24.19.0 locally as the proxy for modern-warning-free behavior.
  • Authenticated paths against a live Forgejo — relied on the suite's local-http-server harness (green on Node 24).
  • Fresh npm ci install — reused the main clone's node_modules (commander 15.0.0, matching the lockfile pin) via symlink in the throwaway worktrees.
Requesting changes for one blocking item — the implementation itself matches the spec exactly. ## Blocking **`npm test` fails on Node 22.12.0, the repo's declared engines floor** (CONTRIBUTING: "requires Node.js 22.12.0 or newer"; `package.json` engines `>=22.12.0`). Acceptance criterion 9's first clause is unqualified. - On this box's Node 22.12.0: **144/145, one fail** — `auth logout identifies a supplied token that remains active without changing local-only output`, at `test/cli.test.js:90` (`assert.equal(localOnly.stderr, '')`). Reproduced twice, deterministic; the base `2230ca2` is **143/143 green on the same Node**, so the regression is pinned to this diff. - Mechanism: `commander@15.0.0` (the lockfile pin) is ESM; on Node 22.12.0 `require(esm)` emits a once-per-process ExperimentalWarning to stderr for any command that runs to natural completion. `auth logout` completes naturally, so the warning lands on stderr and trips the new empty-stderr assertion. (The two `stderr === ''` assertions in the status test at L53/L58 pass on the floor Node only because the synchronous `process.exit(1)` fires before the deferred warning flushes — timing luck, not a guarantee.) - On Node 24.19.0: **145/145 pass**, so CI's floating `node:22-bookworm` image (currently newer than 22.12) is green — which is why `ci / test` shows success on the head. Unblock (builder's choice, one line in an already-touched file): drop the `assert.equal(localOnly.stderr, '')` at L90, or scope it (`assert.doesNotMatch(localOnly.stderr, /error/i)`), or pass `NODE_NO_WARNINGS=1` in that run's env. Everything else in the assertion can stay. ## Verified (against #64's acceptance criteria) 1. Supplied-token logout message names all three facts (locally removed, stoke did not create / cannot revoke it, still valid on `config.url` + `Settings > Applications`), exits 0 — ran it: rc=0, message present, config file deleted. 2. `--local-only` output byte-identical (`Local credentials removed.\n` only) — new branch is guarded by `!options.localOnly`; asserted exactly and green on Node 24. 3. Non-null `tokenId` paths unchanged — new branch requires `!config.tokenId`, structurally unreachable there; the revocation block is untouched. 4. No-session `auth status` exits 1, prints `Not authenticated.` on stdout — ran it: rc=1, stdout exactly `Not authenticated.\n`. 5. No-session `--json` exits 1 with exactly `{"authenticated": false}` — asserted byte-exact, green. 6. Valid session still exits 0 with raw `/user` JSON — the unmodified `read commands print the raw API JSON with --json` test covers `auth status --json` and passes. 7. No token value printed anywhere in the diff — the new message prints `config.url` only; the test guards with `doesNotMatch` on the literal token. 8. Diff touches exactly `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md` — confirmed via `git diff --stat origin/main...HEAD`; fragment format matches the existing entries. 9. `ci / test` green on the head — verified via the commit status API (run 1160, success, 7m18s). The `npm test` clause is the blocker above. The `--config` routing test was amended (0→1) not deleted — name, intent and `Not authenticated` assertion intact, exactly as the spec directed. The test-plan's failure cases are all present and meaningful (revocation-claim, password-prompt, local-only-output, authenticated-status regressions). ## Could not verify - The exact CI image (`node:22-bookworm` floating tag) — no container runtime here; relied on the commit status API for `ci / test` = success, plus Node 24.19.0 locally as the proxy for modern-warning-free behavior. - Authenticated paths against a live Forgejo — relied on the suite's local-http-server harness (green on Node 24). - Fresh `npm ci` install — reused the main clone's `node_modules` (commander 15.0.0, matching the lockfile pin) via symlink in the throwaway worktrees.
kimi-bot-andresmgsl approved these changes 2026-09-04 02:24:05 +00:00
Dismissed
kimi-bot-andresmgsl left a comment
Member

Approve. Reviewed the whole PR at head bf84b19a against #64's acceptance criteria, in a detached worktree.

Verification (all run, not read):

  • npm test on the head: 145/145 pass (node v22.23.2, this box's node lives outside PATH).
  • Failure-case probe: the two new tests (auth status reports an absent session…, auth logout identifies a supplied token…) fail 2/2 when run against the pre-change src/cli.js; the tree was restored afterwards. The failure cases actually fail.
  • CI on the head: ci / test SUCCESS, labels / labels SUCCESS (status rollup).

Criteria, point by point:

  • Supplied-token logout (tokenId: null, no --local-only) names all three facts — local removal, stoke cannot revoke a token it did not create, token still valid on config.url with Settings > Applications — and the action returns normally, so exit 0. ✓
  • --local-only output asserted byte-identical (Local credentials removed.\n and nothing else). ✓
  • Non-null tokenId paths untouched (the new branch is a trailing else if after the existing revocation block). ✓
  • No-session auth status exits 1, prints Not authenticated. on stdout; --json prints exactly {"authenticated": false}. ✓
  • Authenticated paths unchanged; the existing session tests pass unmodified — only the one deliberately-edited --config routing test changed, its intent and Not authenticated assertion intact, as the issue specified. ✓
  • No token value printed anywhere in the diff (tests assert it; messages carry only config.url). ✓
  • Diff touches exactly src/cli.js (+8/-2), test/cli.test.js, one changelog.d/64.md fragment in the established style. ✓
  • Conventions: CommonJS, node:test, changelog fragment — all per CONTRIBUTING. No workflow or token-handling surface in this diff.

Could not verify: nothing material. The local run plus green CI on this exact head covers the test-plan floor.

Non-blocking nit (builder's discretion): the new logout line prints "Removing local credentials." before clearConfig() and "Local credentials removed." after — mildly redundant phrasing, but it matches the spec's "before clearConfig()" instruction and reads fine.

Approve. Reviewed the whole PR at head bf84b19a against #64's acceptance criteria, in a detached worktree. Verification (all run, not read): - `npm test` on the head: 145/145 pass (node v22.23.2, this box's node lives outside PATH). - Failure-case probe: the two new tests (`auth status reports an absent session…`, `auth logout identifies a supplied token…`) fail 2/2 when run against the pre-change `src/cli.js`; the tree was restored afterwards. The failure cases actually fail. - CI on the head: `ci / test` SUCCESS, `labels / labels` SUCCESS (status rollup). Criteria, point by point: - Supplied-token logout (`tokenId: null`, no `--local-only`) names all three facts — local removal, stoke cannot revoke a token it did not create, token still valid on `config.url` with `Settings > Applications` — and the action returns normally, so exit 0. ✓ - `--local-only` output asserted byte-identical (`Local credentials removed.\n` and nothing else). ✓ - Non-null `tokenId` paths untouched (the new branch is a trailing `else if` after the existing revocation block). ✓ - No-session `auth status` exits 1, prints `Not authenticated.` on stdout; `--json` prints exactly `{"authenticated": false}`. ✓ - Authenticated paths unchanged; the existing session tests pass unmodified — only the one deliberately-edited `--config` routing test changed, its intent and `Not authenticated` assertion intact, as the issue specified. ✓ - No token value printed anywhere in the diff (tests assert it; messages carry only `config.url`). ✓ - Diff touches exactly `src/cli.js` (+8/-2), `test/cli.test.js`, one `changelog.d/64.md` fragment in the established style. ✓ - Conventions: CommonJS, `node:test`, changelog fragment — all per CONTRIBUTING. No workflow or token-handling surface in this diff. Could not verify: nothing material. The local run plus green CI on this exact head covers the test-plan floor. Non-blocking nit (builder's discretion): the new logout line prints "Removing local credentials." before `clearConfig()` and "Local credentials removed." after — mildly redundant phrasing, but it matches the spec's "before clearConfig()" instruction and reads fine.
codex-bot-andresmgsl changed title from fix: report unauthenticated auth state honestly to WIP: fix: report unauthenticated auth state honestly 2026-09-04 02:25:41 +00:00
Author
Member

🔧 addressing round on head bf84b19a07

Round analysis:

  • GLM blocking — agree: the new localOnly stderr-empty assertion is not portable to the declared Node 22.12.0 floor because Commander’s ESM warning can be emitted there. I will remove that brittle stderr assertion while retaining the byte-exact stdout assertion and the behavioral guards, then run the focused test and full suite at the floor runtime if available.
  • Claude non-blocking test-coverage note — agree, no change in this PR: coverage for the pre-existing tokenId-backed logout branches is outside #64 and adding it would exceed the exact three-file scope.
  • Claude non-blocking README note — agree, no change in this PR: #64 explicitly constrains the diff to three files, so documentation expansion belongs in a separate proposal.
  • Kimi non-blocking duplicate removal wording — agree that it is mildly repetitive, no change: the pre-clear and post-clear messages are intentional and required by the issue’s sequencing/output contract.

I will append and complete the fix-round Worklog items, push the test correction without rewriting history, reply once covering the whole round and verification, then signal the final head while draft and mark ready with no intervening commit.

🔧 addressing round on head bf84b19a073219e04c14df264100d5d6d400e443 Round analysis: - GLM blocking — agree: the new localOnly stderr-empty assertion is not portable to the declared Node 22.12.0 floor because Commander’s ESM warning can be emitted there. I will remove that brittle stderr assertion while retaining the byte-exact stdout assertion and the behavioral guards, then run the focused test and full suite at the floor runtime if available. - Claude non-blocking test-coverage note — agree, no change in this PR: coverage for the pre-existing tokenId-backed logout branches is outside #64 and adding it would exceed the exact three-file scope. - Claude non-blocking README note — agree, no change in this PR: #64 explicitly constrains the diff to three files, so documentation expansion belongs in a separate proposal. - Kimi non-blocking duplicate removal wording — agree that it is mildly repetitive, no change: the pre-clear and post-clear messages are intentional and required by the issue’s sequencing/output contract. I will append and complete the fix-round Worklog items, push the test correction without rewriting history, reply once covering the whole round and verification, then signal the final head while draft and mark ready with no intervening commit.
codex-bot-andresmgsl added 1 commit 2026-09-04 02:29:08 +00:00
test: tolerate Node floor module warning
All checks were successful
labels / labels (pull_request) Successful in 12s
ci / test (pull_request) Successful in 3m14s
1335232002
forgejo-actions added
state:addressing
and removed
state:bots-reviewing
labels 2026-09-04 02:29:24 +00:00
Author
Member

Round answered whole for head bf84b19a073219e04c14df264100d5d6d400e443; fixes are pushed at 1335232002.

  • GLM blocking: removed only the local-only stderr-empty assertion. On Node 22.12.0, the original assertion failed deterministically because Commander’s CommonJS-to-ESM ExperimentalWarning is emitted on stderr; the corrected focused test passes, while its byte-exact stdout assertion, exit status, config deletion, no-prompt, no-revocation-claim, and no-token-leak checks remain.
  • Claude non-blocking tokenId-path coverage note: no change. Those pre-existing paths remain outside #64 and direct coverage would exceed the mandated three-file scope.
  • Claude non-blocking README note: no change. The exact three-file acceptance criterion excludes README work; that belongs in a separate proposal.
  • Kimi non-blocking duplicate wording note: no change. The before-clear warning and after-clear confirmation preserve the required sequencing and output contract.

Verification on the final head: the focused test passes on Node 22.12.0 and Node 22.23.1; the full suite passes 145/145 on both runtimes; npm run check:governance passes; git diff --check passes; the tree is clean and matches the pushed remote head; the diff still contains exactly src/cli.js, test/cli.test.js, and changelog.d/64.md. The current-head CI test is pending, not red; the engine owns waiting for it before requesting the panel.

Round answered whole for head bf84b19a073219e04c14df264100d5d6d400e443; fixes are pushed at 133523200262aaa8f4a47c594a524677ace9b026. - GLM blocking: removed only the local-only stderr-empty assertion. On Node 22.12.0, the original assertion failed deterministically because Commander’s CommonJS-to-ESM ExperimentalWarning is emitted on stderr; the corrected focused test passes, while its byte-exact stdout assertion, exit status, config deletion, no-prompt, no-revocation-claim, and no-token-leak checks remain. - Claude non-blocking tokenId-path coverage note: no change. Those pre-existing paths remain outside #64 and direct coverage would exceed the mandated three-file scope. - Claude non-blocking README note: no change. The exact three-file acceptance criterion excludes README work; that belongs in a separate proposal. - Kimi non-blocking duplicate wording note: no change. The before-clear warning and after-clear confirmation preserve the required sequencing and output contract. Verification on the final head: the focused test passes on Node 22.12.0 and Node 22.23.1; the full suite passes 145/145 on both runtimes; npm run check:governance passes; git diff --check passes; the tree is clean and matches the pushed remote head; the diff still contains exactly src/cli.js, test/cli.test.js, and changelog.d/64.md. The current-head CI test is pending, not red; the engine owns waiting for it before requesting the panel.
Author
Member

📣 round answered at head 1335232002

📣 round answered at head 133523200262aaa8f4a47c594a524677ace9b026
codex-bot-andresmgsl changed title from WIP: fix: report unauthenticated auth state honestly to fix: report unauthenticated auth state honestly 2026-09-04 02:30:18 +00:00
codex-bot-andresmgsl requested review from glm-bot-andresmgsl 2026-09-04 02:35:55 +00:00
codex-bot-andresmgsl requested review from claude-bot-andresmgsl 2026-09-04 02:35:55 +00:00
codex-bot-andresmgsl requested review from kimi-bot-andresmgsl 2026-09-04 02:35:56 +00:00
codex-bot-andresmgsl added the
state:bots-reviewing
label 2026-09-04 02:35:56 +00:00
forgejo-actions removed the
state:addressing
label 2026-09-04 02:36:15 +00:00
glm-bot-andresmgsl approved these changes 2026-09-04 02:40:38 +00:00
glm-bot-andresmgsl left a comment
Member

Approve at 133523200262aaa8f4a47c594a524677ace9b026.

Fix round for my request-changes at bf84b19a. The blocking item is resolved exactly as offered, and the whole PR re-reviewed at this head against #64.

The blocker, resolved

Commit 1335232 removes only the assert.equal(localOnly.stderr, '') line at test/cli.test.js that I flagged — the byte-exact stdout assertion, exit status, config-deletion, no-prompt, no-revocation-claim and no-token-leak checks all remain; src/cli.js is untouched since my last round. On this box's default Node 22.12.0 — the exact floor the last round failed on — the full suite now passes 145/145. Also 145/145 on Node 24.19.0.

Verification (all run at this head)

  • npm test (via node --test) on Node 22.12.0 and Node 24.19.0: 145/145 both. commander in the reused node_modules matches the lockfile pin (15.0.0).
  • Failure cases still fail. With only src/cli.js reverted to base 2230ca2, the two new tests (auth status reports an absent session…, auth logout identifies a supplied token…) both go red; tree restored after.
  • Live probes: auth logout on a tokenId: null config exits 0 and names all three facts (local removal, stoke did not create / cannot revoke, still valid on config.url + Settings > Applications); zero occurrences of the token literal across stdout and stderr; --local-only prints exactly Local credentials removed.; no-session auth status exits 1 with Not authenticated. on stdout; --json exits 1 with exactly {"authenticated": false}.
  • Non-null tokenId paths unchanged: structurally guaranteed — the new branch is else if (!config.tokenId && !options.localOnly), unreachable when tokenId is truthy; the revocation block is unmodified.
  • CI: ci / test and labels / labels both read success on 1335232 (commit-statuses API, runs 1172/1173). The PR body's last checkbox was honestly unchecked at write time because CI was pending; it is green in fact now.
  • Diff touches exactly src/cli.js, test/cli.test.js, changelog.d/64.md; git diff --check clean; the --config routing test remains amended-in-place (0→1), not deleted, per the spec.

Could not verify

  • CI run internals (no container runtime here) — relied on the commit-statuses API plus my own runs on both Node versions, one of which is the declared engines floor.
  • Interactive TTY prompt path — no TTY on this box; relied on structure: tokenId falsy cannot reach the branch containing the prompt, and the test still guards against an ungated prompt.
  • Authenticated paths against a live Forgejo — relied on the suite's local-http-server harness (green on both runtimes).

Non-blocking (unchanged from last round, builder's discretion)

The tokenId-backed logout coverage gap and the README exit-code documentation both remain out of this PR by #64's three-file cap — proposals, not review demands.

**Approve** at `133523200262aaa8f4a47c594a524677ace9b026`. Fix round for my request-changes at `bf84b19a`. The blocking item is resolved exactly as offered, and the whole PR re-reviewed at this head against #64. ## The blocker, resolved Commit `1335232` removes only the `assert.equal(localOnly.stderr, '')` line at `test/cli.test.js` that I flagged — the byte-exact stdout assertion, exit status, config-deletion, no-prompt, no-revocation-claim and no-token-leak checks all remain; `src/cli.js` is untouched since my last round. On this box's default Node **22.12.0 — the exact floor the last round failed on** — the full suite now passes **145/145**. Also 145/145 on Node 24.19.0. ## Verification (all run at this head) - `npm test` (via `node --test`) on Node 22.12.0 and Node 24.19.0: 145/145 both. `commander` in the reused `node_modules` matches the lockfile pin (15.0.0). - **Failure cases still fail.** With only `src/cli.js` reverted to base `2230ca2`, the two new tests (`auth status reports an absent session…`, `auth logout identifies a supplied token…`) both go red; tree restored after. - **Live probes:** `auth logout` on a `tokenId: null` config exits `0` and names all three facts (local removal, stoke did not create / cannot revoke, still valid on `config.url` + `Settings > Applications`); zero occurrences of the token literal across stdout and stderr; `--local-only` prints exactly `Local credentials removed.`; no-session `auth status` exits `1` with `Not authenticated.` on stdout; `--json` exits `1` with exactly `{"authenticated": false}`. - **Non-null `tokenId` paths unchanged:** structurally guaranteed — the new branch is `else if (!config.tokenId && !options.localOnly)`, unreachable when `tokenId` is truthy; the revocation block is unmodified. - **CI:** `ci / test` and `labels / labels` both read **success** on `1335232` (commit-statuses API, runs 1172/1173). The PR body's last checkbox was honestly unchecked at write time because CI was pending; it is green in fact now. - Diff touches exactly `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md`; `git diff --check` clean; the `--config` routing test remains amended-in-place (0→1), not deleted, per the spec. ## Could not verify - CI run internals (no container runtime here) — relied on the commit-statuses API plus my own runs on both Node versions, one of which is the declared engines floor. - Interactive TTY prompt path — no TTY on this box; relied on structure: `tokenId` falsy cannot reach the branch containing the prompt, and the test still guards against an ungated prompt. - Authenticated paths against a live Forgejo — relied on the suite's local-http-server harness (green on both runtimes). ## Non-blocking (unchanged from last round, builder's discretion) The tokenId-backed logout coverage gap and the README exit-code documentation both remain out of this PR by #64's three-file cap — proposals, not review demands.
claude-bot-andresmgsl approved these changes 2026-09-04 02:43:35 +00:00
claude-bot-andresmgsl left a comment
Member

Approve at 133523200262aaa8f4a47c594a524677ace9b026.

Whole PR re-reviewed at this head in a detached worktree with npm ci. GLM's blocking item is genuinely fixed, and I confirmed both the failure and the mechanism at the declared floor rather than taking the fix on trust.

The blocker, reproduced and explained

At engines floor Node 22.12.0, commander@15 is "type": "module", so require('commander') from CommonJS emits an ExperimentalWarning on stderr. It does not appear on every invocation: process.emitWarning defers to nextTick, so any action that calls process.exit() synchronously exits before the warning is flushed. That is exactly why the two stderr === '' assertions in the new auth status test passed at bf84b19a while auth logout --local-only — which returns normally and lets the process drain — failed. One failing test, matching GLM's 144/145. Measured on my box:

$ /tmp/node-v22.12.0/bin/node src/cli.js auth logout --local-only   # stderr: ExperimentalWarning ...
$ /tmp/node-v22.12.0/bin/node src/cli.js auth status                # stderr: (empty)

Removing that one assertion is the right scope: the assertion was testing the runtime, not the code.

Acceptance criteria — all nine met

Verified by a base-vs-head behavioural probe across every auth logout / auth status path (tokenId: null and non-null, with and without --local-only; no-session status text and --json), diffed with the ExperimentalWarning lines stripped. Exactly three deltas, all intended:

  1. Supplied-token logout — prints all three facts and exits 0.
  2. --local-only — stdout byte-identical to base on both tokenId values.
  3. Non-null tokenId — no-password skip path byte-identical; the new else if (!config.tokenId && ...) is structurally unreachable when tokenId is set.
  4. auth status no session — exits 1, still Not authenticated. on stdout.
  5. --json no session — exits 1, prints exactly {"authenticated": false}.
  6. Authenticated status — exits 0; the unmodified mock-server case at test/cli.test.js still asserts the raw /user object.
  7. No token printed — probes seeded a sentinel token value; zero occurrences in any output.
  8. Three-file diffsrc/cli.js, test/cli.test.js, changelog.d/64.md; git diff --check clean. The only removed test line is the mandated --config status 01; name and /Not authenticated/ assertion intact, as the issue's test plan requires.
  9. npm test and CI — 145/145 on Node 22.12.0 and on v22.23.2; ci / test success on this head (run 1172), labels / labels success.

Tests actually fail

Against base src/cli.js with head tests, tests 4, 5 and 6 fail on both runtimes (49/52). Mutation-checked the surviving assertions: 7/7 caught — authenticated status exiting 1, the notice leaking into --local-only, the notice on stderr instead of stdout, each of the three facts dropped, the token interpolated into the notice, and --json exiting 0.

I also checked the hazard the process.exit(1) introduces: console.log immediately followed by process.exit() can truncate on a pipe. It does not here — stdout arrives intact through a pipe, a file redirect, and a deliberately slow reader.

Non-blocking nit — one mutant regressed

Deleting the assertion outright cost a little coverage that a narrower assertion would have kept. This mutant was caught at bf84b19a and now survives 52/52:

} else if (!config.tokenId) {
  (options.localOnly ? console.error : console.log)(`Removing local credentials. …`);

Criterion 2 says --local-only output is byte-identical; the stdout half is asserted byte-exact, the stderr half is now unasserted. A portable replacement is one line and does not touch the warning:

assert.doesNotMatch(localOnly.stderr, /did not create this token/);

Your discretion — the implementation is correct today and I verified the behaviour directly, so this rides the approval rather than blocking it.

What I could not verify, and what I relied on instead

  • The revoked and warned sub-paths of criterion 3. Both need an account password and a live forge that will accept deleteToken; I did not construct one. I verified them by reading: the new branch is guarded on !config.tokenId, so with a non-null tokenId control cannot reach it, and the if (config.tokenId && !options.localOnly) block is untouched by this diff. The no-password skip path I did execute, byte-identical to base.
  • CI does not exercise the engines floor. .forgejo/workflows/ci.yml runs node:22-bookworm, i.e. latest 22.x, which is why GLM's finding was invisible to a green ci / test. I ran the floor locally with a downloaded 22.12.0 build instead. Not this PR's problem and not a request-changes — but the gap is real, and if anyone wants CI to cover the declared floor that is a proposal, not a review round.
  • My earlier round's two non-blocking notes (tokenId-path coverage, README) were answered with a reasoned no-change on three-file-scope grounds. I agree; both belong in separate proposals.
**Approve** at `133523200262aaa8f4a47c594a524677ace9b026`. Whole PR re-reviewed at this head in a detached worktree with `npm ci`. GLM's blocking item is genuinely fixed, and I confirmed both the failure and the mechanism at the declared floor rather than taking the fix on trust. ## The blocker, reproduced and explained At `engines` floor Node **22.12.0**, `commander@15` is `"type": "module"`, so `require('commander')` from CommonJS emits an `ExperimentalWarning` on stderr. It does not appear on every invocation: `process.emitWarning` defers to `nextTick`, so any action that calls `process.exit()` synchronously exits before the warning is flushed. That is exactly why the two `stderr === ''` assertions in the new `auth status` test passed at `bf84b19a` while `auth logout --local-only` — which returns normally and lets the process drain — failed. One failing test, matching GLM's 144/145. Measured on my box: ``` $ /tmp/node-v22.12.0/bin/node src/cli.js auth logout --local-only # stderr: ExperimentalWarning ... $ /tmp/node-v22.12.0/bin/node src/cli.js auth status # stderr: (empty) ``` Removing that one assertion is the right scope: the assertion was testing the runtime, not the code. ## Acceptance criteria — all nine met Verified by a base-vs-head behavioural probe across every `auth logout` / `auth status` path (`tokenId: null` and non-null, with and without `--local-only`; no-session status text and `--json`), diffed with the ExperimentalWarning lines stripped. Exactly three deltas, all intended: 1. **Supplied-token logout** — prints all three facts and exits `0`. ✅ 2. **`--local-only`** — stdout byte-identical to base on both `tokenId` values. ✅ 3. **Non-null `tokenId`** — no-password skip path byte-identical; the new `else if (!config.tokenId && ...)` is structurally unreachable when `tokenId` is set. ✅ 4. **`auth status` no session** — exits `1`, still `Not authenticated.` on stdout. ✅ 5. **`--json` no session** — exits `1`, prints exactly `{"authenticated": false}`. ✅ 6. **Authenticated `status`** — exits `0`; the unmodified mock-server case at `test/cli.test.js` still asserts the raw `/user` object. ✅ 7. **No token printed** — probes seeded a sentinel token value; zero occurrences in any output. ✅ 8. **Three-file diff** — `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md`; `git diff --check` clean. The only removed test line is the mandated `--config` status `0`→`1`; name and `/Not authenticated/` assertion intact, as the issue's test plan requires. ✅ 9. **`npm test` and CI** — 145/145 on Node **22.12.0** and on **v22.23.2**; `ci / test` **success** on this head (run 1172), `labels / labels` success. ✅ ## Tests actually fail Against base `src/cli.js` with head tests, tests 4, 5 and 6 fail on both runtimes (49/52). Mutation-checked the surviving assertions: 7/7 caught — authenticated status exiting `1`, the notice leaking into `--local-only`, the notice on stderr instead of stdout, each of the three facts dropped, the token interpolated into the notice, and `--json` exiting `0`. I also checked the hazard the `process.exit(1)` introduces: `console.log` immediately followed by `process.exit()` can truncate on a pipe. It does not here — stdout arrives intact through a pipe, a file redirect, and a deliberately slow reader. ## Non-blocking nit — one mutant regressed Deleting the assertion outright cost a little coverage that a narrower assertion would have kept. This mutant was caught at `bf84b19a` and now survives 52/52: ```js } else if (!config.tokenId) { (options.localOnly ? console.error : console.log)(`Removing local credentials. …`); ``` Criterion 2 says `--local-only` output is byte-identical; the stdout half is asserted byte-exact, the stderr half is now unasserted. A portable replacement is one line and does not touch the warning: ```js assert.doesNotMatch(localOnly.stderr, /did not create this token/); ``` Your discretion — the implementation is correct today and I verified the behaviour directly, so this rides the approval rather than blocking it. ## What I could not verify, and what I relied on instead - **The revoked and warned sub-paths of criterion 3.** Both need an account password and a live forge that will accept `deleteToken`; I did not construct one. I verified them by reading: the new branch is guarded on `!config.tokenId`, so with a non-null `tokenId` control cannot reach it, and the `if (config.tokenId && !options.localOnly)` block is untouched by this diff. The no-password skip path I did execute, byte-identical to base. - **CI does not exercise the `engines` floor.** `.forgejo/workflows/ci.yml` runs `node:22-bookworm`, i.e. latest 22.x, which is why GLM's finding was invisible to a green `ci / test`. I ran the floor locally with a downloaded 22.12.0 build instead. Not this PR's problem and not a request-changes — but the gap is real, and if anyone wants CI to cover the declared floor that is a proposal, not a review round. - My earlier round's two non-blocking notes (`tokenId`-path coverage, README) were answered with a reasoned no-change on three-file-scope grounds. I agree; both belong in separate proposals.
kimi-bot-andresmgsl approved these changes 2026-09-04 03:11:44 +00:00
kimi-bot-andresmgsl left a comment
Member

Approve at 133523200262aaa8f4a47c594a524677ace9b026.

Fresh full review of the whole PR at this head (detached worktree, npm ci), re-requested after my REQUEST_REVIEW at 02:35:56Z. The fix round (bf84b19a1335232) removes exactly the one line GLM blocked on — the localOnly.stderr === '' assertion — and nothing else.

Acceptance criteria — all nine met, verified by execution

  • logout, tokenId: null, no --local-only: prints one line naming all three facts (local credentials removed; stoke did not create the token and cannot revoke it; still valid on config.url with Settings > Applications), then Local credentials removed., exit 0. Probed directly.
  • logout --local-only: stdout byte-identical to base (cmp against 2230ca2Local credentials removed.\n), exit 0.
  • logout, non-null tokenId: the no-password skip path is byte-identical to base (cmp). The revoked and warned sub-paths I verified by reading — the new branch is guarded on !config.tokenId, so a non-null id cannot reach it, and the if (config.tokenId && !options.localOnly) block is untouched by this diff. Both would need an account password and a live forge accepting deleteToken; I did not construct one.
  • status no session: exit 1, Not authenticated. on stdout, stderr empty. Probed.
  • status --json no session: exit 1, stdout exactly {"authenticated": false}\n. Probed.
  • Authenticated status still exits 0, --json still the raw /user object: the existing L989-area case passes unmodified inside the full suite.
  • No token value printed anywhere: grep over every probe transcript found zero occurrences, and the new logout test asserts doesNotMatch on the token.
  • Diff touches exactly src/cli.js, test/cli.test.js, changelog.d/64.md. Confirmed via git diff --stat against the merge base.
  • npm test: 145/145 on node v22.17.0 and 145/145 on the declared floor v22.12.0 (I downloaded the 22.12.0 build and ran the suite there). CI green on this head (ci / test success 02:32, labels success).

Failure cases actually fail

Ran the head's test/cli.test.js against the base tree (2230ca2): the amended --config routing test and both new tests fail there (not ok 4, 5, 6). The new behaviour is load-bearing, not vacuous.

On the fix round itself

GLM's block was real, and the removal is the right fix: on the v22.12.0 floor, commander loads as ESM and node prints an ExperimentalWarning to stderr on every invocation — I reproduced it. The old localOnly.stderr === '' assertion could not pass at the floor, and criterion 2 only claims stdout byte-identity, which I verified directly. The cost is that stderr on the --local-only path is now unasserted; Claude's suggested portable replacement (assert.doesNotMatch(localOnly.stderr, /did not create this token/)) is a one-line nit that rides this approval at the builder's discretion.

What I could not verify, and what I relied on instead

  • The revoked / warned sub-paths of criterion 3 (password + live forge needed): verified by code reading and the guard structure, as above.
  • CI does not exercise the declared Node floor (workflow runs node:22-bookworm); I covered the floor locally instead — same caveat as last round, a proposal-level gap, not this PR's.
**Approve** at `133523200262aaa8f4a47c594a524677ace9b026`. Fresh full review of the whole PR at this head (detached worktree, `npm ci`), re-requested after my REQUEST_REVIEW at 02:35:56Z. The fix round (bf84b19a → 1335232) removes exactly the one line GLM blocked on — the `localOnly.stderr === ''` assertion — and nothing else. ## Acceptance criteria — all nine met, verified by execution - `logout`, `tokenId: null`, no `--local-only`: prints one line naming all three facts (local credentials removed; stoke did not create the token and cannot revoke it; still valid on `config.url` with `Settings > Applications`), then `Local credentials removed.`, exit `0`. Probed directly. - `logout --local-only`: stdout byte-identical to base (`cmp` against `2230ca2` — `Local credentials removed.\n`), exit `0`. - `logout`, non-null `tokenId`: the no-password skip path is byte-identical to base (`cmp`). The revoked and warned sub-paths I verified by reading — the new branch is guarded on `!config.tokenId`, so a non-null id cannot reach it, and the `if (config.tokenId && !options.localOnly)` block is untouched by this diff. Both would need an account password and a live forge accepting `deleteToken`; I did not construct one. - `status` no session: exit `1`, `Not authenticated.` on stdout, stderr empty. Probed. - `status --json` no session: exit `1`, stdout exactly `{"authenticated": false}\n`. Probed. - Authenticated `status` still exits `0`, `--json` still the raw `/user` object: the existing L989-area case passes unmodified inside the full suite. - No token value printed anywhere: grep over every probe transcript found zero occurrences, and the new logout test asserts `doesNotMatch` on the token. - Diff touches exactly `src/cli.js`, `test/cli.test.js`, `changelog.d/64.md`. Confirmed via `git diff --stat` against the merge base. - `npm test`: 145/145 on node v22.17.0 and 145/145 on the declared floor v22.12.0 (I downloaded the 22.12.0 build and ran the suite there). CI green on this head (`ci / test` success 02:32, `labels` success). ## Failure cases actually fail Ran the head's `test/cli.test.js` against the base tree (`2230ca2`): the amended `--config` routing test and both new tests fail there (`not ok` 4, 5, 6). The new behaviour is load-bearing, not vacuous. ## On the fix round itself GLM's block was real, and the removal is the right fix: on the v22.12.0 floor, `commander` loads as ESM and node prints an `ExperimentalWarning` to stderr on every invocation — I reproduced it. The old `localOnly.stderr === ''` assertion could not pass at the floor, and criterion 2 only claims stdout byte-identity, which I verified directly. The cost is that stderr on the `--local-only` path is now unasserted; Claude's suggested portable replacement (`assert.doesNotMatch(localOnly.stderr, /did not create this token/)`) is a one-line nit that rides this approval at the builder's discretion. ## What I could not verify, and what I relied on instead - The revoked / warned sub-paths of criterion 3 (password + live forge needed): verified by code reading and the guard structure, as above. - CI does not exercise the declared Node floor (workflow runs `node:22-bookworm`); I covered the floor locally instead — same caveat as last round, a proposal-level gap, not this PR's.
codex-bot-andresmgsl requested review from andres 2026-09-04 03:12:50 +00:00
codex-bot-andresmgsl added the
state:needs-human
label 2026-09-04 03:12:50 +00:00
forgejo-actions removed the
state:bots-reviewing
label 2026-09-04 03:13:14 +00:00
andres merged commit c4110e7f7e into main 2026-09-04 06:16:21 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/stoke#66
No description provided.