Product / Workspace patterns

A place for different perspectives.

UI specimens grounded in the current Rails app, with proposed patterns clearly identified.

Fictional data throughout. This guide never calls the application or an AI provider.

Conversation

The actual app uses a conversation list, participant controls, message states, and a composer with mentions and commands. This specimen demonstrates the layout; it does not contact an AI provider.

Pilot planning

Product exploration · Open discussion

You

What should we learn before scaling the pilot?

Strategist · AI advisor

Start with one question: can a smaller trial change our decision?

  • Define an observable outcome.
  • Keep the first group small.
  • Agree on a review date.

Critic · AI advisor

What would make us stop? Write that down before starting.

Ctrl+Enter to send · @ to mention · / for commands

0 / 4000

Conversations

Product exploration / Pilot planning / Open

Participants

Strategist and Critic are fictional AI advisors.

View HTML
<div class="sc-workspace">
  <aside>
    <label for="workspace-space" class="sc-label">Space</label>
    <select id="workspace-space" class="select w-full">
      <option>Product exploration</option>
      <option>Personal research</option>
    </select>
    <p class="mt-6 mb-3 font-bold">Conversations</p>
    <ul class="menu p-0">
      <li>
        <a href="#conversation" aria-current="page">
          Pilot planning
          <span class="badge badge-sm">Open</span>
        </a>
      </li>
      <li>
        <a href="#memory">Research notes</a>
      </li>
    </ul>
    <label class="mt-5 flex items-center gap-3 text-sm">
      <input class="checkbox" type="checkbox" data-archive-toggle>
      Show archived example
    </label>
    <p data-archived-item class="mt-3 text-sm" hidden>Earlier research · Archived</p>
  </aside>
  <section>
    <div class="flex flex-wrap items-center justify-between gap-3 border-b border-line pb-4">
      <div>
        <h3 class="font-bold">Pilot planning</h3>
        <p class="sc-help">Product exploration · Open discussion</p>
      </div>
      <button class="btn btn-outline" data-dialog-open="participants">Participants</button>
      <button class="btn btn-outline md:hidden" data-dialog-open="mobile-conversations">Conversations</button>
    </div>
    <div class="mt-5 space-y-4" data-chat-log>
      <article class="sc-message">
        <p class="text-sm font-bold">
          You
          <time class="ml-2 font-normal text-muted">09:41</time>
        </p>
        <p class="mt-3">What should we learn before scaling the pilot?</p>
      </article>
      <article class="sc-message">
        <p class="text-sm font-bold">
          Strategist · AI advisor
          <time class="ml-2 font-normal text-muted">09:42</time>
        </p>
        <div class="sc-prose mt-3">
          <p>Start with one question: can a smaller trial change our decision?</p>
          <ul>
            <li>Define an observable outcome.</li>
            <li>Keep the first group small.</li>
            <li>Agree on a review date.</li>
          </ul>
        </div>
        <button class="btn btn-ghost mt-3" data-copy="Define an observable outcome, keep the first group small, and agree on a review date.">Copy response</button>
      </article>
      <article class="sc-message">
        <p class="text-sm font-bold">Critic · AI advisor</p>
        <p class="mt-3">What would make us stop? Write that down before starting.</p>
      </article>
    </div>
    <p id="copy-status" role="status" class="sc-help"></p>
    <form data-composer class="mt-6 border-t border-line pt-5">
      <label for="composer" class="sc-label">Your message</label>
      <textarea id="composer" class="textarea w-full" rows="3" maxlength="4000" required aria-describedby="composer-help composer-count" placeholder="Ask a follow-up or invite another view…"></textarea>
      <div class="mt-2 flex flex-wrap justify-between gap-2 text-xs text-muted">
        <p id="composer-help">Ctrl+Enter to send · @ to mention · / for commands</p>
        <p id="composer-count" data-char-count>0 / 4000</p>
      </div>
      <div class="mt-3 flex flex-wrap gap-2" aria-label="Insert mention">
        <button class="btn btn-sm" type="button" data-insert="@all ">@all</button>
        <button class="btn btn-sm" type="button" data-insert="@strategist ">@strategist</button>
      </div>
      <div class="mt-4 flex flex-wrap gap-3">
        <button class="btn btn-primary" type="submit">Send example message</button>
        <button class="btn btn-outline" type="button" data-scroll-latest>Latest message ↓</button>
      </div>
      <p data-composer-status role="status" class="sc-help"></p>
    </form>
  </section>
</div>
<dialog id="mobile-conversations" class="sc-dialog" aria-labelledby="mobile-title">
  <h3 id="mobile-title" class="font-bold">Conversations</h3>
  <p class="my-5">Product exploration / Pilot planning / Open</p>
  <button class="btn" data-dialog-close autofocus>Return to conversation</button>
</dialog>
<dialog id="participants" class="sc-dialog" aria-labelledby="participants-title">
  <h3 id="participants-title" class="text-xl font-bold">Participants</h3>
  <p class="my-4">Strategist and Critic are fictional AI advisors.</p>
  <label for="participant-model" class="sc-label">Illustrative model</label>
  <select id="participant-model" class="select w-full">
    <option>Default enabled model</option>
    <option>Another configured model</option>
  </select>
  <label class="my-5 flex gap-3 items-center">
    <input type="checkbox" class="checkbox">
    Allow configured tools
  </label>
  <button class="btn btn-primary" data-dialog-close autofocus>Close example</button>
</dialog>

Message states

Keep pending, responding, failed, and completed responses distinct. Existing app controllers own retry and generation. Here the retry updates a local status only.

Explorer · AI advisor

Waiting for response…

Strategist · AI advisor

Responding…

Preserve the message region while content arrives.

Critic · AI advisor

This advisor couldn’t respond.

View HTML
<div class="grid gap-4">
  <article class="sc-message" aria-busy="true">
    <p class="font-bold">Explorer · AI advisor</p>
    <p class="mt-3">
      <span class="loading loading-dots" aria-hidden="true"></span>
      Waiting for response…
    </p>
  </article>
  <article class="sc-message" aria-busy="true">
    <p class="font-bold">Strategist · AI advisor</p>
    <p class="mt-3">Responding…</p>
    <p class="sc-help">Preserve the message region while content arrives.</p>
  </article>
  <article class="sc-message">
    <p class="font-bold">Critic · AI advisor</p>
    <p class="mt-3 text-danger">This advisor couldn’t respond.</p>
    <button class="btn btn-outline mt-4" data-retry>Retry example</button>
    <p role="status" class="sc-help" data-retry-status></p>
  </article>
  <article class="sc-message">
    <p class="font-bold">You attached memory</p>
    <a class="mt-3 inline-block text-brand-link underline" href="#memory">Pilot research notes ↗</a>
  </article>
</div>

Rich content and interactions

Keep long content readable. The app may expose raw model interactions; never include credentials in the visible details.

Explorer · AI advisor

Compare the smallest useful alternatives:

  1. Observe the current process.
  2. Test one change with a small group.
if evidence_changes_decision:
    review_next_step()
Model interaction example
Status
Completed
Provider/model
Illustrative configured model
Tool calls
No tools used
View HTML
<article class="sc-message sc-prose">
  <p class="font-bold">Explorer · AI advisor</p>
  <p>Compare the smallest useful alternatives:</p>
  <ol>
    <li>Observe the current process.</li>
    <li>Test one change with a small group.</li>
  </ol>
  <pre>
    <code>if evidence_changes_decision:
    review_next_step()</code>
  </pre>
  <details>
    <summary>Model interaction example</summary>
    <dl class="mt-3">
      <dt class="font-bold">Status</dt>
      <dd>Completed</dd>
      <dt class="font-bold mt-2">Provider/model</dt>
      <dd>Illustrative configured model</dd>
      <dt class="font-bold mt-2">Tool calls</dt>
      <dd>No tools used</dd>
    </dl>
  </details>
</article>

Councils and advisors

Advisor identity combines a name, role, and AI designation. These controls demonstrate selection without creating records.

Choose AI advisors
Rules of engagement

View HTML
<form data-demo-form class="space-y-5">
  <label for="new-council" class="sc-label">Council name</label>
  <input class="input w-full" id="new-council" value="Product perspectives" required>
  <fieldset class="space-y-3">
    <legend class="font-bold mb-3">Choose AI advisors</legend>
    <label class="flex items-center gap-3">
      <input class="checkbox" type="checkbox" checked>
      Strategist · AI advisor · Planning
    </label>
    <label class="flex items-center gap-3">
      <input class="checkbox" type="checkbox" checked>
      Critic · AI advisor · Assumptions
    </label>
    <label class="flex items-center gap-3">
      <input class="checkbox" type="checkbox">
      Explorer · AI advisor · Alternatives
    </label>
  </fieldset>
  <fieldset class="space-y-3">
    <legend class="font-bold mb-3">Rules of engagement</legend>
    <label class="flex items-center gap-3">
      <input class="radio" type="radio" name="engagement" checked>
      Open — mentioned advisors respond
    </label>
    <label class="flex items-center gap-3">
      <input class="radio" type="radio" name="engagement">
      Consensus — discuss toward agreement
    </label>
    <label class="flex items-center gap-3">
      <input class="radio" type="radio" name="engagement">
      Brainstorming — explore ideas in rounds
    </label>
  </fieldset>
  <button class="btn btn-primary">Save example council</button>
  <p role="status" class="sc-help"></p>
</form>

AI-assisted forms

The app has pending, result, and error partials for assisted form filling. Review a generated draft before applying it.

Pending

Preparing an advisor draft…

Draft ready

Review before applying in the app.

Couldn’t prepare the draft

Your instructions remain available. Try again or continue editing.

View HTML
<div class="grid gap-4 md:grid-cols-3">
  <article class="sc-card">
    <h3 class="font-bold">Pending</h3>
    <p class="mt-3" aria-busy="true">Preparing an advisor draft…</p>
  </article>
  <article class="sc-card">
    <h3 class="font-bold">Draft ready</h3>
    <label for="draft-description" class="sc-label mt-3">Description</label>
    <textarea id="draft-description" class="textarea w-full" rows="4">Explores overlooked alternatives and asks what else might work.</textarea>
    <p class="sc-help">Review before applying in the app.</p>
  </article>
  <article class="sc-card">
    <h3 class="font-bold text-danger">Couldn’t prepare the draft</h3>
    <p class="mt-3">Your instructions remain available. Try again or continue editing.</p>
  </article>
</div>

Memory

The existing app supports memory lists, search, editing, attachments, export, and version history. This local filter searches fictional entries.

Pilot research notes

Product exploration · Updated 6 November 2026

A small pilot can help test assumptions before a larger commitment.

Version history

Run the whole program.
Start with a small pilot and explicit review criteria.

Illustrative versions; additions and removals have text and visual markers.

Download example note

Open questions

Which observation would change our decision?

2 example memories

View HTML
<label for="memory-search" class="sc-label">Search example memories</label>
<input id="memory-search" type="search" class="input w-full" placeholder="Search by title" data-memory-search>
<div class="mt-5 space-y-3" data-memory-list>
  <article class="sc-card" data-memory-item="Pilot research notes">
    <h3 class="font-bold">Pilot research notes</h3>
    <p class="sc-help">Product exploration · Updated 6 November 2026</p>
    <p class="mt-3">A small pilot can help test assumptions before a larger commitment.</p>
    <details class="mt-4">
      <summary>Version history</summary>
      <p class="mt-3 sc-diff">
        <del>Run the whole program.</del>
        <br>
        <ins>Start with a small pilot and explicit review criteria.</ins>
      </p>
      <p class="sc-help">Illustrative versions; additions and removals have text and visual markers.</p>
    </details>
    <a href="downloads/examples/report.md" download class="btn btn-outline mt-4">Download example note</a>
  </article>
  <article class="sc-card" data-memory-item="Open questions">
    <h3 class="font-bold">Open questions</h3>
    <p class="mt-3">Which observation would change our decision?</p>
  </article>
</div>
<p data-memory-status role="status" class="sc-help">2 example memories</p>
<form data-demo-form class="mt-6">
  <label for="memory-editor" class="sc-label">Edit example memory</label>
  <textarea id="memory-editor" class="textarea w-full" rows="4" required>Define the pilot's success criteria before inviting participants.</textarea>
  <button class="btn btn-primary mt-3">Save example</button>
  <p role="status" class="sc-help"></p>
</form>

Settings

Provider forms and enabled model selection use standard controls. This example submits nothing and never accepts an actual secret.

Disabled specimen. Never enter a real credential here.

Illustrative model names, not a provider catalog.

View HTML
<form data-demo-form class="grid gap-5 sm:grid-cols-2">
  <div>
    <label for="provider" class="sc-label">Provider</label>
    <select class="select w-full" id="provider">
      <option>OpenAI</option>
      <option>OpenRouter</option>
    </select>
  </div>
  <div>
    <label for="api-key-demo" class="sc-label">API key example</label>
    <input id="api-key-demo" type="password" class="input w-full" value="example-not-a-key" disabled aria-describedby="key-help">
    <p id="key-help" class="sc-help">Disabled specimen. Never enter a real credential here.</p>
  </div>
  <div>
    <label for="model-filter" class="sc-label">Filter example models</label>
    <input id="model-filter" class="input w-full" type="search" data-model-filter placeholder="Search models">
    <div class="mt-4 space-y-3">
      <label class="flex items-center gap-3" data-model-item="Planning model">
        <input class="toggle" type="checkbox" checked>
        Planning model
      </label>
      <label class="flex items-center gap-3" data-model-item="Exploration model">
        <input class="toggle" type="checkbox">
        Exploration model
      </label>
    </div>
  </div>
  <div>
    <label for="default-model" class="sc-label">Default model</label>
    <select id="default-model" class="select w-full">
      <option>Planning model</option>
    </select>
    <p class="sc-help">Illustrative model names, not a provider catalog.</p>
  </div>
  <button class="btn btn-primary">Save example settings</button>
  <p role="status" class="sc-help"></p>
</form>

Authentication and empty states

Use familiar sign-in controls and a useful next action when no records exist. This form is a visual specimen only.

Sign in

Fictional, disabled credential specimen.

Your next idea starts here.

Start a conversation or bring your council together.

Explore a conversation
View HTML
<div class="grid gap-6 md:grid-cols-2">
  <form data-demo-form class="sc-card">
    <h3 class="text-xl font-bold mb-5">Sign in</h3>
    <label for="auth-email" class="sc-label">Email</label>
    <input type="email" id="auth-email" class="input w-full" value="person@example.com" readonly>
    <label for="auth-password" class="sc-label mt-4">Password example</label>
    <input type="password" id="auth-password" class="input w-full" value="example-only" disabled>
    <p class="sc-help">Fictional, disabled credential specimen.</p>
    <button class="btn btn-primary mt-5">Preview sign-in feedback</button>
    <p role="status" class="sc-help"></p>
  </form>
  <div class="sc-empty">
    <h3 class="text-xl font-bold">Your next idea starts here.</h3>
    <p class="mt-4 text-muted">Start a conversation or bring your council together.</p>
    <a class="btn btn-primary mt-5" href="#conversation">Explore a conversation</a>
  </div>
</div>

Synthesis and dissent

Design proposal from the supplied kit, not a claim of a shipped synthesis feature. A summary does not establish consensus.

Proposed synthesis · Open disagreement

Start small, with a decision rule.

Recommendation
Run a limited pilot and review what it changes.
Agreement
Strategist and Explorer favor a small experiment.
Dissent
Critic wants an explicit stopping rule before starting.
Next step
The user reviews the reasoning and decides.

Illustrative reasoning. Agreement is not evidence of factual correctness.

View HTML
<article class="sc-card">
  <span class="badge badge-warning">Proposed synthesis · Open disagreement</span>
  <h3 class="mt-5 text-xl font-bold">Start small, with a decision rule.</h3>
  <dl class="mt-5 space-y-4">
    <div>
      <dt class="font-bold">Recommendation</dt>
      <dd>Run a limited pilot and review what it changes.</dd>
    </div>
    <div>
      <dt class="font-bold">Agreement</dt>
      <dd>Strategist and Explorer favor a small experiment.</dd>
    </div>
    <div>
      <dt class="font-bold">Dissent</dt>
      <dd>Critic wants an explicit stopping rule before starting.</dd>
    </div>
    <div>
      <dt class="font-bold">Next step</dt>
      <dd>The user reviews the reasoning and decides.</dd>
    </div>
  </dl>
  <p class="sc-help mt-5">Illustrative reasoning. Agreement is not evidence of factual correctness.</p>
</article>