Skip to content

feat: P2 batch — doctor, links, clone (#3, #7, #23)#43

Merged
KalebCole merged 6 commits intomainfrom
sasha/p2-batch
Mar 25, 2026
Merged

feat: P2 batch — doctor, links, clone (#3, #7, #23)#43
KalebCole merged 6 commits intomainfrom
sasha/p2-batch

Conversation

@KalebCole
Copy link
Copy Markdown
Owner

@KalebCole KalebCole commented Mar 25, 2026

Closes #3, closes #7, closes #23

What

Three P2 features implemented in parallel:

Doctor command (#3)

  • partiful doctor — 5 health checks (config, token, API, env, platform)
  • Table output with ✓/✗ + structured JSON
  • --dry-run, --format json, exit code 1 on failure
  • Cascading skip logic, sensitive field masking

Event links (#7)

  • --link <url> and --link-text <text> on events create and events update
  • Multiple links supported, paired by position
  • Falls back to URL as display text when no link-text provided

Clone events (#23)

  • partiful events clone <eventId> --date <date>
  • Copies title, description, location, capacity, image, theme, etc.
  • Duration preservation (3hr event stays 3hr with new start time)
  • All create flags work as overrides
  • --dry-run support

Testing

  • 79 tests total (12 new), all passing
  • Zero regressions

Summary by CodeRabbit

  • New Features

    • Added doctor command for diagnostics (credentials, token/API checks, platform/runtime reporting, JSON or human-readable output, dry-run)
    • Added --link and --link-text to events create/events update for managing event links
    • Added events clone to duplicate events with overrides (title, date, timezone/theme/effect, visibility, location, capacity, image/poster)
  • Tests

    • Added tests for doctor command behavior and error cases
    • Added integration tests for link options and events clone dry-run behavior

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 14499102-5573-4332-a3b9-87440c2757c4

📥 Commits

Reviewing files that changed from the base of the PR and between 52a19a9 and ee87fb8.

📒 Files selected for processing (1)
  • src/commands/doctor.js

📝 Walkthrough

Walkthrough

Adds a new doctor diagnostic CLI command, extends events with repeatable --link/--link-text options, and implements events clone <eventId>. Includes unit and integration tests covering doctor, link handling for create/update, and clone behavior in dry-run and error cases.

Changes

Cohort / File(s) Summary
CLI Setup
src/cli.js
Registers the new doctor command by importing and invoking registerDoctorCommands(program) during CLI initialization.
Doctor command & tests
src/commands/doctor.js, tests/doctor.test.js
New doctor subcommand: config file JSON validation, required-field checks, token refresh, API connectivity check, environment/platform detection, --dry-run and --format json support, human-readable table to stderr when not JSON, JSON envelope to stdout, non‑zero exit on any failed check. Tests validate dry-run output, missing config behavior, and envelope shape.
Events: links, update tweaks & clone
src/commands/events.js, tests/events-integration.test.js
Adds repeatable --link <url...> and --link-text <text...> to events create and events update (maps missing text to URL). Fixes poster selection in update. Adds events clone <eventId>: fetch source event, compute new dates (preserve duration unless --end-date provided), copy/override fields (title/location/description/capacity/privacy/timezone/theme/effect/visibility), merge/override links and poster (supports upload vs URL), supports dry-run preview of /createEvent payload; integration tests cover link behavior and clone cases.

Sequence Diagrams

sequenceDiagram
    actor User
    participant CLI
    participant Config
    participant TokenService
    participant API

    User->>CLI: partiful doctor
    CLI->>Config: Load credentials file
    Config-->>CLI: config JSON / error

    rect rgba(100,150,100,0.5)
    Note over CLI,Config: Validate JSON and required fields
    CLI->>CLI: Check apiKey, refreshToken, userId
    end

    rect rgba(100,100,150,0.5)
    Note over CLI,TokenService: Refresh access token
    CLI->>TokenService: Exchange refreshToken
    TokenService-->>CLI: new token or error
    end

    rect rgba(150,100,100,0.5)
    Note over CLI,API: Connectivity and basic API call
    CLI->>API: POST /getMyUpcomingEventsForHomePage
    API-->>CLI: response or error
    end

    CLI->>CLI: Collect env/platform info
    CLI-->>User: Emit JSON envelope to stdout (and table to stderr when not json)
Loading
sequenceDiagram
    actor User
    participant CLI
    participant EventsAPI
    participant Storage
    participant ImageService

    User->>CLI: partiful events clone <eventId> --date "2026-04-22T19:00"

    rect rgba(100,150,100,0.5)
    Note over CLI,EventsAPI: Fetch source event
    CLI->>EventsAPI: POST /getEvent { eventId }
    EventsAPI-->>CLI: source event or error
    end

    rect rgba(150,150,100,0.5)
    Note over CLI: Transform and merge overrides
    CLI->>CLI: Parse new startDate, compute endDate (preserve duration unless overridden)
    CLI->>CLI: Merge links, title, location, description, visibility, capacity, etc.
    end

    rect rgba(100,100,150,0.5)
    Note over CLI,ImageService: Poster handling
    alt poster is local file and not dry-run
        CLI->>ImageService: upload image
        ImageService-->>CLI: poster reference
    else use existing poster ID/URL
        CLI->>CLI: reuse poster
    end
    end

    rect rgba(150,100,100,0.5)
    Note over CLI,EventsAPI: Create cloned event
    CLI->>EventsAPI: POST /createEvent (or print payload in dry-run)
    EventsAPI-->>CLI: created event or error
    end

    CLI-->>User: Show payload/result (and exit code)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hop through configs, sniff each key,
I nudge the tokens, hum a glee,
I stitch the links and clone the fête,
I dry-run payloads tidy and neat,
A little rabbit cheers: "All clear — golly gee!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main features added: doctor command, event links, and clone functionality, with clear issue references.
Linked Issues check ✅ Passed All coding requirements from issues #3, #7, and #23 are met: doctor command with 5 checks [#3], --link/--link-text flags for events [#7], and events clone with field overrides [#23].
Out of Scope Changes check ✅ Passed All changes are directly aligned with the three linked issues. The poster-search bug fix in events.js and env-check guarding in doctor.js are scope-appropriate refinements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sasha/p2-batch

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

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
tests/doctor.test.js (1)

11-15: Let runCli() callers override the credentials fixture.

Because PARTIFUL_CREDENTIALS_FILE is assigned after ...env, every test is forced into the missing-file path. Moving the default before ...env makes it possible to add invalid-JSON and happy-path doctor cases with the same helper.

Small cleanup
       env: {
         ...process.env,
-        ...env,
         PARTIFUL_CREDENTIALS_FILE: '/tmp/__nonexistent_partiful_auth__.json',
+        ...env,
       },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/doctor.test.js` around lines 11 - 15, The env spread in the test helper
currently forces PARTIFUL_CREDENTIALS_FILE to always be
'/tmp/__nonexistent_partiful_auth__.json' because it is added after ...env;
update the helper used by runCli() so the default PARTIFUL_CREDENTIALS_FILE is
set before spreading ...env (i.e., place PARTIFUL_CREDENTIALS_FILE:
'/tmp/__nonexistent_partiful_auth__.json' before ...env) allowing callers of
runCli() to override PARTIFUL_CREDENTIALS_FILE in their env argument for
invalid-JSON and happy-path tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/commands/doctor.js`:
- Around line 40-44: The try/catch that parses raw JSON should not return early;
instead when JSON.parse(raw) fails push the invalid config result
(results.push({ name: 'config_file', passed: false, detail: 'Invalid JSON' }))
and set the config variable (or parsed) to null so subsequent checks can run and
report skipped/passed state; remove the immediate return in the catch block so
doctor continues to run environment/platform checks (refer to variables parsed,
raw, config, and results to locate the code to change).

In `@src/commands/events.js`:
- Around line 467-485: Add an explicit opt-in re-invite flag to the clone
command: add .option('--reinvite', 'Re-invite guests from source event')
alongside the existing options on the command('clone') block and then forward
that options.reinvite boolean into the clone handler/path that performs the API
call (the same code that currently reads other overrides) so the clone logic
(e.g., where you call the cloneEvent/createClone function or build the clone
payload) includes a reinvite field when true; leave default behavior unchanged
when options.reinvite is falsy.
- Around line 544-554: The clone logic is resetting many toggle flags to
create-time defaults instead of copying the source event's settings; replace the
hard-coded true values for showHostList, showGuestCount, showGuestList,
showActivityTimestamps, displayInviteButton, allowGuestPhotoUpload,
enableGuestReminders, rsvpsEnabled, allowGuestsToInviteMutuals and
rsvpButtonGlyphType with values derived from the source event (src.<flag>) —
preserving the existing visibility logic (opts.private ? 'private' :
(src.visibility || 'public')) so that opts can still override when intended;
ensure any opt-based overrides remain handled but otherwise inherit each toggle
from src to accurately duplicate the source event.
- Around line 501-516: The dry-run branch currently forces sourceEvent = null
which causes clone previews to lose copied fields; instead, still perform the
read-only fetch with apiRequest when globalOpts.dryRun is true so the preview
can show the real source event (preserving fields like duration). Update the
logic around sourceEvent/apiRequest so that the POST '/getEvent' call with
token, getPayload and globalOpts.verbose runs for dry-run previews (but keep any
non-mutating behavior), and only treat a missing sourceEvent as an error via
jsonError when not in dry-run; keep using src = sourceEvent || {} for downstream
code.

---

Nitpick comments:
In `@tests/doctor.test.js`:
- Around line 11-15: The env spread in the test helper currently forces
PARTIFUL_CREDENTIALS_FILE to always be '/tmp/__nonexistent_partiful_auth__.json'
because it is added after ...env; update the helper used by runCli() so the
default PARTIFUL_CREDENTIALS_FILE is set before spreading ...env (i.e., place
PARTIFUL_CREDENTIALS_FILE: '/tmp/__nonexistent_partiful_auth__.json' before
...env) allowing callers of runCli() to override PARTIFUL_CREDENTIALS_FILE in
their env argument for invalid-JSON and happy-path tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a3bf5dca-0c98-4bdc-b326-43b2aae9d3ab

📥 Commits

Reviewing files that changed from the base of the PR and between 64d832a and 9092900.

📒 Files selected for processing (5)
  • src/cli.js
  • src/commands/doctor.js
  • src/commands/events.js
  • tests/doctor.test.js
  • tests/events-integration.test.js

Comment on lines +40 to +44
try {
parsed = JSON.parse(raw);
} catch {
results.push({ name: 'config_file', passed: false, detail: 'Invalid JSON' });
return results;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Invalid JSON short-circuits the rest of doctor.

Line 44 returns immediately after the config_file failure, so the dependent checks are never marked as skipped and the independent environment / platform checks disappear entirely. Keep config = null and let the later checks report their own skipped/passed state.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/doctor.js` around lines 40 - 44, The try/catch that parses raw
JSON should not return early; instead when JSON.parse(raw) fails push the
invalid config result (results.push({ name: 'config_file', passed: false,
detail: 'Invalid JSON' })) and set the config variable (or parsed) to null so
subsequent checks can run and report skipped/passed state; remove the immediate
return in the catch block so doctor continues to run environment/platform checks
(refer to variables parsed, raw, config, and results to locate the code to
change).

Comment on lines +467 to +485
.command('clone')
.description('Clone an existing event with a new date')
.argument('<eventId>', 'Source event ID')
.requiredOption('--date <date>', 'New event date (required)')
.option('--end-date <endDate>', 'End date/time (overrides duration preservation)')
.option('--title <title>', 'Override title')
.option('--location <location>', 'Override location name')
.option('--address <address>', 'Override street address')
.option('--description <desc>', 'Override description')
.option('--capacity <n>', 'Override guest limit', parseInt)
.option('--private', 'Make event private')
.option('--timezone <tz>', 'Override timezone')
.option('--theme <theme>', 'Override color theme')
.option('--effect <effect>', 'Override visual effect')
.option('--poster <posterId>', 'Override with built-in poster ID')
.option('--poster-search <query>', 'Override with poster search')
.option('--image <path>', 'Override with custom image')
.option('--link <url...>', 'Override links (repeatable)')
.option('--link-text <text...>', 'Display text for links')
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clone still has no opt-in re-invite path.

Lines 467-485 only expose create-style overrides. Issue #23 also calls out guest re-invite control, and without a --reinvite-style flag every clone is forced to drop the guest list.

If helpful, I can sketch a minimal flag/payload shape that preserves the current default while enabling explicit re-invites.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/events.js` around lines 467 - 485, Add an explicit opt-in
re-invite flag to the clone command: add .option('--reinvite', 'Re-invite guests
from source event') alongside the existing options on the command('clone') block
and then forward that options.reinvite boolean into the clone handler/path that
performs the API call (the same code that currently reads other overrides) so
the clone logic (e.g., where you call the cloneEvent/createClone function or
build the clone payload) includes a reinvite field when true; leave default
behavior unchanged when options.reinvite is falsy.

…ch, inherit source toggles, add --reinvite flag
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/commands/doctor.js (1)

40-47: ⚠️ Potential issue | 🟠 Major

Guard parsed before required-field checks.

If JSON parsing fails, parsed is undefined and Line 46 throws while evaluating parsed[f]. That produces secondary error noise and duplicate config_file failures.

🔧 Proposed fix
-      let parsed;
+      let parsed = null;
       try {
         parsed = JSON.parse(raw);
       } catch {
         results.push({ name: 'config_file', passed: false, detail: 'Invalid JSON' });
       }
-      const required = ['apiKey', 'refreshToken', 'userId'];
-      const missing = required.filter(f => !parsed[f]);
-      if (missing.length > 0) {
-        results.push({ name: 'config_file', passed: false, detail: `Missing fields: ${missing.join(', ')}` });
-      } else {
-        config = parsed;
-        results.push({ name: 'config_file', passed: true, detail: displayPath });
+      if (parsed) {
+        const required = ['apiKey', 'refreshToken', 'userId'];
+        const missing = required.filter(f => !parsed[f]);
+        if (missing.length > 0) {
+          results.push({ name: 'config_file', passed: false, detail: `Missing fields: ${missing.join(', ')}` });
+        } else {
+          config = parsed;
+          results.push({ name: 'config_file', passed: true, detail: displayPath });
+        }
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/doctor.js` around lines 40 - 47, The JSON parse error handler
can leave parsed undefined, causing the required-field check (the required array
and the missing = required.filter(f => !parsed[f]) logic) to throw; update the
flow in the function that builds results so that after the catch you either skip
the required-field checks or short-circuit (e.g., return or continue) when
parsed is falsy, ensuring you only compute missing when parsed is an object, and
keep pushing the single config_file failure into results rather than letting a
secondary exception occur.
🧹 Nitpick comments (2)
src/commands/events.js (1)

521-522: Timezone parameter has no effect on date parsing.

The tz value is passed to parseDateTime(), but according to the implementation in src/lib/dates.js, the timezone parameter is accepted but never used — all parsing operates in local/system timezone. Users may expect --timezone to affect how --date is interpreted, but it only sets the stored timezone field on the event.

This is a pre-existing limitation, not introduced by this PR, but worth documenting or addressing separately.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/events.js` around lines 521 - 522, The tz argument passed from
src/commands/events.js (tz computed and then passed to parseDateTime) is ignored
because parseDateTime in src/lib/dates.js accepts but doesn't use the timezone
parameter; update parseDateTime to apply the timezone parameter when parsing
(e.g., use a timezone-aware parser like luxon/DateTime.fromISO / fromFormat with
the zone option or moment.tz) so that parseDateTime(dateString, timezone)
interprets the input in the provided zone, and ensure tests for parseDateTime
and any callers (including the events command) validate that passing tz changes
the resulting Date/time and stored timezone field accordingly.
tests/doctor.test.js (1)

37-47: Add an invalid-JSON config regression test.

The suite validates missing-file behavior, but it doesn’t cover a malformed credentials file (doctor requirement explicitly includes invalid JSON). Adding this case would protect the config parsing branch and skip-chain behavior.

✅ Suggested test case
+  it('invalid config JSON marks config_file failed and continues envelope output', () => {
+    const badPath = '/tmp/__partiful_bad_auth__.json';
+    require('fs').writeFileSync(badPath, '{not-json', 'utf8');
+    const { stdout, exitCode } = runCli(['doctor'], { PARTIFUL_CREDENTIALS_FILE: badPath });
+    expect(exitCode).not.toBe(0);
+    const parsed = JSON.parse(stdout.trim());
+    expect(parsed.status).toBe('success');
+    const configCheck = parsed.data.checks.find(c => c.name === 'config_file');
+    expect(configCheck?.passed).toBe(false);
+  });

Also applies to: 49-61

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/doctor.test.js` around lines 37 - 47, Add a new test in
tests/doctor.test.js (alongside the existing "missing config file produces
failed config_file check") that writes an intentionally malformed JSON
credentials/config file at the same path the CLI expects, invokes
runCli(['doctor']), then asserts the CLI returns a non-zero exitCode, the parsed
JSON output has status 'success', contains a 'config_file' check (find via
parsed.data.checks.find(c => c.name === 'config_file')), that this check.passed
is false, and parsed.data.allPassed is false; ensure the test cleans up the
malformed file after running so it doesn't affect other tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/commands/doctor.js`:
- Around line 95-101: The unguarded read/parse of package.json using pkgPath and
pkg can throw and abort the whole doctor run; wrap the package.json read +
JSON.parse in a try/catch around the logic that builds the environment result
(the block that computes pkg and calls results.push with name: 'environment'),
and on error push an environment check with passed: false (or passed: true if
you prefer non-fatal) and include the caught error.message in detail so the
command records the failure instead of throwing; ensure normal success still
pushes CLI version and Node version when parse succeeds.

In `@src/commands/events.js`:
- Line 486: The --reinvite <statuses> option is declared but unused; update the
clone handler in src/commands/events.js to check opts.reinvite, parse the CSV
string into a Set of uppercased statuses, and after fetching the event's guests
filter guests whose status is in that set and call the same
invitation/re-invitation code path used elsewhere in this file (use the existing
invite/send-invite function used for initial invites) for each matched guest; if
you prefer not to implement, remove the .option('--reinvite <statuses>')
declaration to avoid a no-op flag.
- Around line 611-618: The update command is incorrectly accessing a
non-existent .poster property on the searchPosters result; change the block that
handles opts.posterSearch so it uses the poster object directly (i.e., pass
results[0] to buildPosterImage and assign the returned value to event.image)
rather than trying to read results[0].poster—update the code around
searchPosters, results[0], buildPosterImage and event.image to match the
create/clone command behavior.

---

Duplicate comments:
In `@src/commands/doctor.js`:
- Around line 40-47: The JSON parse error handler can leave parsed undefined,
causing the required-field check (the required array and the missing =
required.filter(f => !parsed[f]) logic) to throw; update the flow in the
function that builds results so that after the catch you either skip the
required-field checks or short-circuit (e.g., return or continue) when parsed is
falsy, ensuring you only compute missing when parsed is an object, and keep
pushing the single config_file failure into results rather than letting a
secondary exception occur.

---

Nitpick comments:
In `@src/commands/events.js`:
- Around line 521-522: The tz argument passed from src/commands/events.js (tz
computed and then passed to parseDateTime) is ignored because parseDateTime in
src/lib/dates.js accepts but doesn't use the timezone parameter; update
parseDateTime to apply the timezone parameter when parsing (e.g., use a
timezone-aware parser like luxon/DateTime.fromISO / fromFormat with the zone
option or moment.tz) so that parseDateTime(dateString, timezone) interprets the
input in the provided zone, and ensure tests for parseDateTime and any callers
(including the events command) validate that passing tz changes the resulting
Date/time and stored timezone field accordingly.

In `@tests/doctor.test.js`:
- Around line 37-47: Add a new test in tests/doctor.test.js (alongside the
existing "missing config file produces failed config_file check") that writes an
intentionally malformed JSON credentials/config file at the same path the CLI
expects, invokes runCli(['doctor']), then asserts the CLI returns a non-zero
exitCode, the parsed JSON output has status 'success', contains a 'config_file'
check (find via parsed.data.checks.find(c => c.name === 'config_file')), that
this check.passed is false, and parsed.data.allPassed is false; ensure the test
cleans up the malformed file after running so it doesn't affect other tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b18cc6eb-d463-4425-8f1d-1a8d0db0f38f

📥 Commits

Reviewing files that changed from the base of the PR and between 9092900 and 95c9338.

📒 Files selected for processing (3)
  • src/commands/doctor.js
  • src/commands/events.js
  • tests/doctor.test.js

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/commands/doctor.js (1)

40-52: ⚠️ Potential issue | 🔴 Critical

Invalid JSON still crashes subsequent field checks.

When JSON.parse(raw) throws (line 41), parsed remains undefined. Line 46 then attempts parsed[f], which throws a TypeError, short-circuiting the entire runChecks() flow. The outer catch at line 54 will catch it, but the result detail will be misleading and independent checks (environment, platform) won't run properly.

Guard against undefined before accessing parsed:

🐛 Proposed fix
       let parsed;
       try {
         parsed = JSON.parse(raw);
       } catch {
         results.push({ name: 'config_file', passed: false, detail: 'Invalid JSON' });
+        parsed = null;
       }
-      const required = ['apiKey', 'refreshToken', 'userId'];
-      const missing = required.filter(f => !parsed[f]);
-      if (missing.length > 0) {
-        results.push({ name: 'config_file', passed: false, detail: `Missing fields: ${missing.join(', ')}` });
-      } else {
-        config = parsed;
-        results.push({ name: 'config_file', passed: true, detail: displayPath });
+      if (parsed) {
+        const required = ['apiKey', 'refreshToken', 'userId'];
+        const missing = required.filter(f => !parsed[f]);
+        if (missing.length > 0) {
+          results.push({ name: 'config_file', passed: false, detail: `Missing fields: ${missing.join(', ')}` });
+        } else {
+          config = parsed;
+          results.push({ name: 'config_file', passed: true, detail: displayPath });
+        }
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/doctor.js` around lines 40 - 52, The JSON parse failure leaves
parsed undefined and later code accesses parsed[f], causing a TypeError; guard
the subsequent required-field checks by only running the required/missing logic
when parsed is defined—wrap the const required / const missing / if
(missing.length > 0) ... else ... block in an if (parsed) { ... } (or
return/continue after pushing the 'Invalid JSON' result) so that when
JSON.parse(raw) fails you skip field checks and avoid crashing runChecks();
refer to the parsed variable and the missing/required logic in
src/commands/doctor.js.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/commands/doctor.js`:
- Around line 21-25: The file defines an unused helper function mask(value,
visibleEnd = 4) that is dead code; either remove this function entirely or wire
it up where sensitive fields (e.g., apiKey, refreshToken) are printed. To fix,
delete the mask function definition from src/commands/doctor.js (and any related
unused imports) if you don't need masking, or apply mask(...) when formatting
any sensitive values before logging/output (search for places that would print
apiKey/refreshToken and call mask there) to ensure the helper is actually used.

---

Duplicate comments:
In `@src/commands/doctor.js`:
- Around line 40-52: The JSON parse failure leaves parsed undefined and later
code accesses parsed[f], causing a TypeError; guard the subsequent
required-field checks by only running the required/missing logic when parsed is
defined—wrap the const required / const missing / if (missing.length > 0) ...
else ... block in an if (parsed) { ... } (or return/continue after pushing the
'Invalid JSON' result) so that when JSON.parse(raw) fails you skip field checks
and avoid crashing runChecks(); refer to the parsed variable and the
missing/required logic in src/commands/doctor.js.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 83830573-defe-496e-863c-27a8ad0003d8

📥 Commits

Reviewing files that changed from the base of the PR and between 95c9338 and 52a19a9.

📒 Files selected for processing (2)
  • src/commands/doctor.js
  • src/commands/events.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/commands/events.js

@KalebCole KalebCole merged commit d658eba into main Mar 25, 2026
1 check was pending
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.

[P2] Clone/duplicate events [P2] Add links in event description [P2] Doctor command for diagnostics

1 participant