Skip to content

fix(spectrum): report exhausted shared-line capacity - #97

Closed
Henry Zhang (caezium) wants to merge 1 commit into
mainfrom
henry/eng-2161-surface-exhausted-shared-imessage-capacity-in-dashboard-and
Closed

fix(spectrum): report exhausted shared-line capacity#97
Henry Zhang (caezium) wants to merge 1 commit into
mainfrom
henry/eng-2161-surface-exhausted-shared-imessage-capacity-in-dashboard-and

Conversation

@caezium

@caezium Henry Zhang (caezium) commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

  • create a platformless project when --platforms is omitted, in both non-interactive and interactive use
  • keep explicit iMessage project creation successful when the owner phone cannot receive another shared line, while printing an actionable warning
  • warn after successful spectrum platforms enable imessage when no phone is connected
  • fail spectrum users add visibly, with a structured non-zero JSON error when shared capacity is exhausted
  • preserve existing JSON shapes when no warning is present

Behavior

projects create no longer infers iMessage from an omitted --platforms flag. Human output explains that no platform was enabled and shows the follow-up enable command.

When iMessage is explicit and owner enrollment is exhausted, the command returns success for the new project and writes the warning to stderr; --json includes the warning in the successful result. Other platform enables and iMessage disablement do not show the warning.

The recovery copy offers another phone or a dedicated line. It does not suggest deleting a project or contacting support. Regression coverage keeps the warning after project deletion because deletion does not currently restore phone-wide shared-line capacity.

Upstream version

  • @photon-ai/dashboard-api@1.6.12 — unchanged
  • no generated API types were edited by hand; warning response fields are decoded through local runtime shapes

Routes added/removed/changed

  • (none) — this CLI PR adds no server routes
  • consumes the optional warning returned by POST /api/projects
  • consumes the optional warning returned by POST /api/projects/:id/platforms/toggle
  • consumes structured failures returned by POST /api/projects/:id/spectrum/users

Snapshot changes

  • (none)

New runtime dependencies

  • (none)

Testing

  • focused project/Spectrum contract tests — 23 passed
  • repository test directory — 106 passed
  • TypeScript check over the tracked workspace — passed
  • bun run build — passed
  • clean GitHub Check workflow — passed
  • hand-tested against the authenticated exhausted-capacity account before PR creation

The repository root also contains unrelated untracked nested CLI worktrees, so bare local bun test and bun run typecheck discover those directories. The scoped tracked-workspace commands above pass, and the clean PR checkout passes the complete check workflow; those untracked directories are not part of this PR.

Checklist

  • API type changes come from a @photon-ai/dashboard-api version bump, not hand edits (no API type changes)
  • No new runtime deps
  • All snapshot diffs explained above
  • bun run check passes in the clean PR checkout

Dashboard/API companion: photon-hq/dashboard#279

Linear: ENG-2161

Copilot AI review requested due to automatic review settings August 4, 2026 08:42
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Project creation now supports typed warnings and platformless projects. Platform toggles report iMessage connection warnings. Spectrum user enrollment reports structured failures in human-readable and JSON output. Contract tests and mock-server fixtures cover these responses.

Changes

CLI outcome handling

Layer / File(s) Summary
Project creation outcomes
src/lib/types.ts, src/commands/projects.ts, README.md, tests/helpers/mock-server.ts, tests/_setup.ts, tests/contract/projects.contract.test.ts
Project creation uses typed results, reports owner-enrollment warnings, and creates projects without platforms when --platforms is omitted.
Platform toggle warnings
src/lib/types.ts, src/commands/spectrum/platforms.ts, tests/helpers/mock-server.ts, tests/contract/projects.contract.test.ts
Platform enable operations recognize iMessage connection warnings and include them in JSON or stderr output.
Spectrum user failure handling
src/lib/types.ts, src/commands/spectrum/users.ts, tests/helpers/mock-server.ts, tests/contract/projects.contract.test.ts
Spectrum user creation discovers nested structured failures and emits human-readable or JSON errors with exit status handling.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant API
  participant Output
  CLI->>API: Create project or toggle platform
  API-->>CLI: Typed result with optional warning
  CLI->>Output: Write JSON response or human-readable warning
Loading

Possibly related PRs

  • photon-hq/cli#89: Revises the same projects create platform parsing and omission behavior.
  • photon-hq/cli#96: Expands the same platformless project behavior and contract tests.

Suggested reviewers: copilot, lcandy2, invisicat

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately identifies the shared-line capacity warning and failure-handling change, which is a main aspect of the pull request.
Description check ✅ Passed The description covers the required sections, behavior changes, testing, dependencies, routes, snapshots, and checklist items.
✨ 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 henry/eng-2161-surface-exhausted-shared-imessage-capacity-in-dashboard-and

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

Copilot AI 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.

Pull request overview

This PR updates the CLI’s Spectrum-related flows to correctly surface exhausted shared iMessage line capacity and missing phone connection scenarios, while also changing projects create so omitting --platforms creates a platformless project instead of inferring iMessage.

Changes:

  • Adjusts projects create to send an empty platform list when --platforms is omitted, and adds normalized non-blocking warnings for iMessage enrollment issues (including --json support).
  • Adds iMessage-specific warning handling to spectrum platforms enable imessage, preserving the prior JSON shape when no warning is present.
  • Improves spectrum users add failure handling to emit structured non-zero JSON errors (and clearer human output), backed by expanded contract tests and mock-server behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/helpers/mock-server.ts Expands mock server state and routes to simulate project create warnings, platform toggle warnings, deletes, and Spectrum user add failures.
tests/contract/projects.contract.test.ts Adds contract coverage for platformless creation, iMessage enable warnings, and structured Spectrum user add failures.
tests/_setup.ts Forces CI=1 during tests to prevent interactive prompts from hanging test runs.
src/lib/types.ts Introduces local runtime result/warning shapes for project creation, platform toggles, and Spectrum user add failures.
src/commands/spectrum/users.ts Parses structured API failures and emits JSON { error: { code, message } } with exit code 1 when requested.
src/commands/spectrum/platforms.ts Reads optional warning responses when enabling iMessage and prints/returns normalized warning content only when relevant.
src/commands/projects.ts Changes default behavior for omitted --platforms and adds normalized warning mapping/printing for iMessage-related create flows.
README.md Updates command tree to reflect the projects create --platforms interface and “platformless when omitted” behavior.
Suppressed comments (1)

src/commands/projects.ts:70

  • value in PROJECT_CREATE_WARNINGS also matches inherited keys (e.g. "constructor"), which can cause untrusted warning codes to pass validation. Use an own-property check instead.
function isProjectCreateWarningCode(
  value: unknown
): value is ProjectCreateWarningCode {
  return (
    typeof value === "string" && value in PROJECT_CREATE_WARNINGS
  );
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/commands/projects.ts
Comment on lines +60 to +62
function isOwnerWarningStatus(value: unknown): value is OwnerWarningStatus {
return typeof value === "string" && value in OWNER_STATUS_WARNING_CODES;
}

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/helpers/mock-server.ts (1)

434-449: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test the explicit project warning independently.

The mock always emits ownerStatus with warning. The owner-status fallback can therefore satisfy these tests if readProjectCreateWarning stops reading result.warning.

  • tests/helpers/mock-server.ts#L434-L449: Add independent warning state that can return a recognized warning without ownerStatus.
  • tests/contract/projects.contract.test.ts#L156-L220: Add terminal and JSON cases for the warning-only response and assert the normalized local message.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/helpers/mock-server.ts` around lines 434 - 449, Add independent warning
state in tests/helpers/mock-server.ts around the project creation response so it
can return a recognized warning without emitting ownerStatus; preserve existing
owner-status behavior for other cases. In
tests/contract/projects.contract.test.ts, add terminal and JSON scenarios
covering the warning-only response and assert that readProjectCreateWarning
produces the normalized local message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/projects.ts`:
- Around line 60-69: Update isOwnerWarningStatus and isProjectCreateWarningCode
to validate warning-code membership using an own-property check on
OWNER_STATUS_WARNING_CODES and PROJECT_CREATE_WARNINGS rather than the in
operator, so inherited keys such as constructor and __proto__ are rejected.

---

Nitpick comments:
In `@tests/helpers/mock-server.ts`:
- Around line 434-449: Add independent warning state in
tests/helpers/mock-server.ts around the project creation response so it can
return a recognized warning without emitting ownerStatus; preserve existing
owner-status behavior for other cases. In
tests/contract/projects.contract.test.ts, add terminal and JSON scenarios
covering the warning-only response and assert that readProjectCreateWarning
produces the normalized local message.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9762052e-5535-4130-8331-80d9809d513e

📥 Commits

Reviewing files that changed from the base of the PR and between 84923b7 and a8e2da8.

📒 Files selected for processing (8)
  • README.md
  • src/commands/projects.ts
  • src/commands/spectrum/platforms.ts
  • src/commands/spectrum/users.ts
  • src/lib/types.ts
  • tests/_setup.ts
  • tests/contract/projects.contract.test.ts
  • tests/helpers/mock-server.ts

Comment thread src/commands/projects.ts
Comment on lines +60 to +69
function isOwnerWarningStatus(value: unknown): value is OwnerWarningStatus {
return typeof value === "string" && value in OWNER_STATUS_WARNING_CODES;
}

function isProjectCreateWarningCode(
value: unknown
): value is ProjectCreateWarningCode {
return (
typeof value === "string" && value in PROJECT_CREATE_WARNINGS
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use own-property checks for warning codes.

in accepts inherited keys such as "constructor" and "__proto__". A malformed API warning can pass isProjectCreateWarningCode, and readProjectCreateWarning can return a prototype member instead of a ProjectCreateWarning. Use an own-property check in both predicates.

Proposed fix
 function isOwnerWarningStatus(value: unknown): value is OwnerWarningStatus {
-  return typeof value === "string" && value in OWNER_STATUS_WARNING_CODES;
+  return (
+    typeof value === "string" &&
+    Object.prototype.hasOwnProperty.call(OWNER_STATUS_WARNING_CODES, value)
+  );
 }

 function isProjectCreateWarningCode(
   value: unknown
 ): value is ProjectCreateWarningCode {
-  return typeof value === "string" && value in PROJECT_CREATE_WARNINGS;
+  return (
+    typeof value === "string" &&
+    Object.prototype.hasOwnProperty.call(PROJECT_CREATE_WARNINGS, value)
+  );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function isOwnerWarningStatus(value: unknown): value is OwnerWarningStatus {
return typeof value === "string" && value in OWNER_STATUS_WARNING_CODES;
}
function isProjectCreateWarningCode(
value: unknown
): value is ProjectCreateWarningCode {
return (
typeof value === "string" && value in PROJECT_CREATE_WARNINGS
);
function isOwnerWarningStatus(value: unknown): value is OwnerWarningStatus {
return (
typeof value === "string" &&
Object.prototype.hasOwnProperty.call(OWNER_STATUS_WARNING_CODES, value)
);
}
function isProjectCreateWarningCode(
value: unknown
): value is ProjectCreateWarningCode {
return (
typeof value === "string" &&
Object.prototype.hasOwnProperty.call(PROJECT_CREATE_WARNINGS, value)
);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/projects.ts` around lines 60 - 69, Update isOwnerWarningStatus
and isProjectCreateWarningCode to validate warning-code membership using an
own-property check on OWNER_STATUS_WARNING_CODES and PROJECT_CREATE_WARNINGS
rather than the in operator, so inherited keys such as constructor and __proto__
are rejected.

Copy link
Copy Markdown
Member Author

Replaced by #98 after splitting the Dashboard and CLI work into separate Linear issues. The replacement is linked to ENG-2164 and removes the incorrect claim that this change introduced platformless creation.

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.

2 participants