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
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,20 @@ requirements and the exact coordination guarantees.
With Local Markdown, `wrighty web` provides the board, item editor, recovery actions, and local
worker visibility:

[![Local Markdown Wrighty board with Todo, Worker queue, In Progress, Done, and attention-required items](docs/assets/screenshots/local-markdown-web-ui-board.png)](docs/assets/screenshots/local-markdown-web-ui-board.png)
<p>
<a href="docs/assets/screenshots/local-markdown-web-ui-board.png"><img src="docs/assets/screenshots/local-markdown-web-ui-board.png" width="31%" align="top" alt="Local Markdown Wrighty board with Todo, Worker queue, In Progress, and Done columns"></a>
<a href="docs/assets/screenshots/local-markdown-web-ui-board-agents.png"><img src="docs/assets/screenshots/local-markdown-web-ui-board-agents.png" width="31%" align="top" alt="Local Markdown Wrighty board with the Agents popover open"></a>
<a href="docs/assets/screenshots/local-markdown-web-ui-board-workers.png"><img src="docs/assets/screenshots/local-markdown-web-ui-board-workers.png" width="31%" align="top" alt="Local Markdown Wrighty board with the Workers popover open"></a>
</p>
<p>
<a href="docs/assets/screenshots/local-markdown-web-ui-board-needs-attention.png"><img src="docs/assets/screenshots/local-markdown-web-ui-board-needs-attention.png" width="15.5%" align="top" alt="Local Markdown Wrighty board showing an item that needs attention"></a>
<a href="docs/assets/screenshots/local-markdown-web-ui-operations.png"><img src="docs/assets/screenshots/local-markdown-web-ui-operations.png" width="31%" align="top" alt="Local Markdown Wrighty Operations view"></a>
</p>

With the GitHub backend, the configured GitHub Project remains the shared board. Wrighty adds the
queue, policy, claim, and recovery state used by local workers on each computer:

[![GitHub Project board with Wrighty queue, policy, claim, and recovery fields](docs/assets/screenshots/github-board.png)](docs/assets/screenshots/github-board.png)
<a href="docs/assets/screenshots/github-board.png"><img src="docs/assets/screenshots/github-board.png" width="31%" align="top" alt="GitHub Project board with Wrighty queue, policy, claim, and recovery fields"></a>

See [Wrighty workflows](docs/workflows.md) for the actions behind these views and the
[Web console](docs/reference/web-console.md) for the backend-specific web surfaces.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/local-markdown-web-ui-board.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified docs/assets/screenshots/local-markdown-web-ui-operations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions docs/reference/execution-profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ wrighty edit <id> --profile economy --claimant-id <id> --claim-token <token>
wrighty edit <id> --clear-profile --claimant-id <id> --claim-token <token>
```

On the web console the item editor offers **Execution profile** beside **Agent policy**,
whenever the repository configures a vocabulary.
On the web console the create and edit item forms offer **Execution profile** beside **Agent policy**.
They show the repository vocabulary when configured, or the built-in `economy`, `balanced`, and
`deep` names otherwise. The repository-default option includes the configured default profile name
when one exists, or says `vendor defaults` when Wrighty will pass no model or effort override.

**Resolution fails closed.** A profile that resolves to nothing usable is an error
(`AGENT_PROFILE_UNAVAILABLE`), never a quiet fallback. Wrighty does not drop to a cheaper profile to
Expand Down
45 changes: 34 additions & 11 deletions docs/reference/web-console.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,19 @@ not replace the board.

## Start, observe, and stop workers

**Operations → Local worker processes** shows both kinds of local worker:
The header's **Workers** button opens an installation-local anchored popover, matching the
**Agents** control. It lists running
workers, distinguishes **Worker preparing** from **Agent working**, shows the current item, agent,
runtime, and heartbeat, and offers a confirmed graceful **Stop** plus **Details**. **Details** opens
Operations at that exact worker and briefly highlights it. **Start new worker** adds a worker owned
by the current web-console process. Stale or unverifiable registrations stay out of the running
list and are linked to the complete Operations view.

**Operations → Local worker processes** remains the complete surface and shows both kinds of local
worker:

- **Hosted by this web console** is a background task owned by the current `wrighty web` process.
Every **Start worker** action adds another generic continuous worker using the configuration
Every **Start worker** or **Start new worker** action adds another generic continuous worker using the configuration
snapshot loaded at web startup. Closing, refreshing, or navigating away from the browser does
not stop them. Stopping the `wrighty web` process does.
- **Started outside the web console** is a `wrighty worker` process launched by a terminal, service
Expand All @@ -61,8 +70,9 @@ and current agent. Older worker versions that did not publish the agent say so i
from the item or claim. Stale and unverifiable records label item, agent, and state as last-reported
facts. The header's **Workers** button reports the verified running count from every tab, labels an
idle pool, and highlights how many workers are actively processing an item. Stale or unverifiable
registrations are called out separately. Select the button to open and focus **Operations → Local
worker processes**. The current hosted worker card exposes a bounded structured operational log. Opening it
registrations are called out separately. Select the button to open the running-worker overview;
use **Details** or **View all in Operations** for the complete process controls. The current hosted
worker card exposes a bounded structured operational log. Opening it
starts at the newest event. Normal and manual Operations refreshes continue updating the whole
worker card while preserving the disclosure and its scroll position for the same run. Updates
follow the tail until the operator scrolls back, at which point Wrighty preserves that reading
Expand Down Expand Up @@ -116,6 +126,13 @@ Operations organizes a bounded window. Wrighty asks the backend for one item bey
and the visible count describe the loaded 100-item window, not the entire repository. Refine the
filters or use the backend's native tracker when repository-wide discovery is required.

Board cards distinguish a worker that has claimed an item from one that has started its agent. A
neutral **Worker preparing** card means the worker owns the claim while it prepares the workspace
and validates the launch. After the operating-system process starts, the card changes to a raised,
outlined **Live — Agent working** treatment with a full-width execution banner, using the selected
agent's display name. Its motion becomes static when the browser requests reduced motion. Older
claims that do not record an execution phase continue to display as working for compatibility.

## Open a retained session from Operations

When an operational item needs attention, or is Done with no active claim, and this installation
Expand Down Expand Up @@ -327,22 +344,28 @@ active-work, completion, and archive-triggering statuses are excluded and reject
With worker-queue authorization enabled, status owns execution eligibility: creation in
`defaultPickFrom` authorizes execution and the form shows that rule instead of an independent
checkbox. With queue authorization disabled, the form offers **Allow automatic execution**, off by
default. An agent policy does not imply eligibility. **Create item** uses the ordinary retry-safe
creation pipeline. It never claims the new item, starts a worker, or launches a vendor agent.
default. The form also offers the item's agent and execution-profile policies; neither implies
eligibility. **Create item** uses the ordinary retry-safe creation pipeline. It never claims the new
item, starts a worker, or launches a vendor agent.

The item editor's **Execution policy** section explains status-controlled authorization when the
worker queue owns that decision; otherwise it offers the per-item automatic-execution checkbox. It
also carries agent policy and — when the repository configures an execution-profile vocabulary —
**Execution profile**. A repository that does not use profiles sees no such control. The choice
applies to the item's next fresh run; a recorded session keeps the model and effort it started with. See
[Execution profiles](execution-profiles.md).
also carries **Agent policy** and **Execution profile**. The profile choices come from the repository
vocabulary when configured, or from the built-in `economy`, `balanced`, and `deep` names otherwise.
For both policies, the repository-default choice includes the configured value when one exists; an
execution profile with no repository default says **vendor defaults**, meaning Wrighty passes no
model or effort override. The item viewer reports both policies with the same repository-default
labels. A profile choice applies to the item's next fresh run; a recorded session keeps the model and
effort it started with. See [Execution profiles](execution-profiles.md).

The web console also shows configured status columns, priority and claim state, supports
active/archived filtering, and renders each item's Markdown. The Board-wide sort offers operational
priority, item number, creation/update time, configured priority rank, and title. A compact control
in each status column can override that default; choose **Board sort** there to clear the override.
Every explicit order uses item number as its stable tie-break, and missing values remain last in
both directions.
both directions. The default operational order keeps scarce live work visible above a potentially
large backlog: **Agent working**, **Worker preparing**, **Needs attention**, retry scheduled,
handoff queued, resume queued, then other items. Operations uses the same default order.

Structured Board filters narrow claimant kind, associated agent, priority, claim ownership,
and update recency. The associated agent is the active claim's agent when present, then the retained
Expand Down
6 changes: 4 additions & 2 deletions docs/reference/worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -1125,7 +1125,9 @@ wrighty status --json # same groups for scripting
- **Completed — retained worktree** — finished items whose worktree is still present, each with the
branch, its `dirty`/`merged` git state, and the integration commands for the configured policy.
- **Paused — resumable session** — retained sessions waiting to be resumed, with the resume command.
- **Active** — items with a live claim (agent processing, human editing, automation).
- **Active** — items with a live claim. A worker-run claim reports **Worker preparing** while the
workspace and launch are being prepared, then the selected agent as **working** after its
operating-system process starts; human editing and automation claims retain their own labels.
- **Resume queued** — items marked to be resumed by a continuous worker.
- **Retry scheduled** — retained sessions waiting for their bounded retry time.
- **Handoff queued** — retained workspaces waiting for a due cross-agent continuation by the
Expand All @@ -1135,7 +1137,7 @@ wrighty status --json # same groups for scripting
`wrighty provider probe AGENT` to test it immediately without selecting a work item.
- **Local worker processes** — one installation-local heartbeat record per worker invocation,
including CLI-process/web-hosted origin, PID, verified/stale/unknown liveness, lifecycle state,
current item and agent, cooperative-control version, startup configuration revision, and a
current item title and agent, cooperative-control version, startup configuration revision, and a
sanitized invocation summary. The web console orders Running, then Unknown, then Stale workers,
then uses immutable start time and run ID within each group so heartbeat updates never make cards
trade places. Stale rows are visually de-emphasized.
Expand Down
15 changes: 4 additions & 11 deletions docs/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,7 @@ For Local Markdown, run `wrighty web`, choose **New item**, enter the structured
**Create item**. Creation does not claim the item or start a worker. The resulting card is selected
and the board refreshes.

[![Local Markdown New item form with status, priority, automatic execution, and agent policy controls](assets/screenshots/local-markdown-web-ui-item-create.png)](assets/screenshots/local-markdown-web-ui-item-create.png)

The example above creates an explicitly authorized **Worker queue** item. For ordinary intake,
To create an explicitly authorized **Worker queue** item, select that status. For ordinary intake,
choose **Todo** and leave **Allow automatic execution** unchecked.

For GitHub, create from the configured Project's `Todo` group or column in a board grouped by the
Expand Down Expand Up @@ -383,8 +381,8 @@ worktrees, or choose `--workspace-mode shared` explicitly and accept the collisi

### Web console

Use **Start worker** on Operations to add a continuous worker hosted by the current web server.
Select it again to add more. Closing or navigating away from the browser does not stop them;
Use **Start new worker** in the header's **Workers** overview—or **Start worker** on Operations—to
add a continuous worker hosted by the current web server. Select it again to add more. Closing or navigating away from the browser does not stop them;
stopping `wrighty web` does. Workspace concurrency behaves exactly as it does for CLI workers:
`current` serializes access and shows extra workers waiting, `worktree` isolates concurrent work,
and `shared` accepts collision risk. For a persistent service, start `wrighty worker` independently
Expand Down Expand Up @@ -498,12 +496,7 @@ Wrighty takes no claim, passes no claimant credentials, and leaves any further c
workspace changes to the operator.

The Local Markdown item panel keeps the agent's request, last-run result, retained session and
workspace, and the next recovery actions together. Select either view for the full-size image.

<p>
<a href="assets/screenshots/local-markdown-web-ui-item-attention.png"><img src="assets/screenshots/local-markdown-web-ui-item-attention.png" width="49%" alt="Upper part of a Local Markdown item panel showing an agent request for clarification and the last run result"></a>
<a href="assets/screenshots/local-markdown-web-ui-item-attention2.png"><img src="assets/screenshots/local-markdown-web-ui-item-attention2.png" width="49%" alt="Lower part of the same item panel showing retained claim, session, workspace, and recovery actions"></a>
</p>
workspace, and the next recovery actions together.

1. Open the item marked **Agent needs attention**.
2. If the work item is already correct and an external problem has been fixed, choose **Queue for
Expand Down
20 changes: 13 additions & 7 deletions src/Highbyte.Wrighty.Cli/Output/OutputWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public sealed class OutputWriter(
TextWriter error,
Func<DateTimeOffset>? clock = null)
{
private const string AgentFallback = "agent";
private readonly Func<DateTimeOffset> now = clock ?? (() => DateTimeOffset.UtcNow);

private static readonly string[] PartialErrorDetailKeys =
Expand Down Expand Up @@ -148,7 +149,8 @@ public async Task WriteStatusAsync(
var completed = Group(items, OperationalStatuses.Completed);
var paused = Group(items, OperationalStatuses.PausedSession);
var active = items.Where(value => value.OperationalStatus
is OperationalStatuses.AgentActive
is OperationalStatuses.WorkerPreparing
or OperationalStatuses.AgentActive
or OperationalStatuses.HumanEditing
or OperationalStatuses.AutomationActive).ToArray();
var queued = Group(items, OperationalStatuses.Queued);
Expand Down Expand Up @@ -1730,16 +1732,18 @@ private static string WorktreeMarker(WorkItemOperationalState value) =>
private string OperationalStatusToken(WorkItemOperationalState value) => value.OperationalStatus switch
{
OperationalStatuses.NeedsAttention => "!attention",
OperationalStatuses.WorkerPreparing =>
$"preparing:{value.Claim.Agent ?? AgentFallback}",
OperationalStatuses.AgentActive when IsWorkerRunClaim(value) =>
$"processing:{value.Claim.Agent ?? "agent"}",
OperationalStatuses.AgentActive => $"claimed:{value.Claim.Agent ?? "agent"}",
OperationalStatuses.Queued => $"queued:{value.Session?.Agent ?? "agent"}",
$"processing:{value.Claim.Agent ?? AgentFallback}",
OperationalStatuses.AgentActive => $"claimed:{value.Claim.Agent ?? AgentFallback}",
OperationalStatuses.Queued => $"queued:{value.Session?.Agent ?? AgentFallback}",
OperationalStatuses.RetryScheduled => value.Session?.Dispatch is { } dispatch
? $"retry:{dispatch.NotBefore.ToLocalTime():HH:mm}"
: "retry",
OperationalStatuses.HandoffQueued =>
$"handoff:{value.Session?.Dispatch?.Agent ?? "agent"}",
OperationalStatuses.PausedSession => $"paused:{value.Session?.Agent ?? "agent"}",
$"handoff:{value.Session?.Dispatch?.Agent ?? AgentFallback}",
OperationalStatuses.PausedSession => $"paused:{value.Session?.Agent ?? AgentFallback}",
OperationalStatuses.Completed => "completed",
OperationalStatuses.HumanEditing => "human",
OperationalStatuses.AutomationActive => "automation",
Expand All @@ -1750,6 +1754,7 @@ OperationalStatuses.AgentActive when IsWorkerRunClaim(value) =>
private string OperationalStatusLabel(WorkItemOperationalState value) => value.OperationalStatus switch
{
OperationalStatuses.NeedsAttention => "Needs attention",
OperationalStatuses.WorkerPreparing => "Worker preparing",
OperationalStatuses.AgentActive when IsWorkerRunClaim(value) =>
$"{AgentLabel(value.Claim.Agent) ?? "Agent"} processing",
OperationalStatuses.AgentActive => $"{AgentLabel(value.Claim.Agent) ?? "Agent"} claimed",
Expand All @@ -1759,7 +1764,7 @@ OperationalStatuses.AgentActive when IsWorkerRunClaim(value) =>
: "Retry scheduled",
OperationalStatuses.HandoffQueued => value.Session?.Dispatch is { } dispatch
? $"{AgentLabel(dispatch.SessionAgent) ?? "Agent"} → " +
$"{AgentLabel(dispatch.Agent) ?? "agent"}"
$"{AgentLabel(dispatch.Agent) ?? AgentFallback}"
: "Handoff queued",
OperationalStatuses.PausedSession => "Session retained",
OperationalStatuses.Completed => "Completed",
Expand Down Expand Up @@ -1892,6 +1897,7 @@ private object OperationalDto(
claimantId = claimView?.ClaimantId,
sessionId = claimView?.SessionId,
workspacePath = claimView?.WorkspacePath,
executionPhase = claimView?.ExecutionPhase,
workerRun = IsWorkerRunClaim(value),
leaseRemainingSeconds = LeaseRemainingSeconds(value.Claim),
value.Claim.TakeoverAvailable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public sealed record AgentExecutionContext(
string? Warning = null,
ClaimantKind ClaimantKind = ClaimantKind.Unknown,
string? ClaimantId = null,
string? ClaimToken = null)
string? ClaimToken = null,
string? ExecutionPhase = null)
{
public ClaimantKind EffectiveClaimantKind => ClaimantKind;

Expand Down
5 changes: 4 additions & 1 deletion src/Highbyte.Wrighty.Core/Claims/ClaimMarker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ value.EventType is not ("acquired" or "takenOver" or "released" or
Agent = Normalize(value.Agent),
SessionId = NormalizeOpaque(value.SessionId),
WorkspacePath = NormalizeWorkspace(value.WorkspacePath),
ClaimantKind = ClaimantKinds.ToStorageValue(ClaimantKinds.FromStorageValue(value.ClaimantKind))
ClaimantKind = ClaimantKinds.ToStorageValue(ClaimantKinds.FromStorageValue(value.ClaimantKind)),
ExecutionPhase = ClaimantKinds.FromStorageValue(value.ClaimantKind) == ClaimantKind.Agent
? ClaimExecutionPhases.Normalize(value.ExecutionPhase)
: null
};
return true;
}
Expand Down
Loading