Commit Graph

14 Commits

Author SHA1 Message Date
jennyf19 8ec1fe86d7 fix Cairn desk-launch containment + comment accuracy (GHCP review round 6)
Sync signals-dashboard/extension.mjs to the-workshop@f3d2298.

- isInsideRoot: reuse the trailing separator when the workshop root is a filesystem root (/ or C:\\) so desks below it aren't rejected.

- Correct the launch guard comment (macOS single-quotes deskPath; Linux uses cwd).

- Replace the stale double-quote-rejection claim with the real containment + quoting guarantees.

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 12:04:28 -07:00
jennyf19 563148b5b4 harden Cairn desk launch (GHCP review round 5)
Sync signals-dashboard/extension.mjs to the-workshop@91c09d7.

- Render the desk open button unconditionally.

- Drop the deskPath double-quote guard (path is quoted/cwd/single-quoted per platform; guard rejected valid POSIX paths).

- Escape CR/LF in AppleScript string literals.

- On Windows run the agent through cmd.exe /k so PATHEXT resolves .cmd shims (copilot/agency).

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 11:55:23 -07:00
jennyf19 e43d6ea666 signals-dashboard: trySpawn resolves only from spawn/error
Synced from the-workshop@3cd8a0c6a1e24864d746fedb1f2f7ee4f3b17603. Round-4 review: remove the success timeout that could report an unconfirmed launch as launched:true; Node guarantees one of spawn/error fires.

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 11:41:51 -07:00
jennyf19 df4f3ebc42 signals-dashboard: drop unused existsSync import
Synced from the-workshop@591591c. Round-3 review: existsSync became dead after PATH validation moved to statSync/accessSync.

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 11:36:24 -07:00
jennyf19 055dda1672 signals-dashboard: harden desk launch (round 2 review)
Synced from the-workshop@8106dd4. Addresses the second GHCP review pass on #2363:

- isOnPath now requires a runnable file (X_OK / PATHEXT), not just existsSync.

- launchDeskConsole adds a realpath-containment check (symlink escape) and takes workshopDir.

- Dashboard copies the path only on the non-launch fallback.

- Mutating /api/* routes now require the canonical loopback Host plus a per-server capability token (DNS-rebinding defense), mirroring connector-namespaces.

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 11:28:43 -07:00
jennyf19 d4656d988d fix(the-workshop): harden signals-dashboard desk launch
Addresses the Copilot review on this PR:

- deskAgentArgv: an explicit WORKSHOP_DESK_AGENT override is now
  authoritative. =agency insists on the wrapper even when it isn't on
  PATH; the PATH check is only used for automatic selection when unset.
- launchDeskConsole: restrict the desk name to a conservative slug
  before it reaches any shell, and drop the double quotes from the
  orientation prompt, so the cmd.exe `start` fallback can no longer be
  turned into command execution by a desk directory named e.g.
  "review&calc".
- macOS: drive Terminal via AppleScript to actually cd into the desk and
  exec the agent (POSIX single-quoted), instead of only opening Terminal
  and falsely reporting the CLI launched.
- Linux: pass the agent command after each emulator's exec flag, so the
  desk comes up running its agent instead of a bare shell.
- Client openDesk: track whether the clipboard write succeeded and stop
  claiming "path copied" when the browser blocked it.

Synced from the-workshop@8e22ce84b2b28d9c2205730b1cd52db8586a0416

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

Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 11:09:46 -07:00
jennyf19 517506a260 feat(the-workshop): sync signals-dashboard to the-workshop@bc708fe
Brings the awesome-copilot copy of the signals-dashboard (Cairn) extension to parity with jennyf19/the-workshop@bc708fe. The desk cards' path button becomes an open button: clicking it launches a Copilot CLI in that desk's folder, oriented to read the journal and continue, mirroring the workshop app's console launcher. This keeps every desk inside the one workshop repo instead of spinning off a separate checkout.

The launcher prefers a wrapper agent CLI when one is on PATH (env-overridable via WORKSHOP_DESK_AGENT), and falls back to vanilla 'copilot' otherwise, so it works out of the box for everyone. New open_desk canvas action; /api/open now returns whether a terminal launched. plugin.json and assets/preview.png are unchanged.

Provenance: jennyf19/the-workshop@bc708fe905

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
2026-07-20 10:49:35 -07:00
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