wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<!--
  One project: its worktrees side by side, its repositories and boards, its
  notes and links, and the sessions run in its worktrees.

  The middle level between the machine and a worktree's workbench. What is
  shown about each worktree is the home's row with more of it — the path, the
  exact commit, the upstream — because this is where worktrees are compared.
-->
<script lang="ts">
  import { untrack } from "svelte";
  import { levels } from "../../stores/levels.svelte.js";
  import WorktreeRow from "./WorktreeRow.svelte";
  import NewWorktreeForm from "./NewWorktreeForm.svelte";
  import PlacedSessions from "./PlacedSessions.svelte";
  import ProjectGitHub from "./ProjectGitHub.svelte";
  import AnnotationsPanel from "../annotations/AnnotationsPanel.svelte";

  interface Props {
    project: string;
  }

  let { project }: Props = $props();

  const found = $derived(levels.project(project));
  const home = $derived(levels.home(project));

  // The project named is the trigger; what loading it reads is not.
  $effect(() => {
    const name = project;
    untrack(() => {
      void levels.ensureLoaded();
      void levels.loadProject(name);
    });
  });

</script>

<div class="project">
  <h1>{project}</h1>

  {#if levels.loaded && !found}
    <p class="empty">There is no project {project} on this machine.</p>
  {:else}
    {#if found}
      <p class="subtle"><code>{found.path}</code>{found.github ? ` · ${found.github}` : " · no GitHub origin"}</p>
    {/if}
    {#if levels.slotsError}
      <p class="slots-error" role="alert">prj could not list its session slots: {levels.slotsError}</p>
    {/if}

    <section aria-label="Worktrees">
      <div class="section-title">Worktrees</div>
      <div class="worktrees">
        {#each found?.worktrees ?? [] as worktree (worktree.id)}
          <article class="worktree-card">
            <WorktreeRow {worktree} detailed />
          </article>
        {/each}
      </div>
      <div class="new">
        <NewWorktreeForm {project} />
      </div>
    </section>

    <div class="columns">
      <section aria-label="GitHub">
        <div class="section-title">GitHub</div>
        <ProjectGitHub {project} />
      </section>
      <section aria-label="Notes and links">
        {#if found?.github}
          <AnnotationsPanel about="project:{found.github}" writeInto={home?.id ?? null} />
        {:else if found}
          <p class="empty">
            {project} has no GitHub origin, so notes and links cannot name it: add its GitHub
            repository as <code>origin</code> in its main worktree.
          </p>
        {/if}
      </section>
      <section aria-label="Sessions">
        <div class="section-title">Sessions in its worktrees</div>
        <PlacedSessions place={{ project }} limit={30} />
      </section>
    </div>
  {/if}
</div>

<style>
  .project {
    max-width: 1400px;
    margin: 0 auto;
    padding: var(--wb-spacing-24) var(--wb-spacing-20);
  }

  h1 {
    font-size: var(--wb-font-size-18);
    font-weight: 600;
    margin: 0;
    color: var(--vscode-editor-foreground);
  }

  code {
    font-family: var(--vscode-editor-font-family, monospace);
  }

  section {
    margin-top: var(--wb-spacing-20);
  }

  .worktrees {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: var(--wb-spacing-12);
  }

  .worktree-card {
    border: 1px solid var(--vscode-panel-border);
    border-radius: var(--wsb-radius-lg);
    background: var(--vscode-sideBar-background);
    overflow: hidden;
  }

  .new {
    margin-top: var(--wb-spacing-10);
  }

  .slots-error {
    color: var(--wb-error);
    font-size: var(--wb-font-size-12);
  }

  .columns {
    display: grid;
    grid-template-columns: minmax(240px, 1fr) minmax(280px, 1.5fr) minmax(320px, 2fr);
    gap: var(--wb-spacing-24);
  }

  @media (max-width: 767px) {
    .columns {
      grid-template-columns: 1fr;
    }
  }
</style>