Commit Graph
155 Commits
Author SHA1 Message Date
Aaron PowellandCopilot App 9ce814859e Rebuild website on Primer Brand design (#2703)
* feat(website): rebuild site on Primer Brand design prototype

Replace the Astro + Starlight site with the Brand Engineering design
prototype, ported component-for-component onto plain Astro + React
islands. The prototype is treated as the authority on markup and
styling; dynamic data is injected into its components rather than the
components being reinterpreted.

Framework:
- Remove @astrojs/starlight entirely, along with its document shell,
  search, footer and language selector. BaseLayout.astro now owns the
  document head, CSP, social meta and analytics.
- Add @primer/react-brand and @astrojs/react. Alias the package to its
  ESM build in vite.resolve, since the default CJS entrypoint breaks
  named-export detection during SSR, and mark it noExternal so its
  stylesheet imports resolve.
- Promote pagefind to an explicit devDependency; it was previously
  pulled in transitively by Starlight.

Pages: home, the five catalogs, the five detail routes, contributors,
Playbook index and articles, and the cookbook are all rendered by
ported prototype components inside a shared PageShell.

Detail pages share a DetailChassis (hero, breadcrumbs, sticky TOC with
scroll-spy, prev/next) while keeping what makes each type distinct: a
file switcher over bundled skill assets, an included-items grid and
external provenance for plugins, and a hero-scale preview for
extensions.

i18n: resolve translated Playbook entries via Astro.currentLocale
inside the shared article route instead of separate [locale] routes.
The explicit routes collided with the i18n fallback routes, so
translated articles were being shadowed by their English originals and
900 nonsensical double-locale pages were emitted.

Search: TopNavSearch now queries the Pagefind index client-side in
addition to the static resource index, merging on href and degrading
to the static index in dev, where no index has been built.

Also delete the superseded vanilla-TS page renderers and Astro
partials, which the ported React components fully replace.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): resolve accessibility violations in ported detail pages

Fixes the three axe violations surfaced by the a11y audit after the
Primer Brand redesign:

- aria-prohibited-attr: `aria-label` was set on roleless `div`s in
  InstructionDetail and PluginDetail. The "Applies to" list now uses
  list/listitem roles; plugin provenance uses a group role.
- scrollable-region-focusable: the install command `code` element
  overflows horizontally but was not keyboard reachable. Added
  tabIndex to all three render sites.
- color-contrast: the Playbook "New" label used the brand's
  success-fg on success-subtle, reaching only 4.09:1 in light mode.
  Stepped one down the same green ramp for 6.14:1. Scoped to light
  mode; dark mode already passed and its green-7 is near-black.

Also corrects the stale route list in the audit script: /hooks/,
/workflows/ and /tools/ have never existed as pages.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): collapse long filter facets and unpin detail-page footer

Two issues surfaced by review of the redesigned site:

Catalog facets rendered every option. The prototype's filter groups were
built from small hardcoded arrays, but real data produces 193 tool options
on /agents/ and 245 "Applies to" values on /instructions/. The sidebar grew
to ~10,000px and stretched the whole catalog row, pushing the (already
present) pagination control far below the fold so it read as missing.

Adopt the prototype's own solution for this, which it had already applied to
the extensions page: collapse groups past 10 options behind a "Show N more"
toggle, and cap .filterOptions with an internal scroll area. Ported verbatim
to the agents, instructions, skills, and plugins catalogs.

Detail pages scroll inside .scrollHost rather than the document, but the
footer came from PageShell, outside that element, so it stayed pinned over
the content instead of appearing at the end. The prototype renders its
footer inside the scroll host; PageShell now takes a renderFooter flag so
DetailChassis can do the same. LearningArticleLayout already did this.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): source contributor count from .all-contributorsrc

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Removing playwright-mcp files

* fix(website): resolve article text colour inside themed scope

Injected markdown inherited color from body, which sits outside the
ThemeProvider and always resolved the light-mode token, making body
copy unreadable in dark mode.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): drop 'In this article' TOC from resource detail pages

Resource detail pages (agent, instruction, skill, plugin, extension) are
not articles, and their markdown headings do not form a meaningful
outline. Playbook and cookbook articles keep their TOC.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* style(website): thin the sidebar scrollbar on detail pages

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): use themed link colour for markdown links in dark mode

Raw markdown-injected <a> elements previously fell back to the browser's
default blue/purple link colours, which are harsh against the dark-mode
background. Route them through --brand-color-text-link-rest (and the
pressed/hover token) instead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): apply ThemeProvider to Playbook article layout so dark mode works

LearningArticleLayout replaces PageShell for Playbook articles but never
wrapped itself in a ThemeProvider, so its useTheme() call always fell back
to Primer's light default regardless of the site's actual theme preference.
Split the component into a thin ThemeProvider wrapper plus the existing
implementation (now LearningArticleLayoutBody), matching the pattern already
used by PageShell.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): align raw markdown code blocks with prototype styling

Astro's default Shiki config bakes in the fixed 'github-dark' theme's
literal colors, ignoring the site's actual light/dark mode - this made
plain markdown-fenced code blocks (as opposed to the prototype's own
SyntaxHighlightedCode component) always render a hardcoded dark box
regardless of theme.

Switch shikiConfig to the 'css-variables' theme so highlighted tokens
resolve through --astro-code-* custom properties instead, then map
those to the same brand color tokens the prototype's codeBlock uses
(canvas-subtle background, border-muted border, brand text/link/accent
colors for tokens). Raw markdown code blocks now match the prototype's
bordered, canvas-subtle surface in both color modes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): show real contributor count on every page shell

The contributor badge rendered 0 on Playbook, Cookbook, home and custom
pages, and reverted to 0 on hydration everywhere else.

Two causes:
- Shells that bypass PageShell (LearningArticleLayout, PlaybookIndex,
  PlaybookArticleBody, CookbookIndex, HomePage, TopNav, Custom) defaulted
  contributorsTotal to 0 instead of the site-data value.
- site-data read .all-contributorsrc with node:fs at module scope. Those
  shells are client:load hydrated, so the read threw in the browser and
  the count reset to 0 after hydration.

The count is now read once in astro.config.mjs and inlined through
vite.define as __CONTRIBUTORS_TOTAL__, so it is a literal in both the
server render and the client bundle.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* style(website): soften catalog filter list scrollbars

The filter option lists only set scrollbar-width: thin, so they rendered
the platform default scrollbar. They now use the same muted, transparent
track treatment as the article sidebar, which resolves through
--brand-color-border-muted in both colour modes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* refactor(website): remove Access from tools panel from plugins catalog

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* feat(website): make Copilot app deep link the default plugin install

Plugin detail pages exposed only a copyable CLI command. They now lead
with a ghapp://plugins/install deep link in the same split-button
ActionMenu the other detail pages use, keeping the CLI command available
as a Copy action in the menu.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): migrate markdown remark plugins to unified processor

Astro 7 deprecates markdown.remarkPlugins in favour of passing a
unified() processor from @astrojs/markdown-remark. Moves the GitHub
admonitions plugin into markdown.processor, clearing the startup
deprecation warning. shikiConfig stays at the markdown level as it is
not part of UnifiedProcessorOptions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): fail the build when the contributor manifest is unreadable

Silently falling back to 0 is how the contributor badge regressed before,
so a missing or malformed .all-contributorsrc now throws in production
builds and warns in dev instead of shipping a wrong count.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Fix codespell and CodeQL findings in website components

- Fix real typos flagged by codespell: 'Couldn&apos;t' -> 'Couldn't'
  (plain apostrophe, matching convention elsewhere in JSX) and
  'Unparseable' -> 'Unparsable' in catalogFilters.ts
- DetailChassis.tsx: replace sequential HTML entity unescaping with a
  single-pass replace to avoid double-unescape/injection risk flagged
  by CodeQL
- SyntaxHighlightedCode.tsx: make the markup HTML comment regex match
  newlines so multi-line comments cannot break out of the token
  (Bad HTML filtering regexp)
- pagefindSearch.ts: strip HTML tags in a loop until stable so nested/
  malformed markup can't survive a single-pass strip (Incomplete
  multi-character sanitization)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): harden detail heading sanitization

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* github-app settings

* Fix light-theme flash before dark mode applies on page load

ThemeProvider colorMode="auto" from @primer/react-brand only resolves
the real OS colour-scheme preference inside a useEffect, so its first
render is always light. Add a synchronous inline script in <head> that
reads prefers-color-scheme and stamps data-color-mode onto <html>
before first paint, using the same attribute Primer Brand's CSS
already keys off. React's own data-color-mode on the inner element
takes over once it hydrates.

Fixes #2820

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Fix light-mode scrollbar rendering in dark mode on Playbook articles

.scrollHost (the article scroll region shared by Playbook articles,
cookbook recipes, and extension detail pages) never declared a
color-scheme, so the browser always painted its native scrollbar using
light-mode chrome regardless of the site's active theme. Set
color-scheme: light dark as a baseline and pin it explicitly to the
resolved data-mode, and add scrollbar-color so Firefox picks up the
themed thumb colour too.

Fixes #2822

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Widen and center extension card preview image

The Canvas Extensions overview card thumbnail was fixed at 360px, leaving
uneven left/right margins within the card. Let it grow up to 440px and
center it with margin-inline: auto so the image is balanced within the
card.

Fixes #2823

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Link Submit CTAs to each resource's contribution section

The bottom "Submit" CTA on every catalog page pointed at the top of
CONTRIBUTING.md, forcing readers to scroll and hunt for the relevant
"how to contribute" instructions for that specific resource type.
Point each catalog's CTA directly at the section that documents how to
contribute that resource: agents, instructions, plugins, and skills
link to their dedicated docs/README.*.md "How to Contribute" section,
and canvas extensions link to CONTRIBUTING.md's "Adding Canvas
Extensions" section (extensions have no dedicated README doc).

Fixes #2824

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Center-align "View on GitHub" source link with its icon

The source-link label sat on the default inline text baseline instead
of being vertically centered against the GitHub mark icon next to it,
so the two visually drifted apart. Wrap the icon and label in an
inline-flex container with align-items: center so they share the same
vertical center.

Fixes #2825

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Fix mobile resource and Playbook article layout issues

Clean up the shared resource detail and Playbook article styling so mobile pages no longer show unintended divider lines or overflow horizontally.

- remove article-section divider borders so content separates with spacing instead of white/muted horizontal rules
- drop the detail-page breadcrumb divider on mobile to match the Playbook mobile treatment
- constrain raw markdown pre/code blocks to their column and let long code scroll horizontally
- allow metadata chips to wrap inside the mobile sidebar instead of widening the page

Fixes #2827
Fixes #2828
Fixes #2829

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Only show language selector on pages with real translations

Most of the site is English-only, but the language selector rendered
unconditionally on every page even though only the
learning-hub/copilot-workshops/app track has mirrored translations.

Add hasTranslations() to playbook-routes.ts, thread a showLanguageSelect
prop through PageShell, TopNav and LearningArticleLayout, and compute
it from the article's englishId in learning-hub/[...slug].astro so only
translated Playbook articles show the selector.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Add Workshop recommended card to Playbook index

The copilot-workshops hands-on tracks (VS Code, CLI, App, Cloud harnesses) existed and rendered correctly at direct URLs, but had no entry point in the new Playbook index UI -- the Articles grid intentionally excludes nested multi-page tracks by design, and the only prior link was buried in body prose.

Adds a 'Workshop' recommended card (following the existing cli-for-beginners precedent) linking to /learning-hub/copilot-workshops/, and registers the route in pageHref.ts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Add a Workshop content-type filter to the Playbook

The hands-on workshop tracks (CLI for Beginners, and the copilot-workshops harnesses) had no shared way to discover them from the Articles grid -- each had a recommended card, but no consistent categorization.

Tags both workshop landing pages 'workshop', adds a new 'Workshop' Kind/content-type facet (derived the same way as the existing Terminology/Tutorial/Example kinds), and includes both landing pages in the Articles grid dataset so filtering by Content type > Workshop surfaces exactly the two tracks.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Fix P0/P1 items from Brand Engineering audit (brand-experience#458)

- P0: html lang now reflects the actually-rendered locale for a page,
  not the requested URL locale (BaseLayout.astro, playbook-routes.ts,
  PlaybookArticle.astro)
- P0: markdown tables get tabindex=0 via enhanceMarkdownA11y, which
  Playbook articles were never running (PlaybookArticle.astro)
- P0: long inline content and breadcrumbs no longer clip on narrow
  viewports (dotnet-upgrade.module.css, github-copilot-app.module.css)
- P1: strip the markdown document's own leading H1 so detail pages
  don't render the title twice (detail-page.ts)
- P1: document the hero secondary-CTA hex and InstructionsCatalog
  illustration colors as intentional prototype-fidelity values rather
  than defects (styles.module.css)
- P1: add explicit Heading size props in PlaybookIndex.tsx

Ref: github/brand-experience#458

* Rename Playbook to Learning Hub across UI and code

Renames PlaybookIndex.tsx -> LearningHubIndex.tsx, PlaybookArticle.astro
-> LearningHubArticle.astro, PlaybookArticleBody.tsx ->
LearningHubArticleBody.tsx, PlaybookIcon.tsx -> LearningHubIcon.tsx,
lib/playbook-routes.ts -> lib/learning-hub-routes.ts, and
lib/playbook-article.ts -> lib/learning-hub-article.ts. Updates all
call sites, UI copy, TopNav's playbookLabel prop, nav/search entries,
and home page CTA data to use Learning Hub terminology. URLs under
/learning-hub/* are unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Port github-copilot-app as bespoke Learning Hub article

Adopts the prototype's github-copilot-app.tsx directly as a dedicated React
component instead of rendering it through the generic markdown pipeline,
preserving its video carousel, comparison list, learn-more band, and other
bespoke JSX exactly as designed.

- New GithubCopilotApp.tsx under components/brand/learning-hub/, ported
  near-verbatim from the prototype (data-wiring only: pageHref import swap,
  media paths).
- The two large source videos (~23MB, ~32MB) are not committed; the article
  falls back to their poster/webp images with a TODO to host them externally.
- learning-hub-bespoke-articles.ts lists slugs that bypass the generic
  LearningHubArticle.astro pipeline.
- [...slug].astro branches to the bespoke component for "github-copilot-app"
  (English only for now); all other slugs and locales keep the generic path.

* Port bespoke Learning Hub articles

Add bespoke Learning Hub article components for the remaining prototype-backed
article pages, wire the cookbook index to the data-driven port, and route the
CLI overview page through the new bespoke component.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Resolve merge validation blockers in astro config

* Regenerate README docs after merging origin/main

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Fix Learning Hub Get started pages disappearing after opening (#2960)

The bespoke Learning Hub article components (GithubCopilotApp,
AgentsAndSubagents, CopilotConfigurationBasics,
GithubCopilotTerminologyGlossary, UsingAutomationsInCopilotApp,
WhatAreAgentsSkillsInstructions, WorkingWithCanvasExtensions,
CliForBeginnersOverview, CookbookIndex) received the `pageHref` helper
as a function prop passed into a `client:load` React island. Functions
cannot survive Astro's client-hydration prop serialization, so the
prop arrived as `undefined` on the client. The page rendered correctly
server-side (visible briefly), then React threw
`TypeError: pageHref is not a function` during hydration and unmounted
the tree, making the page appear to disappear.

Fixed by having each component import the `pageHref` singleton
directly (as AgentDetail, HomePage, and the other catalog components
already do) instead of receiving it as a prop, and removed the now
unnecessary `pageHref={pageHref}` prop and its import from the two
Astro routes that render these islands.

Verified in the dev server: all 9 previously affected routes now
hydrate without error, and `npm run build` completes successfully
(1097 pages).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* Strip stray trailing divider from Learning Hub articles (#2961)

Several Learning Hub markdown articles end their body with a trailing
--- thematic break, left over from an authoring template. Rendered
as-is it produced an unlabeled <hr> sitting directly above the page
footer, with no heading/section boundary to justify it.

Fix this generically in buildArticleSections() by stripping a single
trailing <hr> from the rendered HTML before it's split into sections,
rather than hand-editing every affected content file. This also
protects future articles authored with the same trailing-rule habit.
Legitimate mid-content dividers (e.g. between CLI lesson steps) are
left untouched.

* Remove emojis from Learning Hub article nav (#2962)

CLI for Beginners lessons decorate their ## headings with emoji
(e.g. "🎯 Learning Objectives"), which is fine inline in the article
body but read as stray glyphs once surfaced as plain-text labels in
the "In this article" nav — other Learning Hub pages don't
emoji-decorate their nav, so this was inconsistent.

Add a shared stripEmoji() helper and apply it to the nav labels built
from markdown headings in LearningHubArticle.astro. The article body
headings themselves are untouched.

* Fix hero code blocks blending into background (#2963)

Detail page hero install-command code blocks (SyntaxHighlightedCode via
heroExtras) used the same background token as the hero surface itself
(--brand-color-canvas-subtle), making them visually indistinguishable
except for a thin border.

Add a scoped .heroContent .codeBlock override in both shared style
modules (dotnet-upgrade.module.css for catalog Detail pages/Cookbook,
github-copilot-app.module.css for Learning Hub) that sets the
background to --brand-color-canvas-default instead, so hero code
blocks stand apart from the hero background.

The base .codeBlock rule is left untouched since body-content code
blocks (e.g. Cookbook recipe steps) correctly rely on canvas-subtle
being distinct from the page's canvas-default background.

* Tie color-scheme to dark mode for native scrollbars (#2964)

Native scrollbars (the page scrollbar, and any overflow container
without custom scrollbar styling, e.g. code block <pre> elements) are
painted by the browser based on the color-scheme CSS property, not our
design tokens. Only a handful of scoped containers (.scrollHost,
.filterOptions, .sidebarSticky) had custom scrollbar-color rules; the
page scrollbar and plain code-block overflow scrollbars had no
color-scheme set at all, so they rendered with light OS-default
scrollbars even when data-color-mode="dark" was set on <html>.

Add a global rule tying html's color-scheme to the same
data-color-mode attribute BaseLayout.astro already stamps on <html>,
so every native scrollbar (and other UA-drawn form controls) follows
the site's theme.

* Unify article/detail page typography, tables, and dividers (#2965)

Raw markdown injected into .articleSection (Skill/Agent/Instruction/
Plugin/Extension Detail pages via dotnet-upgrade.module.css, and
Learning Hub articles via github-copilot-app.module.css) had no styling
for headings, tables, horizontal rules, blockquotes, or inline code, so
it fell back to inconsistent browser UA defaults -- most visibly,
tables rendered with no borders or header emphasis at all.

Add a shared set of rules to both CSS modules, scoped under
.articleSection, that:
- map raw h1-h6 onto the brand type scale (font, weight, line-height)
- give hr a full-width divider matching the border-muted token
- style blockquote with a left accent bar
- render inline `code` (outside <pre>) as a small chip, matching
  .inlineCode used elsewhere for hand-authored tokens
- style table/th/td with bordered cells and a canvas-subtle header row,
  scrolling horizontally on narrow viewports

Also fix skills/acquire-codebase-knowledge/SKILL.md: a stray blank
line inside the "Bundled Assets" table split it into a lone header row
and a second block with no header, so GFM table parsing stopped after
the first row and the remaining rows rendered as literal pipe-delimited
text instead of a table -- this was the exact bug shown in the issue
screenshot.

* fix: align previous/next navigation links horizontally on Detail pages

Detail page Previous/Up next links were stacked vertically. Change
.nextUp to a row layout (space-between) so Previous sits left-aligned
and Up next right-aligned on the same row, with a max-width: 40rem
media query reverting to a stacked column layout on small screens.

Use an explicit .nextUpNext modifier class (applied to the "Up next"
link specifically) with margin-inline-start: auto instead of a
positional :last-child selector, so the link right-aligns correctly
even when it is the only link present (e.g. the first item in a
catalog, which has no Previous link).

Fixes #2966

* fix: align callout blocks with article content width

The .proTip callout (Note/Tip/Caution admonitions in Learning Hub
articles, and the "Maintained outside this repository" notice on
external Plugin Detail pages) had its own 32px horizontal margin.

The prototype places this callout as a sibling of .articleSection
(which has no horizontal padding of its own), using that margin to
align its edges with the section's own 32px padding. Our port always
renders it nested *inside* an already-padded .articleSection, so the
extra margin doubled up with that padding, making the callout visibly
narrower than the surrounding paragraph/table text -- most obvious on
narrow viewports.

Remove the horizontal margin (keep only the bottom spacing) in both
dotnet-upgrade.module.css and github-copilot-app.module.css so the
callout's internal padding lines up with the article text on both
edges, at all viewport widths.

Fixes #2967

* fix: standardize mobile card padding across resource pages

Agents, Instructions, Skills, and Plugins catalog cards (.item) used
the desktop 60px padding at every viewport, including phone widths,
because their @media (max-width: 47.99rem) block never reduced it --
unlike the Extension catalog, which drops to a 32px inset at that
breakpoint. This made cards on those four catalogs look inconsistently
over-indented on mobile compared to Extension cards.

Add the same `.item { padding: var(--base-size-32); }` override to the
mobile media query in agents.module.css, instructions.module.css, and
skills.module.css. plugins.module.css already had an override, but
with an asymmetric 32px/24px padding -- normalized it to the same 32px
on all sides used everywhere else.

Fixes #2968

* fix(website): address PR review feedback

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): preserve legacy resource links

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): bump transitive js-yaml to patched versions

Force astro's js-yaml dependency to 4.3.2 and front-matter/gray-matter's to 3.15.2 via npm overrides, fixing GHSA-52cp-r559-cp3m and GHSA-5p4m-2wfm-xmqj (quadratic-complexity DoS via YAML merge keys and !!omap resolution). Addresses github/vuln-mgmt#209786.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): address redesign follow-up issues

Fix light-mode favicon contrast with an adaptive SVG mark, allow YouTube embeds through the site CSP, and align resource catalog sort controls with the Playbook article sort treatment across Agents, Instructions, Skills, Plugins, and Extensions.

Addresses #3006, #3007, #3008.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): address PR review feedback

Respect reduced-motion preferences in detail TOC scrolling, restore default search indexes for bespoke Playbook pages, add pagination scroll/focus handling to the Agents catalog, sanitize contributor and cookbook URLs before rendering external links, index extension records in Pagefind, and restore install affordances for marketplace-backed external extensions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): revert Learning Hub naming from Playbook rename

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* chore(website): update stale Playbook comments to Learning Hub

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): align source label in detail sidebar

Fixes #3207

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

* fix(website): address security review feedback

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 80686fef-efe3-4cdd-8cd6-bfa61a5d0af6
2026-09-16 10:50:43 +10:00
Aaron PowellandCopilot App a93a83bfec Require new submissions after external plugin rejection (#2978)
* fix(external-plugin): require new submissions after rejection

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix(external-plugin): gate rejected rerun guidance

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* docs: align intake rerun guidance

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-08 14:01:51 +10:00
Aaron PowellandCopilot App f609fccfe1 fix(workflow): refresh learning hub updater lock (#2841)
Regenerate the agentic workflow with gh-aw v0.86.2 so the Copilot CLI is resolved from PATH and staged in the runner temp directory.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5135482d-49dc-4ff7-a2e8-c086ea1eeae4
2026-08-28 11:13:03 +10:00
d1b834940b Add Advanced Copilot CLI course to the Learning Hub (#2817)
* Add Advanced Copilot CLI course to the Learning Hub

Mirror the github-samples/advanced-copilot-cli course into the Learning
Hub and add a weekly sync workflow to keep it aligned, matching the
pattern used for the CLI for Beginners series.

- New agentic workflow advanced-copilot-cli-sync (+ compiled lock) that
  checks the upstream course weekly and opens a PR when content changes
- Source-faithful mirror of the 9 course modules plus an overview page
  under learning-hub/advanced-copilot-cli/, with route-safe links and
  localized chapter-03 diagrams
- Sidebar group and Learning Hub landing-page entry for the new course

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 3a4d8212-b18b-446f-bb8d-a0a81241fa05

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: GeekTrainer <GeekTrainer@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: 3a4d8212-b18b-446f-bb8d-a0a81241fa05
2026-08-27 11:49:34 +10:00
Aaron PowellandCopilot App 37dcfd2325 fix(plugins): discover MCP servers from mcp.json at plugin root (#2713)
* fix(plugins): discover MCP servers from spec-mandated mcp.json at plugin root

MCP config was declared via an extensions.com.github.awesome-copilot.mcpServers
pointer to a .mcp.json file. That namespace is stripped from the served manifest,
so nothing carried the MCP declaration through materialization.

Per Agent Plugins v1.0.0 the fixed location is mcp.json at the plugin root, which
already ships as-is. Drop the pointer, rename both .mcp.json files, and validate
mcp.json (schema, closed top-level fields, server transport variants).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Validate mcp.json against the full v1.0.0 schema with Ajv

Replace the hand-rolled MCP checks with Ajv validation against the
canonical Agent Plugins v1.0.0 MCP schema, so non-spec configs (empty
command/url, non-string args, reserved PLUGIN_ROOT/PLUGIN_DATA env keys,
invalid cwd, unknown server fields) are rejected. Per-server errors are
re-derived from the matching discriminated branch to avoid unhelpful
oneOf output.

Also reject a top-level extensions.mcpServers placement, which slipped
through because the manifest schema allows arbitrary object-valued
extension keys.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Strengthen mcpServers and stdio semantic validation

Reject mcpServers under any extensions namespace in plugin.json so
inline MCP config cannot bypass root-level mcp.json enforcement.

Also run stdio semantic checks after schema validation to reject
absolute command paths and cwd values that escape the plugin root,
with regression tests for both cases.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Enforce MCP path containment across platform path styles

Resolve plugin-relative commands and placeholder-rooted cwd values
against the plugin root, normalize Windows separators, and reject
lexical or symlink escapes. Add regression coverage for traversal,
placeholders, Windows paths, and symlink targets.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Align MCP semantics with the v1.0.0 specification

Restore the canonical cwd pattern and literal ./ command prefix.
Validate remote HTTP URLs and headers, including HTTPS requirements,
header syntax, control characters, and case-insensitive duplicates.
Keep PLUGIN_DATA checks lexical-only so it is not conflated with the
plugin filesystem root.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Reject unsafe MCP symlink paths

Resolve mcp.json through the filesystem and require a regular file
inside the real plugin root, reporting dangling links explicitly.

Harden command and PLUGIN_ROOT containment checks to inspect symlink
ancestors with lstat and realpath instead of treating unresolved paths
as ordinary missing segments. Add regression coverage for outside,
dangling, and ancestor symlink cases.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Handle mixed separators in MCP data paths

Split PLUGIN_DATA traversal checks on both slash types so mixed
separators cannot bypass lexical containment on Windows clients.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

* Reject credentials in MCP package headers

MCP headers are visible package data, so reject credential-bearing
headers including authorization, proxy authorization, cookies, and
common API-key or token names. Preserve ordinary custom headers and
add focused regression coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 764c5bb4-2811-4dc1-b61d-56c4a5597cc9
2026-08-24 10:26:18 +10:00
Rez b95e24caae Add preview deployments for PR's (#2755)
* add preview deployments

* remove workflow from paths

* reduce perm for build
2026-08-24 10:00:53 +10:00
Anton Standrik a2c85e3e7b fix(ci): grant contributor check issue read access (#2693)
Signed-off-by: astandrik <astandrik@yandex-team.ru>
2026-08-18 09:37:35 +10:00
Michael RecachinasandCopilot f48b84e6a2 Fix PRT writer permissions for fork PRs
Restore label and comment synchronization after the PRT migration by granting the downstream writer workflows the pull request permission required for fork-originated PRs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 512eb347-ec89-4250-8bf1-87048974b01d
2026-08-14 09:26:45 -04:00
Michael RecachinasandCopilot 925dc83735 Migrate pull request automation away from pull_request_target (#2625)
* Migrate pull_request_target workflows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR duplicate check writer review

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix duplicate-check writer artifact handling

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Make PR duplicate check gh-aw compilable

Configure the agentic workflow source to allow fork PR triggers with staged safe outputs, upload a PR context artifact through supported post-steps, and have the workflow_run writer consume that context before publishing validated comments. This lets gh-aw regenerate the lockfile without restoring pull_request_target or privileged PR-code execution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 512eb347-ec89-4250-8bf1-87048974b01d

* Harden workflow-run PR writers

Bind privileged artifact processing to trusted workflow-run PR identity, serialize same-PR writers, and cap aggregate quality comments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 512eb347-ec89-4250-8bf1-87048974b01d

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 512eb347-ec89-4250-8bf1-87048974b01d
2026-08-14 11:22:06 +10:00
280b05dc88 feat: surface external plugin review signals (#2623)
* feat: surface external plugin review signals

Add repository and homepage heuristics to external plugin intake and use eyes reactions for approval decisions.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: b745e915-6c5a-4354-ab77-5b52f9e66fea

* fix: harden external plugin review signals

Validate homepage destinations and bound response reads, and correct repository activity metrics.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: b745e915-6c5a-4354-ab77-5b52f9e66fea

* fix: pin external homepage requests

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: b745e915-6c5a-4354-ab77-5b52f9e66fea

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: b745e915-6c5a-4354-ab77-5b52f9e66fea
2026-08-12 10:07:30 +10:00
Aaron Powell 7b602c3370 Updating to latest agentic workflows (#2556)
* Updating to latest agentic workflows

* cleaning up tools and more explicit copilot app checks
2026-08-07 11:19:05 +10:00
a7fdcd5006 Migrate plugins and canvas extensions to Agent Plugins spec (#2546)
* feat: migrate plugins and extensions to Agent Plugins v1.0.0 spec

- Add \ to all 69 curated plugin manifests
- Migrate all 18 extension manifests: add \, move logo into
  xtensions.com.github.copilot.logo namespace, remove top-level
  logo and string xtensions: '.'
- Update eng/validate-plugins.mjs: require \, validate
  namespace-keyed extensions object for canvas extensions, widen
  name pattern to allow dots (spec §5.5, max 64 chars)
- Update eng/materialize-plugins.mjs: emit spec-clean served manifests
  (only spec fields: \, name, version, description, author,
  homepage, repository, license, keywords, extensions)
- Update eng/generate-website-data.mjs: read logo from namespace
  with fallback to top-level logo for compatibility
- Update eng/create-plugin.mjs: scaffold emits \
- Add .github/workflows/validate-plugins.yml: blocking CI for PRs
  touching plugins/** or extensions/**
- Add spec compliance check to external plugin quality gates:
  non-blocking warnings with /⚠️/🛑 emoji legend
- Update AGENTS.md: document new extension manifest shape,
  add \ to plugin checklist

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* refactor: consolidate canvas extension plugins

- Move all extension plugin manifests from extensions/<name> to plugins/<name>
- Keep extensions/<name> as reusable source only
- Remove standalone extension discovery from marketplace and website plugin catalogs
- Auto-bundle same-name extension sources during materialization
- Add build-only extensions.json references for sharing extensions across plugins
- Remove x-awesome-copilot extension metadata support
- Update validation and contributor documentation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* feat: add canvas extension scaffolding skill

- Add repo-local skill for creating canvas extension sources
- Generate spec-compliant plugin manifests under plugins/
- Support registering reusable extensions with multiple plugins
- Remove guidance for extension-local plugin manifests and custom fields

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* fix: align extension namespaces with current guidance

- Use each extension ID as its manifest namespace key
- Update validation and website generation to resolve extension-specific namespaces
- Upsert plugin validation PR comments using the existing repository pattern

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* fix: use Copilot extension namespace

- Adopt com.github.copilot for all canvas extension manifests
- Require the namespace during validation and website generation
- Update extension scaffolding guidance

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* docs: regenerate plugin catalog after merge

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* refactor(plugins): move manifests to plugin roots

Use root plugin.json manifests and namespaced extension directories throughout local tooling, validation, generation, and contributor documentation. Restore materialize-plugins.mjs line breaks so the source remains readable in GitHub.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* feat(plugins): migrate manifests to namespaced composition

Move repository composition metadata under com.github.awesome-copilot, materialize reusable extensions into the plugin extensions directory, and improve contributor and PR validation guidance.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* fix(validation): address plugin review findings

Restore executable build scripts, validate namespaced manifests and hook directories, improve README item counts, and manage validation comments across reruns.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: 8f3a88cb-e01e-4760-8125-460490dc1a76
2026-08-06 22:29:31 +10:00
Aaron Powell dab758a392 Bumping to latest Vally release and standardising on package.json version (#2535)
The workflows were doing their own vally installs, which means that we had the potential for drift in the version of Vally being used. Now we do a npm ci and get the version from there, removing the ambiguity
2026-08-04 16:49:17 +10:00
Christopher HarrisonandCopilot App cb87dae678 Seed Copilot Workshops Learning Hub mirror (#2527)
* Seed Copilot Workshops Learning Hub mirror

Perform the initial import of github-samples/copilot-workshops
(@b543d2f) into the Learning Hub, since a first-run import from the
scheduled sync workflow exceeds the 100-file safe-output PR cap.

Also update the sync workflow prompt so future runs are always
incremental and stay under the file cap.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Stop codespell flagging mirrored workshop content

codespell only knows English, so the localized Learning Hub mirrors
(es-es, ja-jp, ko-kr, pt-br, zh-cn) produce ~150 false positives such as
"comando ==> commando". Skip those locale directories, and allow the two
valid English words the mirrored pages use verbatim.

Mirrored pages must stay source-faithful, so the fix belongs in
.codespellrc rather than in the content. Note that in the sync workflow
so future runs handle new false positives the same way.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-04 15:55:03 +10:00
Aaron PowellandCopilot App 43527d1336 chore: bump contributor check AGT to v4.1.0 (#2484)
Update contributor-check workflow to fetch AGT scripts from v4.1.0.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4b935b0a-90c8-454f-958f-93b468fd4e17
2026-07-30 12:13:36 +10:00
Aaron PowellandCopilot App 8ae5a99109 Enforce external plugin ref/sha consistency (#2463)
* Enforce external plugin ref/sha consistency

Extract shared ref/sha normalization and consistency checks into eng/lib and reuse them in intake plus quality gate flows.

Add a dedicated ref/sha consistency quality gate surfaced in PR/intake summaries, and add targeted tests for matching and mismatched refs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 6afe21ad-eafa-4c90-a1f2-053dedac7625

* Address review: tree/blob ref errors and PR workflow ref/sha column

- resolveCommitShaAtReadRef: classify rev-parse failure as 'fail'
  instead of 'infra_error' because a successfully-fetched ref that
  doesn't dereference to a commit is a submitter problem, not infra.
- validateRemoteRepository (intake): treat HTTP 422 from the commit
  endpoint as a submitter error; all other non-404 errors remain
  transient warnings requiring maintainer re-run.
- external-plugin-pr-quality-gates.yml: add ref/sha consistency
  column to the per-plugin quality table and failure details block.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6afe21ad-eafa-4c90-a1f2-053dedac7625

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6afe21ad-eafa-4c90-a1f2-053dedac7625
2026-07-29 15:28:13 +10:00
7bf8a4d38b fix: add @astrojs/markdown-remark dep and fix build-website CI paths (#2457)
* fix: add @astrojs/markdown-remark dep and fix build-website CI paths

Astro 7.1.x introduced 'Satteri' as the default Markdown processor and
no longer bundles @astrojs/markdown-remark by default. The website config
uses markdown.remarkPlugins which requires this package to be installed
explicitly.

Also update build-website.yml paths to use explicit ** glob patterns
and include root package.json/package-lock.json changes as triggers,
so dependabot package bumps always run the website build check.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ed2219f7-f30c-4e24-95af-9c216166f285

* refactor: use explicit unified() processor in astro.config

Astro 7.1+ changed the markdown.remarkPlugins shorthand to require
@astrojs/markdown-remark. Update to the explicit unified() processor API
which is the supported way to use remark/rehype plugins in Astro 7.1+.

Sätteri (the new default processor) is incompatible with remark plugins,
so we stay on unified() to keep remark-github-admonitions-to-directives
working for Learning Hub GitHub admonition syntax.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ed2219f7-f30c-4e24-95af-9c216166f285

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: ed2219f7-f30c-4e24-95af-9c216166f285
2026-07-28 14:15:00 +10:00
7dc152f472 fix: exclude auto-generated README files from PR risk scan (#2454)
* fix: exclude auto-generated README files from PR risk scan

The scanner was processing README.md and docs/README.*.md which are
auto-generated by \
pm run build\ and shouldn't be reviewed for risk
patterns.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a278c6bb-22ad-4d43-8e68-60432773f987

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: a278c6bb-22ad-4d43-8e68-60432773f987
2026-07-28 11:21:47 +10:00
Aaron PowellandCopilot App 0d466ecec2 fix: strip npm warn/notice lines from Vally PR comment output (#2455)
npm install warnings (EBADENGINE, deprecated) were leaking into both
the Summary findings table and the full linter output block, making
the comment noisy. Filter them out when processing raw vally output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4c3ca9da-500e-464e-88d3-4c09535ec45c
2026-07-28 11:17:18 +10:00
8e137c3c09 Harden external plugin PR quality gate rendering and name validation (#2444)
* Harden external plugin PR quality gates

Reference: https://github.com/github/awesome-copilot/pull/2398

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a79923be-c65f-4d51-8fe3-a86e05fd02f1

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot-Session: a79923be-c65f-4d51-8fe3-a86e05fd02f1
2026-07-27 15:57:06 +10:00
Timothy Harrington 4ec36c7dbf Fix Node.js setup action version in skill quality report workflow 2026-07-23 11:56:04 -04:00
40665c23b7 Migrate extension plugin materialization to extensions container (#2334)
* Migrate extension plugin materialization layout

Materialize extension plugins into a dedicated extensions/ container, validate the new manifest convention, and bump extension plugin versions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d26008fb-9928-4ba7-b7c8-36f35320f7c1

* Keep extension manifests source-compatible

Restore source extension manifests to "extensions": "." while preserving materialization-time rewrite to "extensions" in distribution output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d26008fb-9928-4ba7-b7c8-36f35320f7c1

* Validate canvas extension layout for external submissions

Add intake and quality-gate checks for canvas-tagged external plugins so they must include extensions/extension.mjs and optional manifest extensions is validated when present.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d26008fb-9928-4ba7-b7c8-36f35320f7c1

* Fix plugin clean extension pass and typo guard text

Declare EXTENSIONS_DIR in clean-materialized-plugins and run extension cleanup once after plugin cleanup. Also normalize misspelled-key detection strings to satisfy spelling checks without changing validation behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d26008fb-9928-4ba7-b7c8-36f35320f7c1

* Proper codespell fix

* Separate canvas structure quality gate status

Track canvas structure as its own gate status and output, include it in aggregate summaries, and enforce Git object types so extensions/ is a tree and extensions/extension.mjs is a blob.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d26008fb-9928-4ba7-b7c8-36f35320f7c1

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-17 18:04:03 +10:00
65ef449bda Add Copilot Workshops sync workflow + Learning Hub i18n (#2325)
Adds an agentic (gh-aw) workflow that mirrors the multi-harness workshop
from github-samples/copilot-workshops into the Learning Hub, plus the
Starlight infrastructure it needs: GitHub-admonition rendering, i18n
locales with English at the site root, and a language picker that only
appears when a page has a non-English translation.


Copilot-Session: 9e1d1a4c-a422-4cae-8ea7-b3d5171f58e3

Co-authored-by: GeekTrainer <GeekTrainer@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-17 10:06:29 +10:00
fb80ec4f21 Add canvas-specific intake validation for external plugins (#2319)
* Add canvas-aware checks to external plugin intake

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0f03fd92-3bfa-4c67-a709-177fbd46c40e

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-16 16:58:02 +10:00
61dda50523 Add version parity checks to external plugin quality gates (#2307)
* Add external plugin version-match gate

Enforce external.json version matching against remote plugin.json for source ref and/or sha in shared quality gates, and surface the new gate status/output in intake and PR workflows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8aa3e98d-1873-4cab-8866-1b2efd0f24ad

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-16 12:39:32 +10:00
30472ecf0f Harden external plugin gate comment output safety (#2265)
* Harden external plugin gate comment rendering

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Fix gate output truncation after HTML escaping

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
2026-07-10 16:20:01 +10:00
Aaron PowellandCopilot App bb4766e226 Fix external plugin gate manifest paths and diagnostics (#2261)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-10 14:31:25 +10:00
James MontemagnoandCopilot App 34f0e35050 Fix duplicate PR check role gating (#2241)
Remove the read-only role override from the PR duplicate check so gh-aw pre-activation gates unsupported actors before the PR checkout step runs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-08 11:23:01 +10:00
e986f49695 Migrate extension metadata to plugin.json and enforce conventions (#2177)
* Remove pluginRoots property from marketplace.json

The pluginRoots property is not used by install tooling and was only
informational about the extension/plugin source directories. Removing it
simplifies the marketplace.json structure while maintaining all functionality.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Migrate java-modernization-studio to plugin.json and update validation workflow

- Create .github/plugin/plugin.json for java-modernization-studio extension
- Remove legacy canvas.json from java-modernization-studio
- Update validate-canvas-extensions.yml workflow to check for plugin.json instead of canvas.json
- Update workflow to trigger on .schemas/plugin.schema.json changes (instead of canvas.schema.json)
- Remove schema validation logic that relied on canvas.schema.json
- All 12 extensions now use plugin.json for metadata

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add extensions field to all extension plugin.json files

Per https://github.com/github/copilot-agent-runtime/pull/9929, plugins that ship
extensions need to include an extensions field specifying where the extension code
is located. All 12 extensions now have extensions set to '.' to reference the
current directory where extension.mjs is located.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Enforce convention-based extension metadata and remove x-awesome-copilot

- Remove x-awesome-copilot.screenshots from all extension plugin.json files
- Enforce logo=assets/preview.png convention for all extensions
- Enforce extensions=. per copilot-agent-runtime#9929
- Update validate-plugins.mjs to enforce conventions
- Update validate-canvas-extensions.yml workflow with convention checks
- Update AGENTS.md and CONTRIBUTING.md documentation

All 12 extensions validated successfully.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Use standard plugin validation for extensions

Remove the custom extension schema and schema validation helper, and
validate extension plugin.json files through the existing plugin validator
instead. Update workflows to stop depending on the removed schema.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-03 12:24:38 +10:00
3bd22bc0f4 Fix PR duplicate check not running on external contributor submissions (#2188)
* Initial plan

* Fix PR duplicate check not running on external contributor submissions

Add forks: [\"*\"] and roles: all to pr-duplicate-check.md so the
agentic workflow runs for all PR authors, including external contributors
submitting from forks. Previously, the generated lock.yml contained:
- A fork repository check blocking all fork PRs from running
- A team membership check (admin/maintainer/write) blocking external contributors

Recompiled with gh aw compile to regenerate pr-duplicate-check.lock.yml.
The pre_activation job (which held the membership gate) is now removed,
and the activation job runs unconditionally for all pull_request events.

Closes #2121

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fixing a bunch of warnings on all the agentic workflows

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-03 10:08:42 +10:00
Aaron Powell 235bdb1872 Fixing git sha's (#2170) 2026-07-01 11:25:14 +10:00
79cda6bb19 Add canvas schema validation to extension submission workflow (#2161)
* Add canvas schema and extension submission checks

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* fix: use namespace import for js-yaml

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

* Fix contributors page build markup

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

* Address PR feedback on canvas schema validation

- Add ajv-cli@5 as a pinned devDependency; install via npm ci in CI instead of npx --yes
- Fix screenshot path regex to prevent .. traversal segments
- Validate canvas.schema.json is parseable JSON even on schema-only PRs

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Harden canvas extension workflow against injection attacks

Switch from newline to null-terminated git diff output (git diff -z) so filenames
containing newlines are read atomically, matching the existing skill-check.yml pattern.

Add an allowlist regex guard on the extracted extension directory name immediately after
it is parsed from git diff output. Any name not matching ^[a-z0-9][a-z0-9-]*$ (e.g.
names containing dollar signs, parentheses, spaces, or other shell metacharacters) is
silently skipped before being used anywhere in the script.

Add a matching allowlist guard on each screenshot path extracted from canvas.json before
the file-existence check, so a crafted manifest cannot supply a path with shell
metacharacters or traversal segments even after the schema check passes.

Follows the same defence-in-depth pattern introduced after the injection PoCs in #1236
and #1240.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Replace ajv-cli with in-repo schema validator

- Remove ajv-cli to avoid vulnerable/deprecated transitive dependencies
- Add eng/validate-json-schema.mjs using ajv + ajv-formats
- Update validate-canvas-extensions workflow to use local script
- Use npm ci --ignore-scripts in PR validation job

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-01 10:40:40 +10:00
Aaron PowellandCopilot 28c3a14af4 Switch skill CI validation workflows to vally lint (#2030)
* Switch skill CI checks to vally lint

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Adding Vally to allowed words

* case sensitivity

* Migrate external plugin quality gates from skill-validator to vally lint

Replace the downloaded skill-validator binary with
px @microsoft/vally-cli lint
in the external plugin quality gates pipeline:

- Remove downloadSkillValidator() and SKILL_VALIDATOR_ARCHIVE_URL constant
- Replace uildSkillValidatorArgs() + 
unSkillValidatorGate() with
  uildVallyLintArgs() + 
unVallyLintGate() that run
px vally-cli lint
  per resolved skill directory (falling back to the full plugin root when no
  specific skill paths can be resolved from plugin.json)
- Rename result keys skill_validator_status / skill_validator_output
  to ally_lint_status / ally_lint_output throughout both
  ng/external-plugin-quality-gates.mjs and ng/external-plugin-intake.mjs
- Update PR comment markdown to show 'vally lint' instead of 'skill-validator'
- Update CONTRIBUTING.md prose references accordingly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Use @microsoft/vally library directly instead of vally-cli subprocess

Replace the npx-spawned vally-cli process with a direct call to the
@microsoft/vally core library in the external plugin quality gates scripts:

- Add @microsoft/vally as a devDependency in package.json
- Import runLint and LintConsoleReporter from @microsoft/vally
- Replace runVallyLintGate() process spawn with async API call:
  - runLint({ rootPath }) returns structured LintResults
  - LintConsoleReporter with a Writable capture stream collects
    text output without printing to stdout
- Make runExternalPluginQualityGates() async (propagated to
  runExternalPluginPrQualityGates() and both main entry points)
- Use Promise.all in runExternalPluginPrQualityGates() for parallel
  plugin checks
- Fix remaining skill_validator_status reference in pr-quality-gates
  summary string (now vally-lint=...) and YAML workflow table header
- Add 'npm install @microsoft/vally' step to both calling workflows

This removes a layer of indirection (Node -> npx -> CLI -> library)
and replaces it with a direct in-process library call, which is faster,
more reliable, and gives structured access to lint results.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-30 14:07:45 +10:00
7f19be7380 Fix contributor check gh api marker argument error (#2151)
* Fix contributor check comment upsert behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix contributor check jq marker filtering

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 12:23:17 +10:00
13a1dce22e Fix contributor reputation check comment deduping (#2150)
* Fix contributor check comment upsert behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-29 11:59:19 +10:00
Aaron Powell 4c852c8641 Removing the latent labels from the old branching setup (#2130) 2026-06-26 10:31:05 +10:00
Aaron PowellandCopilot f72401434f chore: remove check-pr-target workflow (#2124)
Now that main is the contributor branch and staged is retired,
no new PRs will target staged. The check-pr-target guard is
no longer needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-25 14:45:14 +10:00
Aaron PowellandCopilot 0eb6062f94 chore(phase2): retarget all automation and contributor guidance from staged to main (#2122)
* chore(phase2): retarget all automation from staged to main

- publish.yml: trigger on main, publish only to marketplace
- check-pr-target.yml: invert — now blocks PRs targeting staged, welcomes main
- 10 PR validation workflows: branches [staged] → [main]
- external-plugin-command-router.yml: --base staged → main (3×), message text
- external-plugin-rereview-command.yml: --base staged → main (2×), message text
- external-plugin-rereview.yml: staged reference in review comment text
- external-plugin-intake.yml: ref: staged checkout → main
- external-plugin-pr-quality-gates.yml: ref: staged checkout → main
- external-plugin-quality-gates.yml: ref: staged checkout → main
- check-plugin-structure.yml: error messages updated for new branch model
- contributors.yml: ref and base target → main
- setup-labels.yml: targets-main label description updated
- cli-for-beginners-sync.md + .lock.yml: base-branch staged → main
- codeowner-update.md + .lock.yml: base-branch staged → main
- learning-hub-updater.md + .lock.yml: base-branch staged → main

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(phase2): update contributor guidance from staged to main

- CONTRIBUTING.md: branch from main, PR targets main; remove Phase 2 gate note
- AGENTS.md: PR target + external plugin PR automation references
- .github/pull_request_template.md: PR checklist targets main
- website/src/content/docs/learning-hub/agentic-workflows.md: PR target

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* aw updates

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-25 14:36:53 +10:00
9c87c1bb64 Upgrade agentic workflows from gh-aw v0.72.1 to v0.80.9 (#2092)
- Recompile all 6 workflow lock files with gh-aw v0.80.9
- Update gh-aw-actions/setup v0.72.1 → v0.80.9
- Update actions/checkout v6.0.2 → v7.0.0
- Refresh container image pins across all workflows
- Fix learning-hub-updater.md: add missing permissions.contents: read
  (root cause of safe_outputs 'Failed to apply bundle' failures)
- Update dispatcher SKILL.md and agentic-workflows agent
- Update actions-lock.json and copilot-setup-steps.yml

Fixes: #2077 (learning-hub-updater), #2080 (cli-for-beginners-sync)
Part of: #2076

Co-authored-by: Ayan Gupta <ayangupta@Ayans-MacBook-Pro.local>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-23 11:25:54 +10:00
Aaron PowellandCopilot b253270faa Phase 1: split source vs published refs and verify dual publish (#2085)
* chore: finalize phase 1 marketplace migration wiring

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: avoid hardcoded source branch in plugin docs links

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-22 15:04:40 +10:00
Aaron PowellandCopilot 18654630ab fix: use pull_request_target trigger for external plugin PR quality gates (#2043)
The workflow was using the pull_request trigger which restricts
GITHUB_TOKEN to read-only for fork PRs, causing the sync-pr-state
job to fail with 403 when trying to add labels.

Switching to pull_request_target runs the workflow in the base
repo context so declared permissions (issues: write, pull-requests:
write) are honoured for cross-repository PRs.

The workflow is safe to use pull_request_target because:
- detect-changed-plugins reads files via the GitHub API only (no checkout)
- run-quality-gates checks out the trusted staged branch, not the PR head
- sync-pr-state also checks out the staged branch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-18 10:57:33 +10:00
Aaron Powell 5e0c0aa59e fixing spelling skill (#2038)
* fixing spelling skill

* adjusting path
2026-06-18 09:42:12 +10:00
2f9d85eef8 Add Agent Arcade canvas extension (#2031)
* Add Agent Arcade canvas extension

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Refine Agent Arcade canvas behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update Agent Arcade canvas credits

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update Agent Arcade canvas catalog anchor

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Ignoring the minified file

* Configure codespell to skip minified Phaser file

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>
2026-06-17 19:29:18 +10:00
Aaron PowellandCopilot 17b174fb0a Canvas manifest implementation for extensions (#2029)
* Add keyword display to extension cards on website

- Add .resource-keywords and .keyword-tag CSS styles for rendering keyword badges
- Update renderExtensionsHtml() to display keywords below extension description
- Keywords now visible on the website extensions page with styled badges
- Regenerate website data to include keyword metadata

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Canvas manifest implementation for all extensions

Add per-extension canvas manifests with:
- Structured canvas metadata (name, description, version, keywords)
- Screenshot definitions (icon and gallery with path/type)
- Relative paths for images within each extension directory

Enhance extension metadata:
- Generate meaningful descriptions from source analysis
- Extract and assign keywords for discoverability
- Store metadata in package.json and extension source files

Update website rendering and data generation:
- Include keywords in extension cards and search index
- Add per-extension canvas.json files for independent evolution
- Support screenshot metadata in manifest structure
- Generate extensions.json with full canonical paths for website

All 9 local canvas extensions now have complete manifests with descriptions, keywords, and screenshot references.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Tweaking some descriptions

* Fix description priority to prefer package.json over in-source metadata

Reverse the priority in canvasDescription so that package.json descriptions
(which contain the enhanced, manually-curated descriptions) take precedence
over older in-source descriptions extracted from createCanvas(...) calls.

This prevents regression when npm run website:data regenerates outputs,
ensuring that committed canvas.json files maintain the current descriptions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix canvas validation to skip external.json file

The validation script was treating extensions/external.json as if it were
a directory, causing false validation failures. Added check to skip files
(identified by presence of dot in filename) and only validate actual
canvas extension directories.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 15:28:15 +10:00
Aaron PowellandCopilot fae6a92c9d Centralize label management and fix permission issues (#2018)
* fix: Allow label operations on pull requests in external plugin approval workflow

The sync-merged-pr-labels job needs pull-requests: write permission to
add/remove labels on merged PRs. Previously it only had issues: write which
is for issues, not pull requests. This fixes the permission error when
workflows try to modify PR labels from a non-contributor account.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Handle 403 permission errors when creating external plugin intake labels

When running on PRs from fork contributors, the GitHub token may not have
permission to create labels in the repository. This is expected and should
not cause the workflow to fail. Allow the ensureLabel function to gracefully
handle 403 Forbidden errors in addition to 422 (label already exists) errors.

This fixes the sync-pr-state job failure in external-plugin-pr-quality-gates.yml
when run on PRs from external contributors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: Centralize label management into a single workflow_dispatch workflow

Create a new 'setup-labels' workflow that is manually dispatched and handles
all label creation and updates. This workflow:
- Creates all labels used by the repository
- Updates descriptions if labels already exist
- Reports success/failure counts
- Fails if any labels cannot be created

All individual workflows now assume labels exist and will fail (loudly) if
they don't. This makes it clear to maintainers when the setup-labels workflow
needs to be dispatched:

- label-pr-intent.yml
- skill-check-comment.yml
- external-plugin-approval-command.yml
- external-plugin-command-router.yml
- external-plugin-rereview.yml
- external-plugin-rereview-command.yml
- eng/external-plugin-intake-state.mjs

This approach is better because:
- Single source of truth for label definitions
- Avoids permission issues with fork contributors
- Clear failure modes when labels are missing
- Easier to maintain consistent label configuration
- No more scattered label creation logic across workflows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove unused ensureLabel methods and managedLabels constants

Labels are now centrally managed by the setup-labels workflow and
assumed to exist in all other workflows. Removed:

- ensureLabel() methods from all 6 workflows and 1 JS module
- managedLabels constants that were only used by ensureLabel
- Promise.all() calls that invoked ensureLabel for each label
- Updated syncManagedLabels in skill-check-comment.yml to remove ensureLabel call

All workflows now assume labels exist and will fail if they don't,
which is the desired behavior—it signals maintainers to dispatch the
setup-labels workflow when new labels need to be created.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 14:12:07 +10:00
Aaron PowellandCopilot 5fb37f6461 feat: add canvas extension validation and labeling (#2017)
- Update PR template to include canvas extension as a contribution type
- Add 'canvas-extension' label (color: E4B9FF) to label-pr-intent workflow
  with auto-detection for PRs touching extensions/**
- Add new validate-canvas-extensions.yml workflow that checks:
  - extension.mjs is present in each changed extension folder
  - assets/preview.png screenshot is present in each changed extension folder
  - Posts a REQUEST_CHANGES review with a fix guide on failure

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-17 09:44:13 +10:00
a34c98bfbf Automate external plugin update PR quality checks (#2005)
* Add PR quality gates for external plugin updates

Automate external plugin update PR review by running skill-validator and install smoke checks against changed entries in plugins/external.json. Sync PR workflow-state labels and upsert a marker-based status comment with source tree links for each changed plugin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Tighten external plugin PR workflow permissions

Scope write permissions to the PR synchronization job, keep the quality-gate job read-only, and handle no-op and detection-failure states explicitly. Also fix source tree link encoding for refs, SHAs, and plugin paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix external plugin workflow job steps

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
2026-06-16 15:40:21 +10:00
3ae6b2007c Add soft-gate PR risk scan automation for agentic PRs (#1969)
* Add soft-gate PR risk scanning automation

Introduce a PR risk scanner script plus two workflows: one to scan changed files and upload findings, and one to upsert a sticky PR comment with a summary table and findings. This adds non-blocking supply-chain risk visibility for agentic contributions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden path checks and reduce scanner false positives

Reject absolute paths, enforce repo-root containment after resolution, and tighten unpinned-version detection to dependency/version contexts to avoid markdown noise.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Harden soft-gate behavior and scanner coverage

Make PR risk scan workflows non-blocking on scanner/artifact edge cases, always upload artifacts, reduce required permissions, and extend scanner script detection to plugin skill paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-15 10:59:01 +10:00
3e4cc87e91 fix: auto-approve bot review when PR base is changed off main (#1971)
* fix: reset bot review when PR base is changed off main

The check-pr-target workflow only ran on 'opened' events targeting main,
so it never re-ran after a submitter edited the base branch to 'staged'.
The REQUEST_CHANGES review was left in place, blocking merge and requiring
a manual maintainer override.

Changes:
- Broaden trigger to also fire on edited, reopened, and synchronize events,
  and add 'staged' to the branches filter so the workflow runs after a
  base-branch edit.
- Before posting REQUEST_CHANGES, check whether the bot already has an
  active CHANGES_REQUESTED review to avoid duplicate reviews.
- After a base-branch edit: if the PR no longer targets main and the bot's
  latest review state is CHANGES_REQUESTED, post an APPROVE review to
  clear the block automatically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: rerun PR target check for any base branch

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
2026-06-12 12:21:47 +10:00
Aaron PowellandCopilot c4a0a3ef5a Route intake failures to submitter fixes (#1970)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-11 15:17:32 +10:00