diff --git a/packages/client/src/__tests__/agent-briefing.test.ts b/packages/client/src/__tests__/agent-briefing.test.ts index a0471e48e..fa0a43644 100644 --- a/packages/client/src/__tests__/agent-briefing.test.ts +++ b/packages/client/src/__tests__/agent-briefing.test.ts @@ -421,6 +421,37 @@ describe("buildAgentBriefing — asking humans, GitHub, and CLI overview", () => expect(briefing).not.toContain("`first-tree-github` skill"); }); + it("frames missing-App and repo-coverage failures as a value-first Connect CTA", () => { + const briefing = buildAgentBriefing(makeOpts()); + const attention = briefing.slice( + briefing.indexOf("## GitHub Entity Attention"), + briefing.indexOf("## Asking Humans"), + ); + // Value first, not an error/chore report. + expect(attention).toContain("is not installed on, or does not cover"); + expect(attention).toContain("account/repo that owns the PR/issue"); + expect(attention).toContain("frame the optional upgrade value first"); + expect(attention).toContain("Promise only current events"); + expect(attention).toMatch(/for a PR, comments, review activity, new commits,\s+and merge\/close state/); + expect(attention).toMatch(/for an issue,\s+comments and open\/close state/); + expect(attention).not.toContain("checks"); + expect(attention).not.toContain("CI"); + // Admins alone receive the CTA; members and unknown roles stay out of the + // admin-only surface. + expect(attention).toContain("Only when the current human is a confirmed org admin"); + expect(attention).toContain("If the human is a member or their role is unknown"); + // Derive the link from the full Server URL without a scheme-breaking host + // placeholder, while preserving valid self-hosted http origins. + expect(attention).toContain("complete `Server:`"); + expect(attention).toContain("trim its trailing slash, append"); + expect(attention).toContain("preserve its `http://` or `https://` scheme"); + expect(attention).not.toContain("https:///settings/github"); + expect(attention).toContain("If the web origin cannot be resolved"); + // Explicit jargon ban so the agent stops parroting CLI wording. + expect(attention).toContain('Never say "webhook", "wire"'); + expect(attention).toContain('"install the App"'); + }); + it("keeps chat metadata rules compact but actionable", () => { const briefing = buildAgentBriefing(makeOpts()); const chatTopic = briefing.slice(briefing.indexOf("## Chat Topic & Description")); diff --git a/packages/client/src/runtime/agent-briefing.ts b/packages/client/src/runtime/agent-briefing.ts index 9bd458911..ec6c09fed 100644 --- a/packages/client/src/runtime/agent-briefing.ts +++ b/packages/client/src/runtime/agent-briefing.ts @@ -501,12 +501,13 @@ Creating a PR or issue **never** follows it; \`gh pr create\`, curl, GitHub MCP, ${bin} github follow Skip the follow only when the entity is clearly unrelated to this chat's task. -- **If the follow fails because the org has not installed the First Tree - GitHub App**, explain the optional value upgrade in product language: live - PR/issue activity (CI, reviews, merge) can flow back into this chat after an - org admin enables **Settings → GitHub** in the First Tree web app. Do not - expose raw error codes or \`github follow\` mechanics; say the PR/issue still - works either way. +- **If the follow fails because the First Tree GitHub App is not installed on, or does not cover, the GitHub account/repo that owns the PR/issue**, frame the optional upgrade value first, not as an error or chore. + Promise only current events: for a PR, comments, review activity, new commits, + and merge/close state; for an issue, comments and open/close state. Make clear the PR/issue still works either way. + - Only when the current human is a confirmed org admin, offer one clickable **Connect GitHub** CTA. Build its absolute URL from the complete \`Server:\` value printed by \`${bin} agent status\`: + trim its trailing slash, append \`/settings/github\`, and preserve its \`http://\` or \`https://\` scheme. If the web origin cannot be resolved, name **Settings → GitHub** in words and do not emit a link. + - If the human is a member or their role is unknown, do not send the CTA or route them into admin-only setup; say a team admin can enable live updates. + Never say "webhook", "wire", "re-follow", "install the App", or "action needed". - **Unfollow only when the human explicitly asks to stop tracking** the entity (\`${bin} github unfollow \`). Do not proactively unfollow merely because a PR or Issue completed, merged, or closed. diff --git a/skills/first-tree-welcome/SKILL.md b/skills/first-tree-welcome/SKILL.md index a04d73120..e482801a2 100644 --- a/skills/first-tree-welcome/SKILL.md +++ b/skills/first-tree-welcome/SKILL.md @@ -1,6 +1,6 @@ --- name: first-tree-welcome -version: 1.2.1 +version: 1.2.2 description: Use for a First Tree onboarding first chat, especially natural opening messages like "welcome aboard", "Please help me get started with First Tree", or "Please help me get settled into this team on First Tree." Also covers the production-scan fix first chat ("fix the launch blockers found by my production readiness scan"). Do not use for dedicated tree setup chats, ordinary chats, PR reviews, repo scans, tree writes, or maintenance. --- @@ -386,11 +386,11 @@ map of what is in flight. ### After a value PR opens: guide App install once -A review-ready PR gives the admin a concrete reason to install or update First -Tree GitHub App coverage: CI results, review comments, and merge state can flow -back into chat. The welcome launcher owns one concise install/coverage guidance -at this moment; do not rely only on the generic PR-following failure text that a -spawned task may have shown. +A review-ready PR gives the admin a concrete reason to connect or update First +Tree GitHub App coverage: comments, review activity, new commits, and merge +state can flow back into chat. The welcome launcher owns one concise +install/coverage guidance at this moment; do not rely only on the generic +PR-following failure text that a spawned task may have shown. - The spawned value task owns following its PR in its own task chat (`first-tree github follow `) and reporting whether live tracking is @@ -401,15 +401,22 @@ spawned task may have shown. add App-install guidance. - If tracking is blocked because the First Tree GitHub App is not installed on, or does not cover, the GitHub account/repo that owns the PR, and the human is a - confirmed **admin**, include one launcher-level install/coverage line when you - report that PR result. Keep it tied to the win, for example: "PR is open. To - have CI, review comments, and merge updates flow back here, install or cover - this repo from Settings -> GitHub." Use a product link only when you have a - stable one; otherwise name **Settings -> GitHub**. Do not fabricate raw GitHub - App install URLs. + confirmed **admin**, include one launcher-level line when you report that PR + result. Lead with value, tied to the win: "Want this PR's comments, reviews, + new commits, and merge status to land in this chat as they happen?" Follow it + with one **Connect GitHub →** CTA and say it is a one-time setup for the team. + Make the CTA clickable only after deriving its URL: take the complete `Server:` + URL from `first-tree agent status`, trim its trailing slash, and append + `/settings/github`, preserving the original `http://` or `https://` scheme. + Use that resulting absolute URL directly as the link destination. If the web + origin cannot be resolved, name **Settings → GitHub** in words instead of + emitting a link. Do not fabricate a raw GitHub App install URL. Say value, + then the CTA — and never use mechanics words ("webhook", "wire", "re-follow", + "install the App", "action needed"). - If the human is an invitee/member or role is unclear, do not route them into - an admin-only install surface. Say an organization admin can enable live PR - updates for this repo if useful. + an admin-only install surface. Say a team admin can turn on live PR updates + (comments, review activity, new commits, and merge status) for this repo, if + useful. - Give this App-install guidance at most once in the onboarding launcher. If the spawned task chat already mentioned the missing App, still include the short launcher-level line; do not repeat a full setup explanation. diff --git a/skills/first-tree-welcome/VERSION b/skills/first-tree-welcome/VERSION index 6085e9465..23aa83906 100644 --- a/skills/first-tree-welcome/VERSION +++ b/skills/first-tree-welcome/VERSION @@ -1 +1 @@ -1.2.1 +1.2.2