Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ When every development cell is infected, World Lab automatically pauses playback

World Lab provides browser-owned absolute run targets of **25, 50, 100, 200, 500, and 1,000**. The session-selected target defaults to 200, past/current targets are unavailable, and a bounded run pauses at the authoritative completed-turn target unless cancellation, failure, or full infection stops it first.

The compact command navbar keeps execution controls and current known cost in one persistent row and moves detailed experiment telemetry, playback speed, and infrequent actions into accessible hover/focus popovers. Its control slots remain stable while async state changes. Explicit agent-marker selection drives the inspector, while explicit H3 selection opens a dismissible map-local details card. Blackberry/teal/mint/celadon/vanilla semantic tokens define the dark application chrome without replacing domain-owned agent and alliance colors.
The persistent operator shell keeps execution controls, run target, playback speed, current turn, known cost, and run state visible while switching between Live and Agents workspaces. Live centers the map between an independently scrolling agent rail and semantic Scoreboard, Agent, Hex, and Run inspector tabs; a bounded activity dock separates public chat, events, and safe failure/recovery records. Agent configuration uses the same mounted execution controller and existing server-authoritative mutations, so workspace switching cannot duplicate or interrupt playback. Infrequent and destructive operations remain in the accessible overflow menu. Blackberry/teal/mint/celadon/vanilla semantic tokens define the dark application chrome without replacing domain-owned agent and alliance colors.

The agent roster defaults to browser-local **Follow turn** behavior: the inspector follows the active request, or the next scheduled agent while paused. Selecting an agent manually disables following without hiding the roster's textual Acting/Next marker; the preference remains in that browser and is never exported. Public world chat and the event log are newest-first bounded feeds, and the shared Model and Export dialogs keep their headers/actions fixed while their bodies scroll within the viewport.

Expand Down
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Tenth focused slice: add versioned configurable World Lab scenarios, actual H3 g

Temporary experiment hardening adds explicitly opted-in browser-lifetime unattended recovery with one to three one-call retries and one attributed skip. It does not replace the future server-owned scheduler or simultaneous-tick recovery policy.

Eleventh focused slice: redesign World Lab as a persistent long-running experiment operator workspace with a single execution controller, Live and Agents workspaces, a compact agent rail, contextual Scoreboard/Agent/Hex/Run inspection, and a bounded tabbed activity dock. This reorganizes existing authoritative configuration and telemetry without adding gameplay mechanics or persistent run storage.

## PR 5 — Goals and memory

Persistent short- and long-term objectives, compact memories, plan revision, summaries, and longer simulation runs.
Expand Down
285 changes: 285 additions & 0 deletions apps/world-lab/src/app/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,242 @@
color: var(--text);
}

/* Long-running experiment operator workspace */
.command-navbar {
grid-template-columns:
minmax(285px, auto) minmax(150px, auto) minmax(0, 1fr)
auto;
}
.command-brand {
gap: 10px;
}
.workspace-switcher,
.tab-list {
display: flex;
align-items: center;
gap: 3px;
}
.workspace-switcher {
margin-left: 10px;
padding-left: 12px;
border-left: 1px solid var(--line);
}
.workspace-switcher button,
.tab-list button {
min-height: 34px;
padding: 6px 10px;
border: 1px solid transparent;
border-radius: 4px;
background: transparent;
color: var(--text-muted);
cursor: pointer;
}
.workspace-switcher button:hover,
.tab-list button:hover:not(:disabled) {
color: var(--text);
background: var(--surface-hover);
}
.workspace-switcher button[aria-current='page'],
.tab-list button[aria-selected='true'] {
border-color: color-mix(in srgb, var(--blackberry-cream) 70%, var(--line));
background: color-mix(in srgb, var(--blackberry-cream) 34%, var(--surface));
color: var(--vanilla-custard);
}
.labeled-command {
min-height: 36px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 7px;
padding: 7px 11px;
white-space: nowrap;
}
.compact-speed-control {
min-height: 36px;
margin: 0;
padding: 0 7px;
display: flex;
align-items: center;
gap: 6px;
border: 1px solid var(--line);
border-radius: 4px;
color: var(--text-muted);
font-size: 0.72rem;
}
.compact-speed-control select {
border: 0;
background: transparent;
}
.destructive-actions {
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid color-mix(in srgb, var(--danger) 45%, transparent);
}
.operator-workspace {
grid-template-columns: clamp(260px, 18vw, 292px) minmax(420px, 1fr) clamp(
320px,
24vw,
380px
);
gap: 1px;
background: var(--line);
}
.operator-inspector {
display: grid;
grid-template-rows: auto auto minmax(0, 1fr);
overflow: hidden;
}
.inspector-heading,
.activity-dock-header,
.workspace-heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.inspector-heading {
padding: 12px 14px 8px;
}
.operator-inspector > .tab-list {
padding: 0 10px 8px;
overflow-x: auto;
}
.inspector-tabpanel {
min-height: 0;
overflow-y: auto;
padding: 0 8px 12px;
}
.operator-facts {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1px;
margin: 14px 0 0;
background: var(--line);
}
.operator-facts > div {
min-width: 0;
padding: 10px;
background: var(--surface);
}
.operator-facts dt {
color: var(--text-muted);
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.07em;
}
.operator-facts dd {
margin: 4px 0 0;
color: var(--vanilla-custard);
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
overflow-wrap: anywhere;
}
.activity-dock {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
min-width: 0;
min-height: 0;
background: var(--surface);
border-top: 1px solid var(--line);
}
.activity-dock-header {
min-height: 48px;
padding: 6px 12px;
border-bottom: 1px solid var(--line);
}
.activity-dock > .panel {
min-height: 0;
height: 100%;
overflow: auto;
border: 0;
}
.activity-dock > .panel > .dock-heading {
display: none;
}
.recovery-panel ol {
max-height: 100%;
margin: 0;
padding: 8px 14px;
display: grid;
gap: 5px;
list-style: none;
overflow: auto;
}
.recovery-panel li {
display: grid;
grid-template-columns: minmax(180px, auto) 1fr auto;
gap: 12px;
padding: 7px 10px;
border-left: 3px solid var(--danger);
background: var(--surface-raised);
}
.agents-workspace {
min-height: 0;
overflow: hidden;
display: grid;
grid-template-columns: clamp(260px, 20vw, 310px) minmax(0, 1fr);
background: var(--line);
gap: 1px;
}
.agents-configuration {
min-width: 0;
min-height: 0;
padding: 16px;
overflow: auto;
background: var(--background);
}
.workspace-heading {
margin-bottom: 14px;
padding-bottom: 14px;
border-bottom: 1px solid var(--line);
}
.agents-configuration .model-console {
position: static;
}
.agents-configuration .agent-inspector {
margin-top: 14px;
}
@media (max-width: 1280px) {
.command-navbar {
grid-template-columns:
minmax(250px, auto) minmax(130px, auto) minmax(0, 1fr)
auto;
}
.operator-workspace {
grid-template-columns: 248px minmax(390px, 1fr) 320px;
}
.command-controls .cancel-request-slot,
.compact-speed-control > span {
display: none;
}
}
@media (max-width: 1050px) {
.operator-workspace {
grid-template-columns: 220px minmax(0, 1fr) 300px;
}
.status-popover,
.failed-turn-controls.inactive {
display: none;
}
.command-navbar {
grid-template-columns: auto minmax(0, 1fr) auto;
}
}
@media (max-width: 820px) {
.operator-workspace {
grid-template-columns: minmax(0, 1fr);
}
.operator-workspace .agent-roster,
.operator-workspace .operator-inspector {
display: none;
}
.agents-workspace {
grid-template-columns: 220px minmax(0, 1fr);
}
.command-navbar {
overflow-x: auto;
}
}

* {
box-sizing: border-box;
}
Expand Down Expand Up @@ -1870,3 +2106,52 @@ dt,
min-width: 570px;
}
}

/* Final operator-shell layout precedence. */
.command-navbar {
grid-template-columns:
minmax(285px, auto) minmax(150px, auto) minmax(110px, auto)
minmax(0, 1fr) auto;
}
.operator-workspace {
grid-template-columns: clamp(260px, 18vw, 292px) minmax(420px, 1fr) clamp(
320px,
24vw,
380px
);
}
.activity-dock {
grid-template-columns: minmax(0, 1fr);
}
@media (max-width: 1280px) {
.command-navbar {
grid-template-columns:
minmax(250px, auto) minmax(130px, auto) minmax(100px, auto)
minmax(0, 1fr) auto;
}
.operator-workspace {
grid-template-columns: 248px minmax(390px, 1fr) 320px;
}
.command-brand {
display: flex;
}
}
@media (max-width: 1050px) {
.command-navbar {
grid-template-columns: auto auto minmax(0, 1fr) auto;
}
.operator-workspace {
grid-template-columns: 220px minmax(0, 1fr) 300px;
}
}
@media (max-width: 820px) {
.command-brand {
display: flex;
}
.command-controls {
min-width: max-content;
}
.operator-workspace {
grid-template-columns: minmax(0, 1fr);
}
}
Loading
Loading