Skip to content

the-workshop: desk cards open an in-place Copilot CLI (prefer a wrapper CLI when installed)#2363

Merged
codemillmatt merged 8 commits into
github:mainfrom
jennyf19:cairn-open-launch
Jul 20, 2026
Merged

the-workshop: desk cards open an in-place Copilot CLI (prefer a wrapper CLI when installed)#2363
codemillmatt merged 8 commits into
github:mainfrom
jennyf19:cairn-open-launch

Conversation

@jennyf19

@jennyf19 jennyf19 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Syncs the signals-dashboard (Cairn) canvas extension to jennyf19/the-workshop@f3d2298.

What changed

Each desk card in the Cairn dashboard had a path button that copied the desk's filesystem path. It is now an open button: clicking it launches a Copilot CLI right in that desk's folder, oriented to read the desk journal and continue. This mirrors the workshop app's console launcher and keeps every desk inside the one workshop repo rather than a separate checkout elsewhere on disk.

Behavior

  • Prefers a wrapper agent CLI when one is on PATH (for example an agency wrapper that preconfigures MCPs), so users who have it get a fully configured desk.
  • Falls back to vanilla copilot for everyone else, so it works out of the box.
  • Override with WORKSHOP_DESK_AGENT=copilot to force vanilla, or =agency to insist on the wrapper (authoritative even when the wrapper is not detected on PATH).
  • Graceful: if no terminal can be launched from the host, it copies the desk path instead. No new dependencies (node builtins only).

New open_desk canvas action; /api/open/<name> now returns whether a terminal launched.

Security hardening (addressing review)

  • PATH detection requires a genuinely runnable file (X_OK on POSIX, a PATHEXT match on Windows) — a directory or non-executable agency no longer wins auto-detection.
  • Launch target is realpath-contained to the workshop root, so a symlinked desk cannot escape the repo (callers stat() through symlinks).
  • Desk names that reach a shell are restricted to a conservative slug, and the orientation prompt is quote-free — no untrusted text reaches a shell parser.
  • Mutating /api/* routes require the canonical loopback Host (127.0.0.1:<port>) plus a per-server capability token echoed by the page, in addition to the existing CSRF check — defeating DNS rebinding. Mirrors extensions/connector-namespaces/server.mjs.
  • The dashboard copies the desk path only on the non-launch fallback, never after a successful open.

Scope

  • extensions/signals-dashboard/extension.mjs (synced to the-workshop's committed version)
  • plugins/the-workshop/README.md (one line documenting the open button)
  • plugin.json and assets/preview.png are unchanged.

Provenance and validation

  • Source of truth: jennyf19/the-workshop@f3d2298
  • node eng/validate-plugins.mjs passes (all 70 plugins, 19 extensions, and the external catalog valid).

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@bc708fe

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 26faf13e-639c-4a21-ac05-c0dc2bff7c62
@jennyf19
jennyf19 requested a review from aaronpowell as a code owner July 20, 2026 17:50
Copilot AI review requested due to automatic review settings July 20, 2026 17:50
@github-actions github-actions Bot added canvas-extension PR touches canvas extensions plugin PR touches plugins labels Jul 20, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

🟡 Contributor Reputation Check: MEDIUM risk

Check Risk
Profile MEDIUM
Credential audit NONE

Maintainers: please review this contributor before merging.
See the workflow run for full details.
Automated check powered by AGT.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor reputation check flagged MEDIUM risk label Jul 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔒 PR Risk Scan Results

Scanned 2 changed file(s).

Severity Count
🔴 High 0
🟠 Medium 0
ℹ️ Info 0

✅ No matching risk patterns were detected in changed files.

This is an automated soft-gate report. Findings indicate review targets and do not block merge by themselves.

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

Syncs the Cairn dashboard with upstream desk-launch behavior.

Changes:

  • Adds cross-platform desk terminal launching and an open_desk action.
  • Updates dashboard behavior and Workshop documentation.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
extensions/signals-dashboard/extension.mjs Adds desk CLI launching and UI/API integration.
plugins/the-workshop/README.md Documents the desk open button.

Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
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
Copilot AI review requested due to automatic review settings July 20, 2026 18:10

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

extensions/signals-dashboard/extension.mjs:69

  • spawn only confirms that the launcher process was created, not that the terminal opened successfully. In particular, osascript can emit spawn and then exit nonzero when Apple Events are denied or the script fails, yet this reports launched: true and suppresses the fallback message. Please observe early launcher failure (and the osascript exit status) before returning success.
            child.on("spawn", () => done(true, child));
            setTimeout(() => done(true, child), 600);

Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Synced from the-workshop@8106dd4. Addresses the second GHCP review pass on github#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
Copilot AI review requested due to automatic review settings July 20, 2026 18:28

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

extensions/signals-dashboard/extension.mjs:70

  • Resolving on spawn only confirms that the terminal-emulator process exists, not that it opened a terminal. For example, on a headless Linux host gnome-terminal can emit spawn and then exit nonzero because no display is available; this returns launched: true, suppresses both the remaining emulator attempts and the documented clipboard fallback. Allow a short-lived nonzero exit to report failure before treating a still-running process as launched.
            child.on("spawn", () => done(true, child));
            setTimeout(() => done(true, child), 600);

Comment thread extensions/signals-dashboard/extension.mjs Outdated
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
Copilot AI review requested due to automatic review settings July 20, 2026 18:36

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread extensions/signals-dashboard/extension.mjs Outdated
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
Copilot AI review requested due to automatic review settings July 20, 2026 18:41

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread extensions/signals-dashboard/extension.mjs
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs
Comment thread extensions/signals-dashboard/extension.mjs
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
Copilot AI review requested due to automatic review settings July 20, 2026 18:55

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
Comment thread extensions/signals-dashboard/extension.mjs Outdated
…nd 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
Copilot AI review requested due to automatic review settings July 20, 2026 19:04

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 20, 2026 21:22

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.

Review details

Comments suppressed due to low confidence (1)

extensions/signals-dashboard/extension.mjs:73

  • spawn only confirms that the launcher process was created, not that it opened a terminal. For example, osascript can start and then exit nonzero when Terminal automation is denied, and a Linux emulator can start and fail when no display/session bus is available. This currently returns launched: true, suppressing the documented clipboard fallback even though no terminal appeared. Account for launcher failure/readiness (at least early nonzero exits, with platform-specific handling where needed) before reporting success.
            const child = spawn(cmd, args, { detached: true, stdio: "ignore", ...opts });
            child.on("error", () => done(false));
            child.on("spawn", () => done(true, child));
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@codemillmatt
codemillmatt merged commit ff8719e into github:main Jul 20, 2026
13 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

canvas-extension PR touches canvas extensions needs-review:MEDIUM Contributor reputation check flagged MEDIUM risk plugin PR touches plugins

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants