Skip to content

Pre-publish review of the 2026-09-01 main changes: eight fixes before v3.0.0 - #143

Merged
ElliotDrel merged 8 commits into
mainfrom
t3code/review-main-changes-npm-readiness
Sep 2, 2026
Merged

ElliotDrel merged 8 commits into
mainfrom
t3code/review-main-changes-npm-readiness

Conversation

@ElliotDrel

Copy link
Copy Markdown
Collaborator

Pre-publish review of everything merged to main on 2026-09-01 (06f4ef0..a957677: #139, 73ca178, #140), with fixes for what the review found. Seven commits, one finding each, every fix has a test that was mutation-checked.

Findings fixed

Severity Finding Commit
Blocker setup and doctor could not finish on any machine with Codex or Claude Code installed. A "not found" CLI failure was mapped to unknown, and the Claude Code probe used -s user --json, which no claude version accepts. CI never saw it because CI has neither client. b0d7aa2
High doctor reported every README-documented registration (bare bin, npx -y google-tools-mcp, clone path) as "entry differs from recommended configuration", exit 1. Now configured + note when the entry launches this package; Codex without CODEX_MCP_PROTOCOL_VERSION stays a problem and names it. b0d7aa2
High Update check hit the npm registry on every launch: readFile/writeFile/mkdir had no defaults, so the cache never read or wrote. 40dac11
High help tool=X rendered the output-io JSON Schema; 50 of 160 tools showed .default() fields as required. 9cf09dc
Medium Auth latch: an abandoned flow could release a newer latch after logout; a flow running at logout could install its client afterwards; a cold request mid re-auth opened a second consent screen. 1e28c2e
Medium Live harness cleanup: already-deleted files reported as left behind, null raw Drive handle after invalid_grant, blocked outcomes uncounted, no post-cleanup listing, --keep printed no ids, track() double-counted. Plus frozen missions archived, false friction in probe 3, coverage scanner gaps, hand-maintained guard-denied list. d15c944
Low doctor --json printed "args": "[Circular]" for any shared reference. a51eee4
Doc README Step 3 Codex commands omitted --env CODEX_MCP_PROTOCOL_VERSION=2026-07-28. CHANGELOG entries for all of the above. SESSION-STATE rewritten (it said main=73ca178 and #140 open). 8d6ad46

Evaluated and left alone: Sheets read-state seeding in createSpreadsheet/copyFile is request-scoped on HTTP. Neither tool claims the Sheet is mutable afterwards and the guard's HTTP branch already says Sheets edits are stdio-only.

Gates at the head of this branch

  • npm run test:ci: 94 suites, 1381 passed, 2 skipped
  • npm audit --omit=dev: 0
  • npm pack --dry-run: 184 files, no tests/live/scripts leakage
  • every dist/**/*.js imports (181 modules)
  • npm run live-coverage: 29 / 131 / 2, exit 0
  • Live against the real API on 2026-09-02: harness-selftest 3/3, verify-created-resource-tracking 2/2, agent-loop-2-fixes 19 calls 5/5, live-smoke 22/22 with 28/28 trashed and an empty folder after. --keep and live-call --cleanup exercised.

Still open before the tag

🤖 Generated with Claude Code

ElliotDrel and others added 7 commits September 2, 2026 13:19
…gistrations

setup and doctor could not finish on any machine that had Codex or Claude
Code installed. Both clients report a missing registration as a failed
command, and every rejection was mapped to `unknown` without reading it, so
setup stopped at Step 5 and doctor said "unrecognized client entry". The
Claude Code probe (`claude mcp get -s user google --json`) is rejected by
every claude version with `unknown option '-s'`, so it was `unknown`
everywhere. A rejection whose text says "missing" now means missing, and the
Claude Code user-scope entry is read from ~/.claude.json (the file
`claude mcp add -s user` writes), with its `type: 'stdio'` and empty `env`
stripped so a correct entry compares equal to the desired one.

doctor also reported every README-documented registration (bare bin, npx,
clone path) as "entry differs from recommended configuration", because its
recommended entry is the absolute path of the copy running doctor. An entry
that launches this package is now `configured` with a note; Codex without
CODEX_MCP_PROTOCOL_VERSION stays a problem and names the variable.

Co-Authored-By: Claude Code <noreply@anthropic.com>
checkForUpdate took injectable readFile/writeFile/mkdir with no defaults, and
index.js passes none, so in production every cache read threw (swallowed as
"no cache") and every write threw on mkdir (swallowed as "best effort"). The
registry was fetched on every launch and update-check.json never written,
while every test injected fakes and passed. A real-temp-dir test now proves
a second launch inside the TTL makes no network request.

Co-Authored-By: Claude Code <noreply@anthropic.com>
help used Zod's bare toJSONSchema(), whose default is the output schema, so
every .optional().default(x) field came back as required. For 50 of the 160
tools that contradicted tools/list. Now io:'input', draft 2020-12, pinned to
the SDK's conversion for every registered tool.

Co-Authored-By: Claude Code <noreply@anthropic.com>
An abandoned flow could clear a newer latch after logout (identity guard), a
flow running at logout could install its client afterwards (authGeneration
counter, bumped by resetClients; the stale flow throws "Logged out while
authorization was in progress"), and a cold request arriving mid
re-authorization opened a second consent screen (ensureAuth now joins
reauthInFlight). Nine tests; removing each guard fails exactly its test.

Co-Authored-By: Claude Code <noreply@anthropic.com>
… [Circular]

doctor --json printed "args": "[Circular]" for the second client because the
two recommended entries share one args array and `seen` never released a
node. A true cycle still prints [Circular].

Co-Authored-By: Claude Code <noreply@anthropic.com>
One shared cleanup loop (scripts/live-smoke/cleanup.mjs) replaces the two
copies in live-mission and live-smoke, both of which reported an
already-deleted file as left behind (containment check before existence
check) and crashed on a null raw Drive handle after an invalid_grant rebuild.
Blocked outcomes are counted, both runners list the test folder and leftover
drafts after cleanup and fail on anything this run left, --keep prints each
kept id with the live-call --cleanup command, and track() dedupes ids the
runner already registered.

live-coverage credits ctx.createDoc()/createFolder() helpers, accepts any
quote style, skips live/missions/archive/ (loop-1 and loop-2 are frozen
transcripts that hard-fail on fixed code), fails on zero coverage, and
derives the guard-denied set from guard.mjs (MUTATING_VERB exported; the only
guard change). verify-preserve-heading probe 3 states that it expects the
heading gone. live-mission's report `account` was always null. The
created-resource pin test now executes all eight creating tools.

Co-Authored-By: Claude Code <noreply@anthropic.com>
CHANGELOG entries for every fix on this branch; README Step 3 Codex commands
now pass --env CODEX_MCP_PROTOCOL_VERSION=2026-07-28, which the breaking-change
section already said Codex needs; SESSION-STATE reflects main=a957677, the
merged #140, this pass, and the current gate numbers; inventory snapshot
regenerated.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 353bd4df-bda3-428a-a5e9-1db5e4d137c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8d6ad46d19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/live-smoke/cleanup.mjs Outdated
Comment thread scripts/live-smoke/cleanup.mjs
Comment thread dist/setupInspect.js Outdated

@ElliotDrel ElliotDrel left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adversarial Review — issue

The draft cleanup audit also fails open on any getDraft error. listLeftoverDrafts() treats every exception as proof that the draft is gone, but getDraft can fail for auth, network, quota, or malformed-response reasons while the draft still exists. Both runners then see an empty leftoverDrafts array and can exit successfully after an unverifiable cleanup.

Failure scenario: cleanup deletes a draft, then the verification getDraft call hits a transient 401/429/5xx or transport failure. The catch block silently classifies that as “gone,” so a draft that survived cleanup is indistinguishable from a real 404.

Smallest fix: only treat a confirmed not-found response as deleted. Propagate or return an explicit verification failure for every other error, and make both runners fail closed on that state. Add a test where getDraft throws a non-404 error and assert the run cannot report cleanup success.

…ries in doctor

Review findings on #143, all four confirmed:

- listLeftovers returned an empty array when the listing threw, read a
  truncated listing as complete, and only looked one level deep. It now scans
  the whole tree (depth 'all', up to 5000 items) and reports UNVERIFIED with
  the reason when the listing failed, was cut short, or skipped an unreadable
  folder. Both runners fail on that state.
- listLeftoverDrafts treated every getDraft error as "deleted". Only an error
  carrying a real 404 status counts as gone; anything else is reported per
  draft in `unverified` and fails the run.
- launchesThisPackage accepted `google-tools-mcp doctor`, `npx google-tools-mcp
  setup`, and `dist/index.js auth` as server launches. dist/index.js dispatches
  on argv[2], so anything after the target is a subcommand, not the server.
  Env entries selecting an HTTP transport are rejected too.

tests/liveHarnessCleanupAudit.test.js covers each state, including the
non-404 getDraft case, and asserts the runner predicate cannot report success
on an unverified audit. Live harness-selftest re-run: 3/3 trashed, sandbox
0 item(s) after cleanup, exit 0.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@ElliotDrel

Copy link
Copy Markdown
Collaborator Author

Addressed in 66d4e18. listLeftoverDrafts now returns { left, unverified }. Only an error carrying a real 404 status (error.code, error.status, or error.response.status) counts as deleted; a message that merely mentions "404" does not. Every other failure (auth, quota, network, malformed response) lands in unverified as { id, reason }. Both runners print UNVERIFIED draft <id>: <reason> and fail on a non-empty unverified exactly as they do on a non-empty left (live-smoke.mjs exit code and live-mission.mjs runnerFailed).

Tests in tests/liveHarnessCleanupAudit.test.js: a 401 invalid_grant and a socket hang up next to a genuine 404 produce unverified for the two non-404 drafts and nothing for the 404; a 429 from getDraft makes the runner predicate return failed; and the three 404 field variants all count as gone. The same file covers the sandbox listing (throw, truncated, unreadable) that the Codex comments raised.

@ElliotDrel
ElliotDrel merged commit 55d8c65 into main Sep 2, 2026
3 checks passed
@ElliotDrel
ElliotDrel deleted the t3code/review-main-changes-npm-readiness branch September 2, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant