DESIGN.md@os-ui · diff
git:20260929.b61c16c to git:20260930.4bad615
18 added, 6 removed. Audit A to A.
# os-ui Design - Research OS Read-only Dashboard
This document is the implementation contract for `os-ui/`. The static visual
mockup lives in [mockup.html](mockup.html).
Authorization boundary: the human authorized a read-only monitor UI on
2026-07-04. That exception applies only to observation. On 2026-07-22 the Human
Owner authorized exactly one narrow write action on top of it — disabling or
enabling a single install location — because it is non-destructive,
reversible, and visible in Git. On 2026-09-26 the Human Owner asked for the
root-agent conversation inside the UI (GOAL.md H2: one root agent as the
human's single point of contact) and, the same evening, a direct entry to each
project's agent, so the **Root Agent** window, the Projects window's **Agent**
view, and their token-gated `/api/chat/*` endpoints were added; they start,
resume, stop, and read os-harness sessions at the repository root or inside one
registered project, and execute nothing themselves.
On 2026-09-30 the Human Owner authorized a second narrow write: setting one
paper or source note's reading `status` (unread, skimmed, read) from the Paper
Wiki viewer, because the status is the human's own reading record and the
static viewer had no way to capture it. It rewrites one frontmatter line,
regenerates `paper-wiki/viz.html`, and is reversible and visible in Git.
+ Later on 2026-09-30 the Human Owner asked for OpenResearch-style buttons that
+ switch literature sources on and off, authorizing a third narrow write: the
+ agent windows' **Papers** button flips one source in
+ `memory/paper-sources.json` through the `paper-search` skill's `sources`
+ command. The switches bind the agents' paper search, so they sit next to the
+ conversation, behind the same token; the write is one boolean, reversible and
+ visible in Git.
Everything else, including install and delete buttons, resident services, SSE,
and any further action endpoint, remains gated by GOAL.md M4: evidence first,
then explicit human confirmation.
## 1. Positioning
- `os-ui` is an observation dashboard with agent conversations. Its write
actions are the skill enable/disable toggle (2026-07-22), the paper
- reading-status buttons (2026-09-30), and the agent
+ reading-status buttons (2026-09-30), the paper-source switches
+ (2026-09-30), and the agent
conversations (2026-09-26: the Root Agent window and each project's Agent
view), which send messages to os-harness sessions.
- It renders repository state and copies commands for the human to run; it does
not execute commands. Skill install and removal are copy-only, like every
other command.
- The filesystem remains the source of truth. It is also the only write
- surface: the toggle renames a file and the status buttons rewrite one
- frontmatter line, rather than mutating hidden state.
+ surface: the toggle renames a file, the status buttons rewrite one
+ frontmatter line, and the source switches rewrite one JSON boolean, rather
+ than mutating hidden state.
- Removing `os-ui/` must leave the Research OS unaffected.
- The UI is infrastructure, not a project in `projects-folder/` and not a
portfolio row.
## 2. Architecture And Contract
```text
plain repository files -> generator (Python, uv) -> state.json -> frontend
one-shot/watch tool schema-only static UI
```
- `frontend/public/state.json` is the only generator/frontend contract.
- `state.json` includes `schema_version`. Schema changes are additive; old
fields are not removed.
- The file is gitignored because it is a cache, not a durable source of truth.
- Generator modes:
- one-shot: `uv run python generate.py`
- foreground watch: `uv run python generate.py --watch`
- The frontend polls `state.json` every few seconds.
- Future realtime service + SSE is an M4-gated resident-service upgrade. The
component layer should not need to change for that upgrade.
### Schema v0.1
```jsonc
{
"meta": { "schema_version": "0.1", "generated_at": "...", "repo_head": "..." },
"policy": { "agent_led_research": "off", "parallelism": "..." },
"portfolio": [
{
"project": "...",
"path": "...",
"owner": "...",
"stage": "...",
"priority": "...",
"status": "...",
"evaluator": "...",
"next_action": "...",
"evidence": { "source": "...", "mtime": "..." }
}
],
"active_work": [
{ "title": "...", "items": [{ "text": "...", "done": false }], "source": "..." }
],
"governance": [{ "date": "...", "decision": "...", "source": "..." }],
"projects": [
{
"name": "...",
"snapshot": {
"owner": null,
"origin": null,
"stage": null,
"priority": null,
"evaluator_status": null,
"current_question": null,
"next_action": null
},
"evaluation": { "target": null, "best_known": null, "source": null },
"rounds": [{ "id": "...", "score": null, "valid": true, "artifacts": [], "tasks": [] }],
"evaluations": [],
"os_feedback": [],
"local_skills": [{ "name": "...", "promotion_candidate": null }]
}
],
"unregistered_projects": [{ "name": "...", "path": "..." }],
"store": {
"collections": [
{
"name": "...",
"skills": [
{
"name": "...",
"description": "...",
"license": "...",
"has_scripts": false,
"installed": { ".claude/skills": true, ".agents/skills": true },
"sync": "synced"
}
]
}
],
"orphans": []
},
"activity": [{ "when": "...", "what": "...", "source": "..." }],
"agent_activity": []
}
```
## 3. Data Sources
| UI element | Source | Current state |
|---|---|---|
| Portfolio strips | `memory/MEMORY.md` Active Projects table | available |
| Policy panel | `memory/MEMORY.md` Research Policy table | available |
| Active Work | `HANDOFF.md` Active Work checklists | available |
| Governance log | `HANDOFF.md` Decisions + `memory/MEMORY.md` decisions | available |
| Project snapshot | `projects-folder/<P>/PROJECT_MEMORY.md` Snapshot | available |
| Evaluation lines | `PROJECT_MEMORY.md` Evaluation Contract | pending a project with rounds |
| Round track | `projects-folder/<P>/Code/runs/<round-id>/result.json` | pending a project with rounds |
| Parallel branches | `projects-folder/<P>/Tasks/<task-id>/` | pending a project with rounds |
| Review reports | `projects-folder/<P>/Evaluations/` | pending a project with reviews |
| OS Feedback | `PROJECT_MEMORY.md` OS Feedback section | pending a project that records it |
| Local skills | project-local `.claude/skills` / `.agents/skills` | partial |
| Skill Store | `research-skills-hub/*/index.md` + `SKILL.md` frontmatter | available |
| License | skill LICENSE -> collection LICENSE/README -> fallback | available |
| Sync status | hub / `.claude/skills` / `.agents/skills` byte comparison | available |
| Activity | `git log` + project progress logs | available |
Pending sources must render empty states. The generator must not fabricate
sample records.
## 4. Information Architecture
Since 2026-07-05 the UI uses a desktop shell: a persistent menu bar, a bottom
dock, and draggable/zoomable/minimizable windows under `frontend/src/desktop/`.
The old tab-shell concept is superseded.
1. **Dashboard**: portfolio strips (stage bar and chips; the status, evaluator,
and next-action sentences open on click), unregistered project warnings,
Active Work rows (progress bar; checklist opens on click), an activity
timeline (first line; full text opens on click), policy chips, and the
collapsed governance log.
2. **Projects**: a header (stage bar, owner/priority/evaluator chips, four
counts), the Snapshot sentences as one-line previews that open on click,
and collapsed sections for the round score track, evaluations, OS
Feedback, and local skills; plus the Agent view (§1).
Rule for both pages, set by the Human Owner on 2026-09-27: show state with
visual elements and as few words as possible; sentences appear only when
the human clicks.
3. **Skill Store**: hub collections, orphan skills, sync badges, script
warnings, license labels, per-target install state, and a per-location
enable/disable toggle; installing elsewhere stays a copied command. How this
splits between the human and the agent is documented in
[research-skills-hub/MANAGING-SKILLS.md](../research-skills-hub/MANAGING-SKILLS.md).
4. **Paper Wiki**: the paper-wiki viewer (Graph and Timeline tabs), embedded by `<iframe>` from
`paper-wiki/viz.html` rather than reimplemented natively. That file is a
generated artifact (source: `research-skills-hub/open-paper-skills/
paper-wiki-manager/scripts/{templates/viz.html,static/viz.{css,js}}`) that
already vendors its own force-directed graph engine (fcose + cytoscape.js)
and stays usable on its own — the GitHub Pages workflow at
`.github/workflows/pages.yml` serves it at `paper-wiki/viz.html` inside the
published os-ui build. Reimplementing that graph natively in React
would duplicate a working, self-contained viewer for no benefit; the iframe
keeps a single source of truth. `frontend/public/paper-wiki/` is a
gitignored cache copy synced by `start.sh` (same treatment as
`state.json`) — re-run `./start.sh` after editing paper-wiki content or the
viewer templates. Its window skips the padded content area every other app
uses (`AppDef.fill`), so the viewer fills the window edge-to-edge and
manages its own scrolling. The viewer probes `GET /api/paper-wiki/status`
([frontend/paper-status-plugin.ts](frontend/paper-status-plugin.ts)); when
it answers, a note's Status row becomes unread / skimmed / read buttons.
`POST` runs paper-wiki-manager's `set_status.py`, regenerates `viz.html`,
and copies the note and viewer into the cache copy, so a reload keeps the
change without re-running `start.sh`.
## 5. State Semantics
- Honest stale state is better than fake realtime.
- Every derived status should expose source and timestamp when available.
- Missing fields render as explicit empty states or `not filled in`.
- The UI does not display "running" unless a durable file contract exists.
- `agent_activity` is reserved for a future leased-heartbeat design. If added,
it must include `expires_at` so stale heartbeats degrade automatically.
## 6. Technology
- Frontend: Vite + React + TypeScript + Tailwind.
- Generator: Python, uv-managed, standard library only.
- Scope: all code and generated cache paths stay inside `os-ui/`.
- No database, resident service, server action surface, or agent transcript
parser in v0.
## 7. Visual Spec
- Mood: research control room, air-traffic progress strips, engineering graph
paper.
- Palette:
- `--paper #F2F4F3`
- `--panel #FFFFFF`
- `--ink #17262E`
- `--ink-soft #52646E`
- `--grid #D9E0E2`
- `--signal #E8590C`
- `--verify #2F7D6D`
- `--warn #B7791F`
- `--danger #C4564A`
- Fonts: IBM Plex Mono for headings/data, IBM Plex Sans for body text.
- Signature elements:
- Dashboard portfolio flight strip
- Project round score track
- Motion: restrained hover lift and drawer slide; respect
`prefers-reduced-motion`.
- Desktop shell: white panel windows, 12px radius, soft shadow, centered mono
title, traffic lights mapped to semantic colors, and a glass dock.
## 8. Non-goals
- - No write operations beyond the skill enable/disable toggle and the paper
- reading-status buttons. The toggle: a symlinked install moves into the
+ - No write operations beyond the skill enable/disable toggle, the paper
+ reading-status buttons, and the paper-source switches. The toggle: a
+ symlinked install moves into the
target's `.disabled/` directory, a copied one renames its `SKILL.md` to
`SKILL.md.disabled`. No skill content is created or deleted, and installing
remains a copied command — the toggle is offered only where an install
already exists. The status buttons change only the `status:` line of a note
under `paper-wiki/papers/` or `paper-wiki/sources/`, never note content.
- - No resident services or SSE until M4. Both write endpoints are Vite
+ The source switches change only one source's boolean in
+ `memory/paper-sources.json`; os-ui itself runs no paper search.
+ - No resident services or SSE until M4. All three write endpoints are Vite
dev-server middleware: they exist only while `start.sh` runs and die with
Ctrl-C.
- No execution buttons until M4. Install and remove stay copy-only.
- No user accounts, multi-user collaboration, or remote deployment of the live
desktop. The one remote copy is the view-only production build that
`.github/workflows/pages.yml` publishes to GitHub Pages from `autoreadpaper`
(Human Owner, 2026-09-30); it carries no endpoints and hides their controls
(`frontend/src/lib/mode.ts`).
- No agent transcript parser or dependence on one specific agent.
- No Chinese UI/i18n layer for now; the current build is English-first. Keep
`README_zh.md` as a reference copy, and add Chinese UI support later when the
OS is mature enough to justify it.