The plugin manifest lists signals-dashboard under x-awesome-copilot.extensions and eng/materialize-plugins.mjs copies it into the materialized plugin, so the canvas files do ship with the plugin. Reworded the TA 'Viewing signals' section to drop the 'installed separately from the plugin' claim and instead state only that the canvas does not auto-load and must be installed and registered separately to show the live board.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
The Workshop TA agent's "Viewing signals" section said the Cairn
canvas "ships bundled with the-workshop plugin." It doesn't — Cairn is
the standalone signals-dashboard extension, installed separately (the
plugin's own README already documents this). Correct the section and
give the awesome-copilot install command
(copilot plugin install signals-dashboard@awesome-copilot) so the
agent's "run cairn" flow has reliable, accurate steps.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
- extension.mjs: serialize stash read-modify-write behind a per-desk mutex;
order signals by explicit ISO timestamp (clone-safe) not mtime; keep desks
with malformed latest signal as 'awaiting'; gate calibration badge on a real
gap value; add prefers-reduced-motion CSS; toast aria-live region; rename
open_desk -> get_desk_path (returns path, no session); handle server.listen errors.
- signal-write/SKILL.md: document timestamp + run_id, ordering guidance, and the
outcome (calibration) signal schema.
- workshop-ta.agent.md: a desk is a persistent workstream picked up by independent
sessions, not one long-running process.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
The signals-dashboard canvas is a standalone extension, not bundled in
the-workshop plugin. Removes the same inaccurate 'bundled' phrasing the
README fix corrected, keeping the subtype guidance intact.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
The dashboard is a canvas extension that ships standalone, not bundled
in the plugin. Installing the-workshop delivers skills/agent/desks only;
the signals-dashboard canvas installs separately and renders in the
GitHub Copilot app. Replaces the false 'bundled... nothing else to
install' claim with the real two-install path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
signals-dashboard imports '@github/copilot-sdk/extension' but shipped
without a package.json — the only SDK-importing extension in the repo
missing one (every peer that imports the SDK declares it). Without the
manifest the host has no dependency to resolve at load time. Add a
package.json matching the peer shape (type: module, main: extension.mjs,
'@github/copilot-sdk': latest — the modal peer convention).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
Two follow-up review findings:
- signals-dashboard: the async createServer callback had no top-level
error boundary, so a malformed %-encoded path, a stash write on a
read-only workshop, or a scan failure rejected a promise the server
never awaits — hanging the request and risking an unhandled-rejection
crash. Wrap the handler and return a controlled 500.
- workshop-create: Path A treated finding a marker (desks/, CAIRN.md,
etc.) as 'just use it', an early stop that left partially initialized
workshops incomplete. Make it detection-only and continue scaffolding
whatever is missing, per the 'only add what's missing' principle.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
Address the remaining doc/skill review findings:
- workshop-create: 'gh repo create --clone' clones into the CWD, which
nests the new repo when run from inside a checkout. Add an explicit
clone-parent selection + 'rev-parse --is-inside-work-tree' guard, and
run the create from that parent.
- workshop-create: desks/ and bench/ were scaffolded empty, so Git drops
them and a later clone loses the scaffold. Scaffold .gitkeep in each
and commit the placeholders.
- bench-read: make <workshop>/bench/ the primary shared location (the
directory workshop-create actually establishes) with desk-local
artifacts as a secondary source, instead of treating the repo root as
the bench.
- the-workshop README: add the Workshop Create skill to the component
table so all six packaged components are documented.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
Second review round on the Cairn canvas extension:
- XSS via numeric fields: self-assessment scores, quality rating, and
token counts are read from unvalidated agent JSON and interpolated
into HTML/style/title. Coerce them at the source in scanSignals via
toScore (clamped 0..5) and toCount (finite nonnegative int), and
esc() the effort label, so a nonnumeric value can neither inject
markup nor break layout/width.
- CSRF: /api/stash, /api/restore, /api/open are state-changing loopback
POSTs that previously accepted any origin, so a web page that guessed
the port could mutate .desk-stash.json. Add isCrossSiteRequest() and
reject cross-site POST /api/* (Origin / Sec-Fetch-Site check), mirroring
the loopback protection in connector-namespaces/server.mjs.
- Accessibility: the 5s auto-refresh replaced the whole #content subtree,
dropping keyboard focus. Skip the swap when markup is unchanged and
restore focus to the same desk/action button when it does change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
Address PR review findings on the Cairn canvas extension:
- XSS: replace inline onclick handlers (which used HTML-escape that
does not escape single quotes) with event delegation via
data-act/data-desk attributes and one document click listener that
survives the innerHTML auto-refresh.
- Path traversal: add isValidDeskName() and enforce it in every HTTP
and canvas-action handler that takes a desk name (reject empty, /,
\\, null byte, '.' and '..').
- Crash safety: String()-coerce in esc()/truncate() and guard
outcomeIssues with Array.isArray so a malformed signal cannot take
down the whole dashboard render.
- Honest UI: the per-desk button no longer claims to 'open' a desk;
it is relabeled 'path' and copies the desk's filesystem path to the
clipboard with an accurate toast built via textContent (not innerHTML).
- Correctness: outcome signals only pair with a signal when emitted at
or after it (within 1hr), and activeCount is computed by excluding
stashed desks instead of subtracting counts (no longer goes negative).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
The signals-dashboard canvas extension bundles with the-workshop
plugin (x-awesome-copilot.extensions), so installing the plugin from
awesome-copilot includes the dashboard. Drop the pointers telling
users to install from jennyf19/the-workshop.
Addresses PR review comments on README (Cairn Dashboard section),
signal-write SKILL note, and workshop-ta agent viewing-signals note.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62