Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ category:

## How {% data variables.copilot.copilot_autofix_short %} works

{% data variables.copilot.copilot_autofix_short %} translates the description and location of an alert into code changes that may fix the alert. It interfaces with the large language model {% data variables.copilot.copilot_gpt_53_codex %} from OpenAI, which has sufficient generative capabilities to produce both suggested fixes in code and explanatory text for those fixes.
{% data variables.copilot.copilot_autofix_short %} translates the description and location of an alert into code changes that may fix the alert. It interfaces with the large language model {% data variables.copilot.copilot_gpt_51 %} from OpenAI, which has sufficient generative capabilities to produce both suggested fixes in code and explanatory text for those fixes.

## Enabling and managing {% data variables.copilot.copilot_autofix_short %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ category:

{% data reusables.rai.code-scanning.copilot-autofix-note %}

{% data variables.copilot.copilot_autofix_short %} generates potential fixes that are relevant to the existing source code and translates the description and location of an alert into code changes that may fix the alert. {% data variables.copilot.copilot_autofix_short %} uses internal {% data variables.product.prodname_copilot %} APIs interfacing with the large language model {% data variables.copilot.copilot_gpt_53_codex %} from OpenAI, which has sufficient generative capabilities to produce both suggested fixes in code and explanatory text for those fixes.
{% data variables.copilot.copilot_autofix_short %} generates potential fixes that are relevant to the existing source code and translates the description and location of an alert into code changes that may fix the alert. {% data variables.copilot.copilot_autofix_short %} uses internal {% data variables.product.prodname_copilot %} APIs interfacing with the large language model {% data variables.copilot.copilot_gpt_51 %} from OpenAI, which has sufficient generative capabilities to produce both suggested fixes in code and explanatory text for those fixes.

{% data variables.copilot.copilot_autofix_short %} is allowed by default and enabled for every repository using {% data variables.product.prodname_codeql %}, but you can choose to opt out and disable {% data variables.copilot.copilot_autofix_short %}. To learn how to disable {% data variables.copilot.copilot_autofix_short %} at the enterprise, organization and repository levels, see [AUTOTITLE](/code-security/code-scanning/managing-code-scanning-alerts/disabling-autofix-for-code-scanning).

Expand Down
10 changes: 1 addition & 9 deletions content/copilot/concepts/agents/enterprise-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,9 @@ The AI Controls view provides a centralized platform where you can manage and mo
* View and filter a list of agent sessions in your enterprise over the last 24 hours
* Find a detailed record of agentic audit log events

## {% data variables.copilot.copilot_cloud_agent %}

{% data reusables.organizations.copilot-policy-ent-overrides-org %}

Enterprise owners and AI managers can control how {% data variables.copilot.copilot_cloud_agent %} is adopted across the enterprise by choosing one of four policy states. This allows you to pilot adoption progressively and manage risk.

If you choose the **Enabled for selected organizations** policy, you can select organizations individually or based on organization custom properties. This lets you define dynamic groups of organizations that align with your existing organizational structure—for example, by region, compliance tier, or department. You can manage this policy setting using the REST API endpoints or directly in the AI Controls page. See [REST API endpoints for Copilot coding agent management](/rest/copilot/copilot-coding-agent-management#copilot-coding-agent-policy-states). Please note that using custom properties to enable CCA is evaluated once at the time of configuration. Organizations will not be automatically enabled or disabled for CCA if the custom property is added, removed, or modified later.

## {% data variables.copilot.copilot_custom_agents %}

{% data variables.copilot.copilot_custom_agents %} are specialized versions of {% data variables.copilot.copilot_cloud_agent %} that you can configure with tailored prompts, tools, and context, making them excel at specific tasks. {% data variables.copilot.custom_agents_caps_short %} can be defined and managed at the enterprise level for greater control and compliance, or at the organization and repository levels to allow teams the flexibility to build for their specific needs.
{% data variables.copilot.copilot_custom_agents %} are specialized versions of {% data variables.copilot.copilot_cloud_agent %} that you can configure with tailored prompts, tools, and context, making them excel at specific tasks. {% data variables.copilot.custom_agents_caps_short %} can be defined and managed at the enterprise level for greater control and compliance, or at the organization and repository levels to allow teams the flexibility to build for their specific needs.

You can manage your enterprise-level {% data variables.copilot.custom_agents_short %}:
* From the AI Controls view
Expand Down
4 changes: 0 additions & 4 deletions content/copilot/concepts/policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ Enterprise owners can choose to set policies for {% data variables.product.prodn

If a policy is defined at the enterprise level, the policy applies to all users and control of the policy is disabled at the organization level.

### Granular organization selection

**For the {% data variables.copilot.copilot_cloud_agent %} policy**, enterprise owners can choose to enable the feature for specific organizations rather than applying a blanket enterprise-wide setting. When **Enabled for selected organizations** is selected by an enterprise owner or an AI manager, only the selected organizations can enable the feature. Organizations can be selected individually or by using organization custom properties.

### No policy

If an enterprise owner selects **No policy**, the impact depends on whether a user has access to {% data variables.product.prodname_copilot_short %} through an organization or directly from the enterprise.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Managing GitHub Copilot cloud agent in your enterprise
intro: 'Enable members of your enterprise to use {% data variables.copilot.copilot_cloud_agent %} and control the repositories where it is available.'
allowTitleToDifferFromFilename: true
permissions: Enterprise owners and AI managers
permissions: Enterprise owners
product: '{% data reusables.gated-features.copilot-cloud-agent %}<br><a href="https://github.com/enterprise/contact?ref_product=copilot&ref_type=engagement&ref_style=button" target="_blank" class="btn btn-primary mt-3 mr-3 no-underline"><span>Contact Sales</span> {% octicon "link-external" height:16 %}</a>'
versions:
feature: copilot
Expand Down Expand Up @@ -34,20 +34,16 @@ category:

{% data variables.copilot.copilot_cloud_agent %} and use of third-party MCP servers are blocked by default for users to whom you have assigned a {% data variables.product.prodname_copilot_short %} license. You can allow members to use these features from the AI Controls tab for your enterprise. See [AUTOTITLE](/copilot/managing-copilot/managing-copilot-for-your-enterprise/managing-policies-and-features-for-copilot-in-your-enterprise#configuring-policies-for-github-copilot).

* On the "Agents" page, click **{% data variables.copilot.copilot_cloud_agent %}**, then select **Enabled everywhere**, **Let organizations decide**, or **Enable for selected organizations**.
* On the "Agents" page, click **{% data variables.copilot.copilot_cloud_agent %}**, then select **Enabled everywhere** or **Let organizations decide**.
* On the "MCP" page, for the "MCP servers in {% data variables.product.prodname_copilot_short %}" policy, select **Enabled everywhere** or **Let organizations decide**.

### Next steps

* If you selected **Enabled everywhere**, tell organization owners that {% data variables.copilot.copilot_cloud_agent %} is enabled for all members. By default, the agent will be available in all repositories, but it is possible to opt out some or all repositories.
* If you selected **Let organizations decide**, discuss member enablement with organization owners.
* If you selected **Enable for selected organizations** ({% data variables.copilot.copilot_cloud_agent %} only), tell the owners of the selected organizations that {% data variables.copilot.copilot_cloud_agent %} is enabled for their members. Organizations that aren't selected will not have access.

For more information, see [AUTOTITLE](/copilot/how-tos/administer-copilot/manage-for-organization/add-copilot-cloud-agent).

> [!NOTE]
> When the {% data variables.copilot.copilot_cloud_agent %} policy is set to **Enabled for selected organizations**, you can select individual organizations in the UI. To select organizations based on custom properties instead, use the REST API. See [AUTOTITLE](/admin/managing-accounts-and-repositories/managing-organizations-in-your-enterprise/custom-properties) and [AUTOTITLE](/rest/copilot/copilot-coding-agent-management#selecting-organizations-with-custom-properties).

## Disabling {% data variables.copilot.copilot_cloud_agent %} in your repositories

{% data variables.product.prodname_copilot_short %} policies, like the "{% data variables.copilot.copilot_cloud_agent %}" and "MCP servers on {% data variables.product.prodname_dotcom_the_website %}" policies described above, affect only the users you assign a {% data variables.product.prodname_copilot_short %} license to.
Expand Down
7 changes: 3 additions & 4 deletions content/copilot/tutorials/index.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: Tutorials for {% data variables.product.prodname_copilot %}
title: 'Tutorials for {% data variables.product.prodname_copilot %}'
shortTitle: Tutorials
intro: Build skills and knowledge about {% data variables.product.prodname_copilot %} through examples and hands-on activities.
intro: 'Build skills and knowledge about {% data variables.product.prodname_copilot %} through examples and hands-on activities.'
versions:
feature: copilot
children:
- /copilot-chat-cookbook
- /customization-library
- /cloud-agent
- /spark
- /customize-code-review
- /use-custom-instructions
- /enhance-agent-mode-with-mcp
- /compare-ai-models
- /speed-up-development-work
Expand Down Expand Up @@ -54,4 +54,3 @@ includedCategories:
- Modernize applications
- Roll Copilot out at scale
---

Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
---
title: Using custom instructions to unlock the power of Copilot code review
shortTitle: Customize code review
intro: Learn how to write effective custom instructions that help {% data variables.product.prodname_copilot %} provide more relevant and actionable code reviews.
intro: 'Learn how to write effective custom instructions that help {% data variables.product.prodname_copilot %} provide more relevant and actionable code reviews.'
versions:
feature: copilot
contentType: tutorials
category:
- Accelerate PR velocity
- Team collaboration
- Configure Copilot
redirect_from:
- /copilot/tutorials/use-custom-instructions
---

## Introduction
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{% data variables.product.prodname_copilot_short %} policies are also managed at the enterprise level. If your enterprise owner has selected a specific policy, such as enabling a feature everywhere, disabling it everywhere, or enabling it for selected organizations only, you cannot override that setting at the organization level. For information on how policies combine, see [AUTOTITLE](/copilot/concepts/policies).
{% data variables.product.prodname_copilot_short %} policies are also managed at the enterprise level. If your organization is part of an enterprise, and explicit settings have been selected at the enterprise level, you cannot override those settings at the organization level. For information on how policies combine, see [AUTOTITLE](/copilot/concepts/policies).
51 changes: 10 additions & 41 deletions src/article-api/lib/get-all-toc-items.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import type { Context, Page } from '@/types'
import type { LinkData } from '@/article-api/transformers/types'
import { resolvePath } from './resolve-path'
import { renderLiquid } from '@/content-render/liquid/index'

interface PageWithChildren extends Page {
children?: string[]
category?: string[]
rawTitle: string
rawIntro?: string
}

interface TocItem extends LinkData {
Expand All @@ -29,11 +26,14 @@ export async function getAllTocItems(
page: Page,
context: Context,
options: {
recurse?: boolean
renderIntros?: boolean
/** Only recurse into children whose resolved path starts with this prefix.
* Prevents cross-product traversal (e.g. /en/rest listing /enterprise-admin). */
basePath?: string
} = {},
): Promise<TocItem[]> {
const { recurse = true, renderIntros = true } = options
const pageWithChildren = page as PageWithChildren
const languageCode = page.languageCode || 'en'

Expand Down Expand Up @@ -70,15 +70,19 @@ export async function getAllTocItems(
)
const href = childPermalink ? childPermalink.href : childHref

const title = await renderPropFast(childPage, 'title', context)
const intro = await renderPropFast(childPage, 'intro', context)
const title = await childPage.renderTitle(context, { unwrap: true })

let intro = ''
if (renderIntros && childPage.intro) {
intro = await childPage.renderProp('intro', context, { textOnly: true })
}

const category = childPage.category || []

// Only recurse if the child is within the same product section
const withinSection = href.startsWith(basePath)
const childTocItems =
withinSection && childPage.children && childPage.children.length > 0
recurse && withinSection && childPage.children && childPage.children.length > 0
? await getAllTocItems(childPage, context, { ...options, basePath })
: []

Expand Down Expand Up @@ -135,38 +139,3 @@ export function flattenTocItems(
recurse(tocItems)
return result
}

/**
* Check whether a string contains markdown link syntax that would need
* processing by the unified pipeline (e.g. link rewriting, AUTOTITLE).
*
* Use this to short-circuit expensive rendering when the text is
* Liquid-only and contains no markdown that needs transformation.
*/
function hasMarkdownLinks(text: string): boolean {
return text.includes('[') && text.includes('](/')
}

const RAW_PROP_MAP = {
title: 'rawTitle',
intro: 'rawIntro',
} as const

/**
* Fast-path rendering for page properties. Renders Liquid only, skipping
* the full unified pipeline. Falls back to page.renderProp() when the
* Liquid output contains markdown links that need rewriting.
*/
async function renderPropFast(
page: PageWithChildren,
prop: keyof typeof RAW_PROP_MAP,
context: Context,
): Promise<string> {
const raw = page[RAW_PROP_MAP[prop]]
if (!raw) return ''
const rendered = await renderLiquid(raw, context)
if (hasMarkdownLinks(rendered)) {
return page.renderProp(prop, context, { textOnly: true })
}
return rendered.trim()
}
5 changes: 4 additions & 1 deletion src/article-api/transformers/bespoke-landing-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ export class BespokeLandingTransformer implements PageTransformer {
// Note: For bespoke-landing pages, the site shows ALL articles regardless of includedCategories
// (includedCategories only filters for discovery-landing pages)
if (bespokePage.children && bespokePage.children.length > 0) {
const tocItems = await getAllTocItems(page, context)
const tocItems = await getAllTocItems(page, context, {
recurse: true,
renderIntros: true,
})

// Flatten to get all leaf articles (excludeParents: true means only get articles, not category pages)
const allArticles = flattenTocItems(tocItems, { excludeParents: true })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ export class DiscoveryLandingTransformer implements PageTransformer {
// recursion (e.g. /rest listing /enterprise-admin children that
// point outside the /rest hierarchy).
if (discoveryPage.children && discoveryPage.children.length > 0) {
const tocItems = await getAllTocItems(page, context)
const tocItems = await getAllTocItems(page, context, {
recurse: true,
renderIntros: true,
})

// Flatten to get all leaf articles (excludeParents: true means only get articles, not category pages)
let allArticles = flattenTocItems(tocItems, { excludeParents: true })
Expand Down
67 changes: 28 additions & 39 deletions src/journeys/lib/journey-path-resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,47 +233,38 @@ export async function resolveJourneyContext(
}
}

// Build the list of guides available for the current version.
// fetchGuideData returns null for guides that don't exist in the current version,
// so this filters out unavailable guides for correct counts and navigation.
const availableGuides = (
await Promise.all(
track.guides.map(async (guide, i) => {
const guideData = await fetchGuideData(guide.href, context)
return guideData ? { rawIndex: i, ...guideData } : null
}),
)
).filter((g): g is { rawIndex: number; href: string; title: string } => g !== null)

const filteredIndex = availableGuides.findIndex((g) => g.rawIndex === guideIndex)
const filteredCount = availableGuides.length

result = {
trackId: track.id,
trackName: track.id,
trackTitle: track.title,
journeyTitle: journeyPage.title || '',
journeyPath:
journeyPage.permalink || Permalink.relativePathToSuffix(journeyPage.relativePath || ''),
currentGuideIndex: filteredIndex >= 0 ? filteredIndex : guideIndex,
numberOfGuides: filteredCount,
currentGuideIndex: guideIndex,
numberOfGuides: track.guides.length,
alternativeNextStep: renderedAlternativeNextStep,
}

// Set up previous guide using the version-filtered list
if (filteredIndex > 0) {
const prev = availableGuides[filteredIndex - 1]
result.prevGuide = { href: prev.href, title: prev.title }
// Set up previous guide
if (guideIndex > 0) {
const prevGuidePath = track.guides[guideIndex - 1].href
const guideData = await fetchGuideData(prevGuidePath, context)
if (guideData) {
result.prevGuide = guideData
}
}

// Set up next guide using the version-filtered list
if (filteredIndex >= 0 && filteredIndex < filteredCount - 1) {
const next = availableGuides[filteredIndex + 1]
result.nextGuide = { href: next.href, title: next.title }
// Set up next guide
if (guideIndex < track.guides.length - 1) {
const nextGuidePath = track.guides[guideIndex + 1].href
const guideData = await fetchGuideData(nextGuidePath, context)
if (guideData) {
result.nextGuide = guideData
}
}

// Only populate nextTrackFirstGuide when on the last guide of the filtered track
if (filteredIndex === filteredCount - 1) {
// Only populate nextTrackFirstGuide when on the last guide of the track
if (guideIndex === track.guides.length - 1) {
foundTrackIndex = trackIndex

if (
Expand Down Expand Up @@ -329,18 +320,16 @@ export async function resolveJourneyTracks(
? await renderContent(track.description, context, { textOnly: true })
: track.description

const guides = (
await Promise.all(
track.guides.map(async (guide: { href: string; alternativeNextStep?: string }) => {
const linkData = await getLinkData(guide.href, context, { title: true })
if (!linkData?.[0]) return null
return {
href: linkData[0].href,
title: linkData[0].title || '',
}
}),
)
).filter((g): g is { href: string; title: string } => g !== null)
const guides = await Promise.all(
track.guides.map(async (guide: { href: string; alternativeNextStep?: string }) => {
const linkData = await getLinkData(guide.href, context, { title: true })
const baseHref = linkData?.[0]?.href || guide.href
return {
href: baseHref,
title: linkData?.[0]?.title || 'Untitled Guide',
}
}),
)

return {
id: track.id,
Expand Down
Loading
Loading