Extension edit tutorial - #2806
Conversation
🔒 PR Risk Scan ResultsScanned 7 changed file(s).
Skipped non-text or missing files
|
There was a problem hiding this comment.
Pull request overview
Adds an installable canvas extension that turns Copilot code edits into interactive tutorials.
Changes:
- Implements walkthroughs, quizzes, exercises, progress persistence, and agent review.
- Registers and documents the new plugin.
- Adds marketplace metadata and visual assets.
Reviewed changes
Copilot reviewed 8 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
extensions/edit-tutorial/extension.mjs |
Implements the canvas and local server. |
extensions/edit-tutorial/package.json |
Defines extension dependencies. |
extensions/edit-tutorial/copilot-extension.json |
Declares extension metadata. |
extensions/edit-tutorial/README.md |
Documents setup and usage. |
extensions/edit-tutorial/assets/icon.png |
Provides extension iconography. |
extensions/edit-tutorial/assets/preview.png |
Provides the plugin preview. |
plugins/edit-tutorial/plugin.json |
Registers the installable plugin. |
plugins/edit-tutorial/README.md |
Documents plugin installation. |
docs/README.plugins.md |
Adds the plugin to documentation. |
.github/plugin/marketplace.json |
Adds the marketplace entry. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const server = createServer(async (req, res) => { | ||
| const url = new URL(req.url, "http://localhost"); | ||
| const state = getState(instanceId); |
| var bset = {}, aset = {}; | ||
| b.forEach(function (l) { if (l.trim()) bset[l.trim()] = true; }); | ||
| a.forEach(function (l) { if (l.trim()) aset[l.trim()] = true; }); |
|
|
||
| if (url.pathname === "/request-tutorial" && req.method === "POST") { | ||
| if (sessionRef) { | ||
| try { await sessionRef.send(buildTutorialRequestPrompt()); } catch {} |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 10 changed files in this pull request and generated 4 comments.
Suppressed comments (1)
extensions/edit-tutorial/extension.mjs:603
- When the exercise is active, that state is represented only by CSS, so assistive technology cannot determine which step is current. Expose the active state with
aria-current="step"here as well.
if (view.kind === "exercise") exCls += " active";
if (S.progress.exercise.completed) exCls += " done";
html += '<button class="' + exCls + '" onclick="gotoExercise()">' +
(S.progress.exercise.completed ? "✓ " : "") + "Exercise</button>";
| var allPass = true; | ||
| lastCheckResults = ex.checks.map(function (c) { | ||
| var pass = false; | ||
| try { pass = new RegExp(c.pattern, c.flags || "m").test(codeText); } catch (err) { pass = false; } |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 10 changed files in this pull request and generated 1 comment.
Suppressed comments (3)
extensions/edit-tutorial/extension.mjs:978
- The synchronous fallback defeats the hard time budget.
screenPatternaccepts catastrophic bounded alternations such as^(a|aa){50}$, so when Blob workers are unavailable this loop can freeze the canvas on learner input. Treat unfinished checks as stalled rather than evaluating them on the UI thread, including the equivalentworker.onerrorfallback.
var inline = function () {
var out = [], k;
for (k = 0; k < checks.length; k++) {
try { out.push(new RegExp(checks[k].pattern, checks[k].flags || "m").test(codeText)); }
catch (err) { out.push(false); }
extensions/edit-tutorial/extension.mjs:1058
- A timeout produces
nullresults and is presented as “could not be run,” but it still incrementsfailedAttempts. Three infrastructure stalls therefore unlock the reference solution even though the learner has not failed a check. Increment this counter only when at least one check actually returnedfalse.
} else {
pe.failedAttempts++;
}
extensions/edit-tutorial/extension.mjs:1039
- A learner can keep editing while the worker runs, but this guard only detects tutorial replacement/reset. If the captured
codeTextpasses and the editor has since changed to failing code, the callback still marks the current attempt complete. Also compare the current exercise code withcodeTextand discard stale results.
if (!S.tutorial || !S.progress || S.tutorial.exercise.checks !== ex.checks) {
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>
| if (index < 0 || index >= info.count || index === info.index) return; | ||
| var forward = index > (info.index || 0); | ||
| lessonSwitching = true; | ||
| api("/lesson", { method: "POST", body: JSON.stringify({ index: index }) }) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| postProgress() | ||
| .catch(function () {}) | ||
| .then(function () { | ||
| return api("/lesson", { method: "POST", body: JSON.stringify({ index: index }) }); |
|
There's still some |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
Tested and found bug. Resolving. |
Pull Request Checklist
npm startand verified thatREADME.mdis up to date.mainbranch for this pull request.Description
Canvas extension where Copilot tutors the user on code changes so that they can
understand the updates applied to the codebase.
Test Conditions
Evaluation Context
Copilot Pro+ Plan Credit Usage
Prompt
Results
Good. The patch to the repo pilot-matter worked. It got creative with the test, making math variations.
Below are screenshots of the tutorial it gave me.
Note
The images were resized, so slightly distorted; in order for each screenshot
to fit on the same composition.
Type of Contribution
By submitting this pull request, I confirm that my contribution abides by the Code of Conduct and will be licensed under the MIT License.