Skip to content

Add a Copilot Canvas extension for agentic workflow operations#42137

Merged
pelikhan merged 11 commits into
mainfrom
copilot/add-github-copilot-canvas-extension
Jun 29, 2026
Merged

Add a Copilot Canvas extension for agentic workflow operations#42137
pelikhan merged 11 commits into
mainfrom
copilot/add-github-copilot-canvas-extension

Conversation

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

This PR adds a project-scoped GitHub Copilot Canvas extension specialized for agentic workflows in github/gh-aw. It introduces a minimal, GitHub-styled dashboard for browsing workflow definitions and runs, reviewing safe markdown step summaries, dispatching predefined workflows, and invoking gh aw logs / gh aw audit commands at canvas level.

  • Extension surface and wiring

    • Added .github/extensions/agentic-workflows-dashboard with Copilot extension metadata and entrypoint.
    • Implemented canvas actions required by the spec:
      • listDefinitions(page, pageSize)
      • listRuns(page, pageSize)
      • getRun(id)
      • dispatchWorkflow(definitionId, inputs)
      • runGhAwLogs(args)
      • runGhAwAudit(args)
  • Strict TypeScript domain model + paging

    • Added strict TS models for WorkflowDefinition, WorkflowRun, WorkflowStep, and generic PagedResult<T>.
    • Implemented deterministic in-memory datasets sized for high-volume pagination (hundreds of definitions/runs).
    • Added shared pagination logic used by both UI and action handlers.
  • Dashboard UI (Alpine.js + Primer CSS, native modules)

    • Added a repository-style header, nav tabs, Box-based panels, counters, status labels, flash messaging, and muted metadata.
    • Implemented responsive multi-column layout for definitions, runs, and run detail panels.
    • Added a compact command panel supporting:
      • gh aw logs
      • gh aw logs --run <id>
      • gh aw audit
      • gh aw audit --run <id>
  • Safe markdown rendering for run summaries

    • Added constrained markdown rendering for step summaries (escaping + limited formatting transforms) before injecting into the run-detail panel.
createCanvas({
  id: "agentic-workflows-dashboard",
  actions: [
    { name: "listDefinitions", handler: (ctx) => paginate(definitions, Number(ctx.input?.page ?? 1), Number(ctx.input?.pageSize ?? 20)) },
    { name: "listRuns", handler: (ctx) => paginate(runs, Number(ctx.input?.page ?? 1), Number(ctx.input?.pageSize ?? 20)) },
    { name: "getRun", handler: (ctx) => ({ run: findRun(String(ctx.input?.id ?? "")) }) },
    { name: "dispatchWorkflow", handler: (ctx) => dispatchWorkflow(String(ctx.input?.definitionId ?? ""), ctx.input?.inputs ?? {}) },
    { name: "runGhAwLogs", handler: (ctx) => runGhAwLogs(String(ctx.input?.args ?? "")) },
    { name: "runGhAwAudit", handler: (ctx) => runGhAwAudit(String(ctx.input?.args ?? "")) }
  ]
});

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Add Copilot canvas extension for agentic workflows dashboard Add a Copilot Canvas extension for agentic workflow operations Jun 28, 2026
Copilot AI requested a review from pelikhan June 28, 2026 21:47
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot

  • configure vitest tests
  • add makefile target to compile canvas and run tests
  • take screenshots using playwright

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot a tabbed view design so that it is easy and modular to add views

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot

  • configure vitest tests
  • add makefile target to compile canvas and run tests...

Implemented in bc6ad18.

  • Configured Vitest for .github/extensions/agentic-workflows-dashboard and added unit tests (test/pagination.test.ts).
  • Added make test-canvas-extension to compile the canvas extension and run its tests.
  • Captured dashboard screenshots with Playwright and added:
    • .github/extensions/agentic-workflows-dashboard/screenshots/dashboard-full.png
    • .github/extensions/agentic-workflows-dashboard/screenshots/dashboard-viewport.png

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot modularize to allow reuse, apply SOLID, DRY, YAGNI.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot also wire gh aw audit-diff and gh aw compile commands

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot

  • move css to separate file
  • add makefile target to lint/fmt

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot init impeccable (https://github.com/pbakaus/impeccable) for the canvas

Configure it as a github.com like experience for exploring, managing, running agentic workflows.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot modularize to allow reuse, apply SOLID, DRY, YAGNI.

Addressed in 2735ec5 and 6dfe1c2. I refactored the dashboard to a reusable tab model with shared view-switch helpers, removed duplicated run-detail navigation logic, and added guarded tab selection for cleaner SOLID/DRY behavior while keeping scope minimal.

@copilot a tabbed view design so that it is easy and modular to add views

Implemented in 2735ec5 and finalized in 6dfe1c2. The dashboard now uses a metadata-driven tabbed view system (Workflows/Runs/Run details/Commands), with each view rendered as an independent panel to make future view additions modular.

Copilot AI and others added 2 commits June 28, 2026 22:35
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot also wire gh aw audit-diff and gh aw compile commands

Implemented in 06e1f42 (plus follow-up polish in 4e3d023): wired gh aw compile and gh aw audit-diff in both canvas actions and the command panel behavior/quick-fill paths.

@copilot init impeccable (https://github.com/pbakaus/impeccable) for the canvas

Configure it as a github.com like experience for exploring, managing, running agentic workflows.

Implemented in 06e1f42: initialized Impeccable context for this canvas with .impeccable/config.json and PRODUCT.md, and aligned the dashboard toward a GitHub-like exploration/operations experience.

@pelikhan pelikhan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot make fmt / lint targets run the new fmt/lint dashboard targets

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot make fmt / lint targets run the new fmt/lint dashboard targets

Implemented in 5f11d4e. make fmt now runs fmt-canvas-extension, and make lint now runs lint-canvas-extension.

@pelikhan pelikhan marked this pull request as ready for review June 28, 2026 22:58
Copilot AI review requested due to automatic review settings June 28, 2026 22:58
Copilot AI requested a review from pelikhan June 28, 2026 22:58
@pelikhan

Copy link
Copy Markdown
Collaborator

/matt

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request introduces a project-scoped GitHub Copilot Canvas extension that provides a lightweight “agentic workflows” dashboard surface (definitions, runs, run details, and a command panel), along with build/lint/fmt targets wired into the repo Makefile.

Changes:

  • Added a new Copilot Canvas extension under .github/extensions/agentic-workflows-dashboard, including the extension entrypoint (extension.mjs) and a static dashboard UI (Primer CSS styling + Alpine.js-driven views).
  • Introduced a strict TypeScript domain model + pagination helper (with Vitest coverage for pagination) and compiled runtime assets under web/.
  • Integrated extension formatting/linting/testing into top-level make fmt, make lint, and added a dedicated test-canvas-extension target.
Show a summary per file
File Description
Makefile Adds build/test/fmt/lint targets for the Canvas extension and wires fmt/lint into existing top-level targets.
.github/extensions/agentic-workflows-dashboard/web/styles.css Adds minimal dashboard-specific CSS utilities (shell spacing, scroll containers, selection styling).
.github/extensions/agentic-workflows-dashboard/web/pagination.js Adds web runtime pagination helper used by the dashboard bundle.
.github/extensions/agentic-workflows-dashboard/web/models.js Adds an (empty) module stub emitted for TS module boundary.
.github/extensions/agentic-workflows-dashboard/web/index.html Adds the dashboard HTML template (Primer layout, tabbed panels, and markdown summary rendering surface).
.github/extensions/agentic-workflows-dashboard/web/app.js Adds the dashboard’s Alpine.js app runtime (definitions/runs datasets, command simulation, safe markdown rendering).
.github/extensions/agentic-workflows-dashboard/vitest.config.ts Configures Vitest discovery for extension tests.
.github/extensions/agentic-workflows-dashboard/tsconfig.json Defines strict TypeScript compilation settings and emits JS into web/.
.github/extensions/agentic-workflows-dashboard/test/pagination.test.ts Adds unit tests for pagination behavior.
.github/extensions/agentic-workflows-dashboard/src/pagination.ts Adds typed pagination helper used by TS sources.
.github/extensions/agentic-workflows-dashboard/src/models.ts Adds strict domain model types for definitions, runs, steps, and paged results.
.github/extensions/agentic-workflows-dashboard/src/app.ts Adds typed dashboard runtime (rendering logic, command simulation, and safe markdown rendering).
.github/extensions/agentic-workflows-dashboard/PRODUCT.md Documents product intent and UI design lane for the extension.
.github/extensions/agentic-workflows-dashboard/package.json Defines extension package scripts/deps (build, lint, test, fmt).
.github/extensions/agentic-workflows-dashboard/package-lock.json Locks dependency tree for the extension.
.github/extensions/agentic-workflows-dashboard/extension.mjs Implements the Copilot Canvas extension (actions, in-memory data, and dashboard open() URL rendering).
.github/extensions/agentic-workflows-dashboard/copilot-extension.json Adds Copilot extension metadata (name/version).
.github/extensions/agentic-workflows-dashboard/.impeccable/config.json Enables Impeccable detector config for the dashboard’s web assets.

Review details

Tip

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

Files not reviewed (1)
  • .github/extensions/agentic-workflows-dashboard/package-lock.json: Generated file
  • Files reviewed: 17/20 changed files
  • Comments generated: 8
  • Review effort level: Low

Comment thread .github/extensions/agentic-workflows-dashboard/web/index.html Outdated
Comment thread .github/extensions/agentic-workflows-dashboard/web/index.html Outdated
Comment thread .github/extensions/agentic-workflows-dashboard/web/index.html Outdated
Comment on lines +3 to +19
export function paginate<T>(items: T[], page: number, pageSize: number): PagedResult<T> {
const totalItems = items.length;
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
const safePage = Math.min(Math.max(1, page), totalPages);
const start = (safePage - 1) * pageSize;
const end = start + pageSize;

return {
items: items.slice(start, end),
page: safePage,
pageSize,
totalItems,
totalPages,
hasNextPage: safePage < totalPages,
hasPreviousPage: safePage > 1,
};
}
Comment on lines +60 to +67
const status = statuses[index % statuses.length] ?? "queued";
const definition = sourceDefinitions[index % sourceDefinitions.length];
const stepStatuses = stepStatusMap[status] ?? stepStatusMap.queued;

return {
id: `run-${String(index).padStart(5, "0")}`,
definitionId: definition.id,
status,
Comment on lines +137 to +140
</main>
</div>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.15.0/dist/cdn.min.js"></script>
<script type="module">
Comment on lines +209 to +218
async function renderDashboardUrl() {
const htmlPath = join(__dirname, "web", "index.html");
const appPath = join(__dirname, "web", "app.js");
const cssPath = join(__dirname, "web", "styles.css");

const [htmlTemplate, appBundle, cssBundle] = await Promise.all([readFile(htmlPath, "utf8"), readFile(appPath, "utf8"), readFile(cssPath, "utf8")]);

const html = htmlTemplate.replace("/*__APP_CSS__*/", cssBundle).replace("/*__APP_JS__*/", appBundle);
return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
}
Comment on lines +10 to +26
"devDependencies": {
"typescript": "6.0.3",
"vitest": "4.1.9"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run",
"lint": "npm run typecheck && npm test",
"fmt": "npm run fmt:ts && npm run fmt:html && npm run fmt:css && npm run fmt:js && npm run fmt:json",
"fmt:ts": "npx prettier --write --parser typescript \"src/**/*.ts\" \"test/**/*.ts\" \"vitest.config.ts\"",
"fmt:html": "npx prettier --write --parser html \"web/index.html\"",
"fmt:css": "npx prettier --write --parser css \"web/styles.css\"",
"fmt:js": "npx prettier --write --parser babel \"extension.mjs\"",
"fmt:json": "npx prettier --write --parser json \"copilot-extension.json\" \"package.json\"",
"impeccable:detect": "npx impeccable detect web/index.html web/styles.css"
}
@github-actions

Copy link
Copy Markdown
Contributor

Review complete: 3 blocking issues, 4 medium priority

Applied /tdd, /zoom-out, /improve-codebase-architecture, /grill-with-docs, and /diagnose. Verdict: REQUEST_CHANGES.

🔴 Blocking (must fix)
# Location Issue
1 extension.mjs:116 runs.unshift() mutates shared module-level state — no session isolation
2 test/pagination.test.ts Zero tests for renderSafeMarkdown, runGhCommand, dispatchWorkflow
3 web/app.js TypeScript compiler output committed alongside source — drift risk
🟡 Medium priority
# Location Issue
4 tsconfig.json:16 Test directory excluded from typecheck
5 src/app.ts:190 runFlagMatch hoisted with implicit branch-ordering dependency
6 extension.mjs:151 Command handling duplicated client-side and server-side with no documented relationship
7 src/app.ts:358 UI dispatch creates separate in-memory run vs canvas dispatchWorkflow action
8 extension.mjs:67 Missing null guard on definition.id (present in app.ts but not .mjs)

@copilot please address the review comments above.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 139.1 AIC · ⌖ 10.1 AIC · ⊞ 6.6K ·
Comment /matt to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd, /zoom-out, /improve-codebase-architecture, /grill-with-docs, and /diagnose — requesting changes on three blocking issues.

📋 Key Themes & Findings

Blocking Issues

  1. Mutable global state (extension.mjs:116) — runs.unshift() mutates module-level state shared across all sessions. In any multi-user deployment this is a correctness bug.

  2. Test coverage gap (test/pagination.test.ts) — 414-line app.ts and 353-line extension.mjs contain complex branchy logic (renderSafeMarkdown, runGhCommand, dispatchWorkflow) with zero tests. The HTML injection surface and command parser both need coverage before this ships.

  3. Generated artifacts committed (web/app.js) — TypeScript compiler output is checked in alongside source, creating silent drift risk on every src/*.ts edit.

Medium Priority

  • tsconfig.json excludes test/ — test files not type-checked by npm run typecheck
  • runFlagMatch hoisted with implicit branch-ordering dependency — fragile, needs localisation and tests
  • Command handling duplicated between extension.mjs and app.ts with no documented relationship
  • dispatchSelectedWorkflow() operates on a separate dataset from the canvas dispatchWorkflow action — no documented design intent

Positive Highlights

  • ✅ Clean domain model in src/models.ts with strict TypeScript (noUncheckedIndexedAccess, exactOptionalPropertyTypes)
  • ✅ Generic paginate<T> function with proper clamping and tested behaviour
  • escapeHtml runs before all inline transforms — XSS fundamentals are sound
  • ✅ Makefile integration (test-canvas-extension, lint-canvas-extension, fmt-canvas-extension) is well-structured
  • ✅ Progressive disclosure design in the Primer-based UI is clean and consistent

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 139.1 AIC · ⌖ 10.1 AIC · ⊞ 6.6K
Comment /matt to run again

pelikhan and others added 3 commits June 28, 2026 16:39
…K dep

- Replace data URI with a per-instance loopback HTTP server; the runtime
  rejects data: scheme URLs with canvas_provider_url_disallowed
- Serve web/app.js and web/pagination.js as separate routes so the ES
  module import chain resolves correctly from the loopback origin
- Add onClose handler to shut down the server when a panel is closed
- Fix Alpine.js x-for directives: move them from <div> to <template>
  elements as required by Alpine v3 (list rendering was silently broken)
- Remove @github/copilot-sdk from package.json dependencies; the CLI
  auto-resolves the SDK, and listing it risks installing a conflicting
  version if someone runs npm install

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Alpine's defer script fires alpine:init before the type=module app.js
has run, so Alpine.data('dashboardApp') was never registered and the
dashboard rendered blank.

Fix: import Alpine as an ESM module directly in app.js and call
Alpine.start() at the end of the module. This gives the module full
control over startup order — Alpine.data() is registered synchronously
before Alpine.start() walks the DOM.

- Remove the defer CDN script tag from index.html (Alpine is now
  imported by app.js via the +esm CDN path)
- Remove the document.addEventListener('alpine:init', ...) wrapper;
  register Alpine.data() at module scope instead
- Add Alpine.start() at the end of app.js

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- extension.mjs: use execFile to call ./gh-aw (dev) or gh aw (installed);
  add /api/status, /api/runs, /api/run-command, /api/refresh routes;
  add 60s result cache; add systemMessage with CLI usage instructions;
  assign workspacePath after joinSession; remove all dummy data functions
- web/app.js: fetch from /api/* endpoints; map real field names
  (workflow, engine_id, run_id, workflow_name, duration, token_usage, turns,
  error_count); add loadingDefinitions/loadingRuns/error state; add refresh()
- web/index.html: update templates for real field names; add loading spinners;
  replace step list in Details tab with metrics grid; add Refresh button;
  update Commands tab quick-fill buttons to real commands

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

Copy link
Copy Markdown
Contributor

🤖 PR Triage — §28342769269

Field Value
Category feature
Risk high
Score 69/100
Priority high
Action fast_track
Status Ready — CI passing, CHANGES_REQUESTED needs resolution

Score breakdown: Impact 42 · Urgency 15 · Quality 12

Rationale: New GitHub Copilot Canvas extension for agentic workflow operations (+2777/−2, 20 files). Significant new product surface: dashboard for browsing workflow definitions/runs, dispatching workflows, and invoking gh aw logs/gh aw audit at canvas level. CI passing. Active engagement from @pelikhan requesting make fmt/lint on dashboard code; skills-based review has CHANGES_REQUESTED with 3 blocking issues.

Next steps:

  1. Run make fmt on the dashboard code per @pelikhan
  2. Address the 3 blocking issues from the skills-based review
  3. Ready for expedited human review once resolved

Generated by 🔧 PR Triage Agent · 107.8 AIC · ⌖ 10.9 AIC · ⊞ 5.4K ·

@pelikhan pelikhan merged commit d84a05a into main Jun 29, 2026
35 checks passed
@pelikhan pelikhan deleted the copilot/add-github-copilot-canvas-extension branch June 29, 2026 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants