Commit Graph

7 Commits

Author SHA1 Message Date
jennyf19 670c5f0419 Address GHCP review: stash race, signal ordering, a11y, outcome schema, error handling
- 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
2026-07-19 19:24:09 -07:00
jennyf19 d71864b706 fix(signals-dashboard): declare @github/copilot-sdk dependency
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
2026-07-19 18:19:22 -07:00
jennyf19 fcae8c506d fix(the-workshop): add HTTP error boundary and make workshop detection non-terminal
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
2026-07-18 19:58:49 -07:00
jennyf19 f9061f6fcc fix(signals-dashboard): coerce untrusted signal fields, block cross-site POSTs, preserve focus
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
2026-07-18 19:50:58 -07:00
jennyf19 967f0d8ede fix(signals-dashboard): harden canvas against XSS, path traversal, and malformed signals
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
2026-07-18 19:44:45 -07:00
Jenny Ferries 0f62533f11 fix(the-workshop): add signals-dashboard preview.png + logo so the canvas validates
The signals-dashboard extension was missing its required screenshot asset, so it failed awesome-copilot's validateExtensionManifest (logo must equal "assets/preview.png" and the file must exist) and never materialized -- meaning the Cairn canvas would not ship to the GHCP app. Adds the 1024x1024 preview.png and the convention logo field. Validated locally: node eng/validate-plugins.mjs -> extension signals-dashboard is valid; all 70 plugins + 19 extensions pass.

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-18 19:21:31 -07:00
Jenny Ferries 9fc4032293 feat: add signals-dashboard canvas extension
The dashboard is the centerpiece — real-time agent coordination
view showing desk status, signal types, intent text, outcome
pairing with honesty gap, token usage, and stash/restore controls.

Includes all updates from the-workshop PRs #3-#7:
- Empty state guidance for new users
- Token usage display per desk
- TA partnership signals + Cairn awareness
- Intent-as-text (execution signals use descriptive text)
- Outcome signal pairing with honesty gap calibration
- Open desk button
- Subtype labels (done/checkpoint/blocked/hands-up)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-18 19:04:34 -07:00