## Metadata

#### Name

present_preview

#### Updated

last month

#### Source

[GitHub source](https://github.com/idemeum/skills/blob/main/presentPreview.ts)

#### Risk

Low

#### Requires consent

false

#### Affected scope

user

## Code

````
/**
 * mcp/skills/presentPreview.ts — present_preview synthetic tool
 *
 * Like wait_for_user_ack, this is NOT a normal tool — it is a registration
 * shim for a first-class G4 gate (the "present-preview" gate) routed
 * specially in electron/agent/guards/execution.ts:executeStep().
 *
 * Why a tool at all?
 * ------------------
 * Agent plans reference tools by name. Registering present_preview in the
 * MCP tool registry lets the planner emit it as a plan step and the
 * execution LLM see its Zod schema (so it passes structured params like
 * { title, summary, categories }). But the actual `run()` below is never
 * invoked — G4 detects `meta.isUserWaitGate: true` and routes the step
 * through runPresentPreviewGate() instead of the normal tool-execution
 * pipeline.
 *
 * Schema overview
 * ---------------
 * Top-level (required): title, summary, categories[] (min 1)
 * Per category (required): id (stable kebab-case), label, summary
 * Per category (optional): detail, defaultSelected (defaults true),
 *   destructive (defaults false)
 *
 * Returns
 * -------
 *   { selected: string[] }
 *
 * The string array contains the category ids the user kept checked.
 * Empty array means cancel / dismiss / timeout / no items checked.
 */

import { z } from "zod";

// -- Meta ---------------------------------------------------------------------

export const meta = {
  name: "present_preview",
  description:
    "Presents a categorised preview of pending actions to the user and " +
    "waits for their selection. Use when a SKILL.md step says 'summarise " +
    "and confirm', 'present a consolidated preview', or 'ask the user " +
    "which categories to proceed with'.\n" +
    "Empty array means cancel / dismiss / timeout / zero items.",
  riskLevel: "low",
  destructive: false,
  requiresConsent: false,
  supportsDryRun: false,
  affectedScope: ["user"],
  auditRequired: true,
  /**
   * The routing flag. G4's executeStep reads this and dispatches to
   * runPresentPreviewGate() — the run() below is never invoked on the
   * normal path.
   */
  isUserWaitGate: true,
  schema: {
    title: z
      .string()
      .min(1)
      .describe(
        "Short heading shown at the top of the preview card " +
        "(e.g. 'Cleanup Plan')."
      ),
    summary: z
      .string()
      .min(1)
      .describe(
        "One-sentence framing shown under the title; typically mentions " +
        "the aggregated total recovery / impact " +
        "(e.g. 'You can recover 8.2 GB by cleaning the following:'). " +
        "Author writes the shape with {placeholder} tokens; executor LLM " +
        "substitutes runtime numbers from scratchpad before invoking."
      ),
    categories: z
      .array(
        z.object({
          id: z
            .string()
            .min(1)
            .describe(
              "Stable kebab-case identifier returned in the gate result — " +
              "subsequent corrective steps reference this id via " +
              "inputsFrom / When: clauses. Must NOT be derived from " +
              "`label` (label edits or localization would silently break " +
              "cross-step references). Unique within one call."
            ),
          label: z
            .string()
            .min(1)
            .describe(
              "Short user-facing name shown next to the checkbox " +
              "(e.g. 'Browser caches')."
            ),
          summary: z
            .string()
            .min(1)
            .describe(
              "One-line description rendered next to the label, typically " +
              "count + size " +
              "(e.g. 'Chrome, Safari, Edge — 1.2 GB' or " +
              "'12 installer files over 50 MB (3.4 GB)'). Author writes " +
              "the shape with {placeholder} tokens; executor LLM " +
              "substitutes runtime numbers from scratchpad."
            ),
          detail: z
            .string()
            .optional()
            .describe(
              "Optional extra bullet text shown when the user expands the " +
              "category. Use sparingly."
            ),
          defaultSelected: z
            .boolean()
            .optional()
            .describe(
              "Whether the checkbox is checked by default. Defaults to " +
              "true. Set false for destructive or non-obvious categories."
            ),
          destructive: z
            .boolean()
            .optional()
            .describe(
              "When true, the renderer shows a ⚠ icon and warning style. " +
              "Combine with defaultSelected: false so the user must " +
              "explicitly opt in."
            )
        })
      )
      .min(1)
      .describe(
        "Ordered list of categories the user can pick from. Min 1 entry."
      ),
  },
} as const;

// -- Exported run function ----------------------------------------------------

/**
 * Safety-net stub. The run() function is never invoked on the normal path —
 * G4's executeStep() detects meta.isUserWaitGate and routes to
 * runPresentPreviewGate() in electron/agent/guards/execution.ts, bypassing
 * the normal tool-execution pipeline. If this throws, the routing is broken.
 */
export async function run(): Promise<never> {
  throw new Error(
    "present_preview.run() was invoked directly — this should never happen. " +
    "G4 is expected to route steps whose tool.meta.isUserWaitGate is true " +
    "through runPresentPreviewGate() in electron/agent/guards/execution.ts, " +
    "bypassing the normal tool-execution pipeline. Check G4's executeStep() " +
    "routing."
  );
}
````
