Skip to content

Read the agent connection ceremony as data with --json - #852

Merged
jeremy merged 7 commits into
mainfrom
agent-connect-json
Oct 17, 2026
Merged

jeremy merged 7 commits into
mainfrom
agent-connect-json

Conversation

@jeremy

@jeremy jeremy commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Builds the machine-readable connection ceremony that the "Bring your agents to Basecamp" cards keep waiting on. CLI additions every GUI path needs lists it ("basecamp auth agent connect refuses --json today"), and the one-click Connect on My > Agent (D6) depends on it. The Distribution doc gives the shape: "Emit the verification URL, the code and the expiry as a first line, then the result."

Problem

auth agent connect refuses every machine output mode, because the link, the code and the wait line all go to stdout. Anything that drives the ceremony for a person has to scrape prose to find the link and the code. That covers a Connect button, the agent sandbox's install, or a coding agent relaying the ceremony.

Change

Under --json, stdout carries two JSON values.

  1. One line, written as soon as Basecamp answers the intake, while the ceremony is still waiting on the person:
    {"type":"verification","verification_uri":"https://…/oauth/agent_connection_verification?user_code=WDJB-MJHT","user_code":"WDJB-MJHT","expires_at":"2026-10-06T18:10:00Z","expires_in":600}
  2. The result envelope every command prints:
    {"ok":true,"data":{"profile":"agent","account_id":"999","base_url":"…","source":"agent_connection","oauth_type":"agent","scope":"full","client_id":"bc-agent-42","profile_created":true,"default":true},"summary":"Connected profile \"agent\" to a Basecamp agent"}
    Or the error, if the person declined, the code expired, or nothing could be stored.

Other behavior:

  • stderr gets the person's half: the link, the code, the phishing warning and the wait line. The browser opens or doesn't exactly as it would without --json.
  • Never on either stream: the client secret or the device code (the poll's bearer). The line carries the validated link (the one the browser would be sent to) and the code with control sequences stripped.
  • --agent is accepted the same way. It prints the result's data alone, after the same line.
  • Still refused: --jq (it filters one envelope, and this writes two values), and --quiet, --ids-only and --count, which would throw the verification line away.
  • Unchanged: BASECAMP_NONINTERACTIVE still refuses the ceremony, because approval still needs a person. connect setup's use of the ceremony is untouched.

The ceremony gets an OnIntake hook in auth.AgentConnectOptions. It is called once, after the intake has been validated and before the browser opens, with only the link, the code and the expiry.

Who uses it

  • The agent sandbox's install. It runs basecamp auth agent connect -P agent --software-name agent-sandbox --json, shows the link and code, and reads the result without scraping.
  • A future one-click Connect. The card's own requirement still applies to whatever launches it: a fixed operation, validated parameters, and no credential ever handed back to the browser.

Tests

  • TestAuthAgentConnectJSONWritesTheVerificationThenTheResult. The mock server snapshots stdout at the poll, which proves the verification line is out, newline-terminated, before approval. The test also checks the result envelope, that stderr carries the code, and that neither stream carries the secret or the device code.
  • TestAuthAgentConnectJSONOnADeclineWritesOnlyTheVerification: a decline leaves only the verification line, mints nothing and stores nothing.
  • TestAuthAgentConnectRefusesOutputModesThatCannotCarryIt: --jq, --quiet, --ids-only and --count. This replaces the old blanket refusal test. It is a regression guard and passes on main too.

The first two fail on main. bin/ci is green on linux.


Summary by cubic

basecamp auth agent connect now reads the connection ceremony as data under --json (or --agent), so a Connect button, the agent sandbox, or a coding agent can drive it without scraping prose.

  • stdout carries two JSON values written in order: a verification line (link, user code, expiry) as soon as Basecamp answers the intake, then the result envelope (or error). The operator's half — link, code, warning, wait line — moves to stderr; the browser opens exactly as it would without --json.
  • The verification line carries the stripped link the terminal shows, and a single fixed deadline governs the published expiry, the operator's copy, and the poll. A failed write of that line stops the ceremony before anything waits or is stored; a callback that outlives the code ends it as expired.
  • Neither stream ever carries the client secret or the device code. --agent prints the result's data alone after the same verification line; --jq, --quiet, --ids-only, and --count are still refused. BASECAMP_NONINTERACTIVE and connect setup are unchanged.
  • The basecamp-connect skill now runs the ceremony with --json and relays the verification line's link, code, and expiry. If an older CLI refuses --json, the skill upgrades it and reruns rather than following the refusal's hint toward a pasted token. auth login and profile create still refuse --json and are run plainly.

Written for commit c1e99b0. Summary will update on new commits.

View guided diff Turn on auto-fix

Copilot AI balanced review requested due to automatic review settings October 6, 2026 18:03
@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) auth OAuth authentication labels Oct 6, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

Comment thread internal/auth/agent_connect.go Outdated
Comment thread internal/commands/auth_agent.go Outdated
Comment thread internal/commands/auth_agent_connect_test.go Outdated
@jeremy
jeremy marked this pull request as ready for review October 7, 2026 03:49
@jeremy
jeremy requested a review from a team as a code owner October 7, 2026 03:49
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-17T06:18:49.540181Z 16ed4c1 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 55bb886253

ℹ️ 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 internal/commands/auth_agent.go Outdated
Comment thread internal/commands/auth_agent.go
Copilot AI balanced review requested due to automatic review settings October 7, 2026 04:11
@jeremy
jeremy force-pushed the agent-connect-json branch from 55bb886 to 1eb0a25 Compare October 7, 2026 04:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@jeremy I have started the AI code review. It will take a few minutes to complete.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 1eb0a25de4

ℹ️ 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".

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

Comment thread internal/commands/auth_agent_connect_test.go
Comment thread internal/auth/agent_connect.go Outdated
Copilot AI balanced review requested due to automatic review settings October 7, 2026 05:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@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: 0f01878a93

ℹ️ 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 internal/commands/auth_agent.go
@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@jeremy I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Turn on auto-fix | Re-trigger cubic

Comment thread internal/commands/auth_agent.go
Comment thread internal/commands/auth_agent_connect_test.go
Comment thread internal/commands/auth_agent.go Outdated

@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: 0f01878a93

ℹ️ 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 internal/auth/agent_connect.go Outdated
@jeremy

jeremy commented Oct 7, 2026 •

Copy link
Copy Markdown
Member Author

Rebased onto main (943dbb5) with no conflicts.

The earlier CI failure on 55bb886 was make tidy-check. go mod tidy could not download google.golang.org/genproto@v0.0.0-20260319201613-d00831a3d3e7.zip from proxy.golang.org: stream error: stream ID 471; INTERNAL_ERROR; received from peer. That is an HTTP/2 transport error from the module proxy, not a tidiness diff. This PR doesn't touch go.mod or go.sum, tidy-check passed on linux for every head since, and main's Test runs were green around the same time. Nothing was skipped or retried blind: the rebased heads ran CI fresh, and it's green on 3a4a795.

Review threads: 11 resolved (9 fixed, 2 declined), 1 open for a decision.

Declined:

Open for a decision:

Codex reported on 3a4a795 with no major issues, and cubic found no issues. Copilot can't review because the requester's quota is exhausted.

Copilot AI balanced review requested due to automatic review settings October 7, 2026 06:12
@github-actions github-actions Bot added the skills Agent skills label Oct 7, 2026
@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review

@jeremy I have started the AI code review. It will take a few minutes to complete.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: d6a6dfe62b

ℹ️ 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".

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 6 files

Turn on auto-fix | Re-trigger cubic

@jeremy

jeremy commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

The open decision is settled. Jeremy decided the skill thread: the basecamp-connect skill now runs auth agent connect --json and relays the verification line's fields. The first-time-setup eval requires --json, and its reject rule now names only the modes the connection still refuses, with a comment that's true. --agent is no longer rejected, because the CLI takes it. Done in d6a6dfe, here rather than on #848, which doesn't touch the skill's connection guidance. Merged together, the two branches pass #848's contract test.

Review threads: 12 resolved (10 fixed, 2 declined), 0 open. The declines are listed in the summary above.

The full make check passed on linux before the push, and CI is green on d6a6dfe. Codex reported on d6a6dfe with no major issues, and cubic found no issues. Copilot can't review because the requester's quota is exhausted.

auth agent connect refused every machine output mode, because the link,
the code and the wait line all went to stdout. Whatever drives the
ceremony for a person (a one-click Connect, a sandbox install, an agent
relaying it) had to scrape prose to learn the link and the code.

Under --json (and --agent) stdout now carries two JSON values: a
verification line, written as soon as Basecamp answers the intake (link,
user code, expiry), then the result envelope (profile, account, scope,
client id). The person's half moves to stderr and the browser opens as
it would. Neither stream carries the client secret or the device code.
--jq, --quiet, --ids-only and --count are still refused: none of them
can carry the verification line.
…ut to its end

The line's link was the raw URL the server named, which url.Parse lets
carry Unicode C1 controls, and the JSON encoder writes those through as
the bytes a terminal acts on. It is now the stripped copy the terminal
shows, as the code already was; the browser is still sent to the URL
itself.

The test read stdout while More(), which at the top level stops quietly
at a stray closing delimiter. It now decodes to the end.
Under --json the line is how the link and the code reach whoever shows
them to the person. A stdout that refused it was ignored, and the
ceremony went on to open the browser, poll and store a credential that
nobody reading the data had been asked to approve. The intake callback
can now fail, and a failed write ends the ceremony before anything
waits.

The test that reads stdout at the poll now hands what it saw across the
server's goroutine under a lock.
The expiry handed to OnIntake, the one the operator is told and the one
the poll stops at were each taken from the clock separately, so a slow
callback left the poll running past what the verification line said,
or opening the browser on a code already dead. ConnectAgent now fixes one
deadline as the intake answers and everything counts down to it; a
callback that outlived the code ends the ceremony as expired.
… nothing

The help called the second value the result envelope in every mode, but
--agent prints the data alone. The output-mode refusals claimed to stop
before the server was asked anything while only mints were counted; the
intake is counted now too.
The skill ran auth agent connect plainly and scraped the terminal for the
link and the code, and its first-time-setup eval forbade --json on the
grounds that the connection refuses it, which this branch makes untrue.
The skill now runs it with --json and relays the verification line's
link, code and expiry, which are already stripped of control characters;
auth login and profile create still refuse --json and are run plainly.

The eval requires --json, mocks the two JSON values the command writes,
and rejects only the output modes the connection still refuses. --agent
is no longer rejected: the CLI takes it, and those rules reject only
what it refuses.
Copilot AI balanced review requested due to automatic review settings October 17, 2026 06:16
@jeremy
jeremy force-pushed the agent-connect-json branch from d6a6dfe to 16ed4c1 Compare October 17, 2026 06:16
@jeremy

jeremy commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

🤖 Rebased onto main (head 16ed4c1). The only conflict was skills/basecamp-connect/SKILL.md in the last commit, because main restructured the skill. I took main's file and re-applied both edits: Interactive logins (run auth agent connect with --json and relay the verification line) and the first-time-setup step (connect with --json). The eval case merged cleanly. The skill-layout budget test, skill drift, eval patterns and the auth/connect tests pass.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The skill still accepts CLI 0.13.0 despite now requiring JSON connection support that release lacks.

1 open issue

Review effort: Balanced

Comment thread skills/basecamp-connect/SKILL.md
The skill's prerequisite still accepts 0.13.x, whose agent connect refuses
--json, so a newer skill on an older CLI would stop at the connection
step. Rather than name a release that doesn't exist yet, the skill reads
the refusal itself: upgrade, tell the person, and run it again, without
following the refusal's hint toward a pasted token.
Copilot AI balanced review requested due to automatic review settings October 17, 2026 06:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approved

Static review identified no blocking defects in the output flow, expiry handling, or failure handling; tests were not executed during this review.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@jeremy
jeremy merged commit 61b8618 into main Oct 17, 2026
33 checks passed
@jeremy
jeremy deleted the agent-connect-json branch October 17, 2026 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth OAuth authentication commands CLI command implementations skills Agent skills tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants