702 lines
27 KiB
TypeScript
702 lines
27 KiB
TypeScript
export const en = {
|
|
shell: {
|
|
kicker: "AI delivery workflow",
|
|
title: "Delivery Console",
|
|
},
|
|
tabs: {
|
|
workflow: "Leader Console",
|
|
roles: "Agents",
|
|
skills: "Skills",
|
|
executions: "Runs",
|
|
merges: "Merge queue",
|
|
},
|
|
localeToggle: {
|
|
label: "Language",
|
|
zh: "中文",
|
|
en: "EN",
|
|
},
|
|
common: {
|
|
close: "Close",
|
|
cancel: "Cancel",
|
|
retry: "Retry",
|
|
loading: "Loading...",
|
|
loadingPage: "Loading page...",
|
|
send: "Send",
|
|
sending: "Sending...",
|
|
sendUpdate: "Send update",
|
|
create: "Create",
|
|
creating: "Creating...",
|
|
confirm: "Confirm",
|
|
edit: "Edit",
|
|
active: "Active",
|
|
notStarted: "Not started",
|
|
backToLatest: "Back to latest",
|
|
previous: "Previous",
|
|
next: "Next",
|
|
showNote: "Show note",
|
|
hideNote: "Hide note",
|
|
latestReply: "Latest reply",
|
|
runNote: "Run note",
|
|
openWorkflow: "Open workflow",
|
|
copyPath: "Copy path",
|
|
pathCopied: "Path copied",
|
|
noMessageContent: "No message content.",
|
|
emptyMessage: "(empty message)",
|
|
emptyBody: "(empty)",
|
|
never: "Never",
|
|
running: "Running",
|
|
fallback: "-",
|
|
},
|
|
themes: {
|
|
"atelier-copper": {
|
|
label: "Atelier Copper",
|
|
description: "Warm premium console",
|
|
},
|
|
"graphite-aqua": {
|
|
label: "Graphite Aqua",
|
|
description: "Cool technical slate",
|
|
},
|
|
"midnight-plum": {
|
|
label: "Midnight Plum",
|
|
description: "Moody editorial control room",
|
|
},
|
|
"ivory-brass": {
|
|
label: "Ivory Brass",
|
|
description: "Warm paper and brass",
|
|
},
|
|
"mist-blue": {
|
|
label: "Mist Blue",
|
|
description: "Crisp blue studio",
|
|
},
|
|
"sage-paper": {
|
|
label: "Sage Paper",
|
|
description: "Soft green planning desk",
|
|
},
|
|
appearance: {
|
|
dark: "Dark",
|
|
light: "Light",
|
|
darkThemes: "Dark themes",
|
|
lightThemes: "Light themes",
|
|
},
|
|
},
|
|
themeSelector: {
|
|
themeTitle: "Theme",
|
|
},
|
|
workspaceRequired: {
|
|
eyebrow: "Project context",
|
|
title: "Select a project",
|
|
detail: (subject: string) =>
|
|
`Choose a project from the picker in the top-right corner to load ${subject}.`,
|
|
},
|
|
globalPendingIndicator: {
|
|
label: "Pending",
|
|
title: (topic: string, count: number) =>
|
|
count === 1
|
|
? `Open pending topic ${topic}`
|
|
: `Open ${topic} and review ${count} pending topics`,
|
|
ariaLabel: (count: number, topic: string) =>
|
|
count === 1
|
|
? `1 pending item. Open topic ${topic}`
|
|
: `${count} pending items. Open topic ${topic}`,
|
|
modalTitle: (count: number) =>
|
|
count === 1 ? "1 pending item" : `${count} pending items`,
|
|
modalDetail: "These topics are waiting for plan confirmation. Choose one to open its detail view.",
|
|
openAction: "Open",
|
|
},
|
|
metadata: {
|
|
workflow: {
|
|
label: "Leader Console",
|
|
description:
|
|
"Operate the leader console: user dialogue, lane orchestration, task graph, and execution state.",
|
|
},
|
|
roles: {
|
|
label: "Agents",
|
|
description:
|
|
"Monitor leader and worker runtime state, attention, and recent activity.",
|
|
},
|
|
skills: {
|
|
label: "Skills",
|
|
description:
|
|
"Maintain the shared skill catalog separately from per-role skill assignment.",
|
|
},
|
|
executions: {
|
|
label: "Runs",
|
|
description:
|
|
"Inspect agent runs, outputs, and completion state across the current workspace.",
|
|
},
|
|
merges: {
|
|
label: "Merge queue",
|
|
description:
|
|
"Review queued merges, changed files, and merge readiness before promoting work.",
|
|
},
|
|
workspaceSuffix: (workspace: string) => `Active workspace: ${workspace}.`,
|
|
},
|
|
workspaceSelector: {
|
|
unavailable: "Workspaces unavailable",
|
|
loadingProjects: "Loading workspaces...",
|
|
missingProject: (value: string) => `${value} (missing)`,
|
|
noProjects: "No workspaces",
|
|
chooseProject: "Choose workspace",
|
|
projectsTitle: "Workspaces",
|
|
noProjectsYet: "No workspaces yet",
|
|
ensureWorkspaceError: "Couldn't prepare the workspace runtime.",
|
|
statusReadyRunning: "Ready",
|
|
statusReadyStopped: "Ready",
|
|
statusFailed: "Setup failed",
|
|
statusMissing: "Not ready",
|
|
loadProjectsError: "Couldn't load workspaces",
|
|
noProjectPath: "No workspace path available",
|
|
},
|
|
runtimeStatus: {
|
|
eyebrow: "Runtime monitor",
|
|
title: "Container runtime",
|
|
detail:
|
|
"Monitor the selected workspace container and recover it here instead of coupling runtime startup to project selection.",
|
|
openDetails: (workspace: string) => `Open runtime details for ${workspace}`,
|
|
summaryFallback: "Open details",
|
|
loadingTitle: "Loading runtime status...",
|
|
errorTitle: "Couldn't load runtime status",
|
|
fields: {
|
|
workspace: "Workspace",
|
|
container: "Container",
|
|
containerState: "Container state",
|
|
provisionState: "Provision state",
|
|
endpoint: "Runner endpoint",
|
|
lastProvisioned: "Last provisioned",
|
|
error: "Provision error",
|
|
},
|
|
states: {
|
|
running: "Running",
|
|
stopped: "Stopped",
|
|
missing: "Missing",
|
|
failed: "Failed",
|
|
},
|
|
endpointMissing: "Endpoint missing",
|
|
refresh: "Refresh status",
|
|
refreshing: "Refreshing...",
|
|
start: "Start runtime",
|
|
starting: "Starting runtime...",
|
|
retry: "Retry runtime",
|
|
retrying: "Retrying runtime...",
|
|
reconcile: "Reconcile runtime",
|
|
reconciling: "Reconciling runtime...",
|
|
actionError: "Runtime action failed",
|
|
},
|
|
roleEditor: {
|
|
title: (roleName: string) => `Edit: ${roleName}`,
|
|
roleTab: "Role",
|
|
roleSkillsTab: "Role Skills",
|
|
loading: "Loading...",
|
|
name: "Name",
|
|
sortOrder: "Sort Order",
|
|
description: "Description",
|
|
descriptionPlaceholder: "Short description of what this role does",
|
|
systemPrompt: "System Prompt",
|
|
promptPlaceholder: "The full system prompt for this agent role...",
|
|
codexConfig: "Codex Config",
|
|
codexConfigPlaceholder:
|
|
"model = \"gpt-5.4\"\napproval_policy = \"never\"\nsandbox_mode = \"workspace-write\"",
|
|
codexAuth: "Codex Auth",
|
|
codexAuthPlaceholder:
|
|
"{\n \"OPENAI_API_KEY\": \"...\"\n}",
|
|
skillsEmpty: "No skills are available for this role yet.",
|
|
skillMissing: "Missing",
|
|
skillsGroupingScope:
|
|
"Skill groups are shared across roles. Edit shared skill content from the Skills page.",
|
|
skillGroupLabel: "Group",
|
|
skillGroupPlaceholder: "group-name",
|
|
skillCategories: {
|
|
adaptation: "Adaptation",
|
|
visual_design: "Visual Design",
|
|
consistency: "Consistency",
|
|
quality: "Quality & Resilience",
|
|
ux_copy: "UX & Copy",
|
|
systemization: "Systemization",
|
|
capability: "Capability",
|
|
other: "Other",
|
|
},
|
|
saveRole: "Save Role",
|
|
saveSkills: "Save Skills",
|
|
saving: "Saving...",
|
|
},
|
|
skillsCatalog: {
|
|
workspaceSubject: "skill catalog",
|
|
eyebrow: "Shared skill library",
|
|
heroTitle: "Maintain shared skills as a first-class surface, separate from role detail editing.",
|
|
heroDetail:
|
|
"This page owns the global skill catalog. Role detail panels stay focused on assignment and grouping, while shared skill instructions live here.",
|
|
summary: {
|
|
totalSkills: "Skills in catalog",
|
|
totalSkillsDetail: "Shared entries available for role assignment.",
|
|
categories: "Categories",
|
|
categoriesDetail: "Unique buckets used to organize the library.",
|
|
assignmentSurface: "Assignments live in",
|
|
assignmentSurfaceValue: "Roles",
|
|
assignmentSurfaceDetail: "Enable and group skills from each role's detail panel.",
|
|
},
|
|
loadingTitle: "Loading skills...",
|
|
errorTitle: "Couldn't load skills",
|
|
catalogScope:
|
|
"Skill content is global. Changes here affect every role that enables the skill.",
|
|
catalogListLabel: "Skill catalog",
|
|
catalogEmpty: "No skills are stored in the database yet.",
|
|
newSkill: "New Skill",
|
|
deleteSkill: "Delete Skill",
|
|
skillGroupLabel: "Group",
|
|
skillGroupPlaceholder: "group-name",
|
|
skillMarkdownSummaryLabel: "Parsed from Markdown",
|
|
skillNameLabel: "Skill Name",
|
|
skillNameMissing: "Add `name:` to the markdown frontmatter.",
|
|
skillDescriptionLabel: "Description",
|
|
skillDescriptionMissing: "Optional. Add `description:` if you want a short summary.",
|
|
skillMarkdownHint:
|
|
"The internal skill ID is generated and maintained automatically from the markdown frontmatter.",
|
|
skillContentLabel: "Skill Content",
|
|
skillContentPlaceholder:
|
|
"---\nname: my-skill\ndescription: Brief summary shown in role assignment.\n---\n\nWrite the skill instructions here.",
|
|
skillCategories: {
|
|
adaptation: "Adaptation",
|
|
visual_design: "Visual Design",
|
|
consistency: "Consistency",
|
|
quality: "Quality & Resilience",
|
|
ux_copy: "UX & Copy",
|
|
systemization: "Systemization",
|
|
capability: "Capability",
|
|
other: "Other",
|
|
},
|
|
sortOrder: "Sort Order",
|
|
saveSkill: "Save Skill",
|
|
saving: "Saving...",
|
|
},
|
|
roleStatus: {
|
|
workspaceSubject: "agent status",
|
|
listTitle: "Agents",
|
|
listDetail: "Leader and workers currently active in this workspace.",
|
|
conciseDescription: {
|
|
leader: "Talks to the user, plans task graphs and derived lanes, and supervises execution.",
|
|
worker: "Executes lane tasks inside an isolated runtime.",
|
|
},
|
|
states: {
|
|
attention: "Needs attention",
|
|
active: "Active",
|
|
idle: "Not started",
|
|
waiting: (count: number) => `${count} waiting`,
|
|
},
|
|
loadingTitle: "Loading agents...",
|
|
errorTitle: "Couldn't load agent status",
|
|
emptyTitle: "No agents yet",
|
|
emptyDetail:
|
|
"Agent status appears here after this workspace starts running leader and worker threads.",
|
|
eyebrow: "Operational roster",
|
|
heroTitle:
|
|
"A live read on which agents are active, blocked, or still waiting to start.",
|
|
heroDetail:
|
|
"This surface keeps the orchestration layer legible: who is running, who has inbox work, and which roles have not entered the thread yet.",
|
|
summary: {
|
|
activeAgents: "Active agents",
|
|
activeAgentsDetail: "Roles with a live session right now.",
|
|
needsAttention: "Needs attention",
|
|
needsAttentionDetail: "Roles carrying pending inbox work.",
|
|
waitingItems: "Waiting items",
|
|
waitingItemsDetail: "Total queued messages across the roster.",
|
|
notStarted: "Not started",
|
|
notStartedDetail: "Roles that have not entered the workspace yet.",
|
|
},
|
|
lastActive: "Last active",
|
|
},
|
|
messageWorkflow: {
|
|
workspaceSubject: "message history",
|
|
eyebrow: "Activity feed",
|
|
loadingTitle: "Loading activity...",
|
|
errorTitle: "Couldn't load activity",
|
|
emptyTitle: "No activity yet",
|
|
emptyDetail:
|
|
"Messages appear here after the first handoff, clarification, or decision lands in Workflow.",
|
|
heroTitle: "Every handoff, decision, and clarification in one readable stream.",
|
|
heroDetail:
|
|
"This view turns message routing into a working narrative, so you can skim what moved, who moved it, and where the thread is headed next.",
|
|
summary: {
|
|
messages: "Messages",
|
|
messagesDetail: "Captured in the current workspace timeline.",
|
|
expanded: "Expanded",
|
|
expandedDetail: "Open cards for deeper reading right now.",
|
|
},
|
|
expandMessage: "Expand full message",
|
|
collapseMessage: "Collapse full message",
|
|
},
|
|
executions: {
|
|
workspaceSubject: "run history",
|
|
eyebrow: "Run ledger",
|
|
loadingTitle: "Loading runs...",
|
|
errorTitle: "Couldn't load runs",
|
|
emptyTitle: "No runs yet",
|
|
emptyDetail:
|
|
"Agent runs appear here after work starts on this project, including new threads, resumed sessions, and verification passes.",
|
|
heroTitle: "A readable history of every agent execution across the workspace.",
|
|
heroDetail:
|
|
"Track who started work, which threads were resumed, and where failures or long-running executions still need attention.",
|
|
summary: {
|
|
running: "Running",
|
|
runningDetail: "Live executions in progress.",
|
|
resumed: "Resumed",
|
|
resumedDetail: "Runs that continued an existing thread.",
|
|
failed: "Failed",
|
|
failedDetail: "Completed with a non-zero exit code.",
|
|
},
|
|
newRunsAvailable: "New runs available",
|
|
newRunsDetail:
|
|
"New executions arrived while you were reviewing older history.",
|
|
topic: "Topic",
|
|
phase: "Phase",
|
|
thread: "Thread",
|
|
duration: "Duration",
|
|
started: "Started",
|
|
recentRuns: "Recent runs",
|
|
recentRunsTitle: "Ordered newest first for quick triage.",
|
|
role: "Role",
|
|
exitCode: "Exit code",
|
|
details: "Details",
|
|
noDetail: "-",
|
|
mobileShowing: (visible: number, total: number) =>
|
|
`Showing ${visible} of ${total} runs.`,
|
|
desktopShowing: (start: number, end: number, total: number) =>
|
|
`Showing ${start}-${end} of ${total} runs.`,
|
|
loadOlderRuns: "Load older runs",
|
|
pageLabel: (page: number, totalPages: number) => `Page ${page} of ${totalPages}`,
|
|
},
|
|
mergeQueue: {
|
|
workspaceSubject: "merge requests",
|
|
eyebrow: "Merge queue",
|
|
loadingTitle: "Loading merge queue...",
|
|
errorTitle: "Couldn't load merge queue",
|
|
emptyTitle: "Nothing waiting to merge",
|
|
emptyDetail:
|
|
"Changes show up here after a build finishes and is ready for review, approval, and merge back to the main project branch.",
|
|
heroTitle: "Review-ready changes collected in one calm, traceable queue.",
|
|
heroDetail:
|
|
"This surface is for final judgment: what is pending, what merged cleanly, and which requests still need human intervention before they can land.",
|
|
summary: {
|
|
pending: "Pending",
|
|
pendingDetail: "Waiting for approval or merge.",
|
|
merged: "Merged",
|
|
mergedDetail: "Already landed back on target.",
|
|
failed: "Failed",
|
|
failedDetail: "Requests blocked by errors or conflicts.",
|
|
},
|
|
status: {
|
|
pending: "Pending",
|
|
merged: "Merged",
|
|
failed: "Failed",
|
|
},
|
|
filesChanged: (count: number) => `${count} files changed`,
|
|
loadDiffError: "Couldn't load file diffs.",
|
|
failedToMerge: "Failed to merge",
|
|
files: "Files",
|
|
created: "Created",
|
|
merged: "Merged",
|
|
mergeAction: "Approve & Merge",
|
|
merging: "Merging...",
|
|
},
|
|
workflow: {
|
|
topicExamplesLabel: "Example topics",
|
|
starterTopicsLabel: "Starter topics",
|
|
kickoffChecklist: [
|
|
{
|
|
label: "Start with the owner",
|
|
detail:
|
|
"Send the first message to the leader so the leader can decide whether to clarify, derive lanes, or start execution.",
|
|
},
|
|
{
|
|
label: "Anchor the goal",
|
|
detail:
|
|
"Summarize the user outcome, constraints, and done criteria the receiving role should optimize for.",
|
|
},
|
|
{
|
|
label: "Keep the first handoff executable",
|
|
detail:
|
|
"Use a topic name and opening message that can survive multiple rounds of review, build, and verification.",
|
|
},
|
|
],
|
|
topicCount: (count: number) => `${count} msg${count !== 1 ? "s" : ""}`,
|
|
noMessageContent: "No message content.",
|
|
recipient: "Recipient",
|
|
phase: "Phase",
|
|
message: "Message",
|
|
messageHint: (shortcut: string) => `${shortcut}+Enter to send`,
|
|
disabledPlaceholder: "Name the topic first...",
|
|
enabledPlaceholder: "Outline the next decision, handoff, or build request...",
|
|
sendFailed: "Send failed",
|
|
createTopicFailed: "Couldn't create the topic.",
|
|
deleteTopic: "Delete topic",
|
|
confirmDeleteTopic: "Confirm delete",
|
|
deletingTopic: "Deleting topic",
|
|
deleteTopicFailed: "Couldn't delete the topic.",
|
|
deleteTopicDialogTitle: "Delete this topic?",
|
|
deleteTopicDialogDetail:
|
|
"This will permanently remove the topic and its workflow history from the leader console.",
|
|
stopTopic: "Stop topic",
|
|
confirmStopTopic: "Confirm stop",
|
|
stoppingTopic: "Stopping topic",
|
|
stopTopicFailed: "Couldn't stop the topic.",
|
|
stopTopicDialogTitle: "Stop this topic?",
|
|
stopTopicDialogDetail:
|
|
"This will halt further execution for the topic. Use this only when the topic should not continue.",
|
|
confirmPlan: "Confirm plan",
|
|
confirmingPlan: "Confirming plan",
|
|
confirmPlanFailed: "Couldn't confirm the plan.",
|
|
topicAwaitingApproval: "Awaiting approval",
|
|
topicStopped: "Stopped",
|
|
topicStatus: (status: string) => `Status: ${status}`,
|
|
pendingPlanBanner: {
|
|
title: (count: number) => count === 1 ? "1 topic is waiting for plan approval" : `${count} topics are waiting for plan approval`,
|
|
detail: "Execution stays paused until the plan is confirmed. Open the topic details to review and approve it.",
|
|
openTopic: (topic: string) => `Open ${topic}`,
|
|
},
|
|
planReview: {
|
|
eyebrow: "Plan review",
|
|
title: "Review the frozen plan before execution starts",
|
|
detail: "This topic already has a proposed task graph. The execution map stays hidden until the plan is confirmed.",
|
|
summaryTitle: "Plan summary",
|
|
summaryEmpty: "The leader froze a plan, but no summary was saved with it.",
|
|
proposedLanes: "Proposed lanes",
|
|
proposedTasks: "Planned tasks",
|
|
lanesEmpty: "No lanes have been proposed yet.",
|
|
tasksEmpty: "No tasks have been proposed yet.",
|
|
versionLabel: (version: number) => `Plan v${version}`,
|
|
createdByLabel: (role: string) => `Prepared by ${role}`,
|
|
},
|
|
untitledTopic: "(no topic)",
|
|
workspaceSubject: "workflow",
|
|
errorTitle: "Couldn't load workflow",
|
|
topics: "Topics",
|
|
newTopic: "+ New",
|
|
hideTopics: "Hide",
|
|
showTopics: "Show topics",
|
|
topicName: "Topic name",
|
|
topicPlaceholder: "topic-name",
|
|
topicHint: "Enter to create, Esc to cancel",
|
|
emptyTopicRailTitle: "No topics yet",
|
|
emptyTopicRailDetail:
|
|
"Start the first leader thread here. The leader will turn it into a task graph, derived lanes, and execution runs.",
|
|
srHeading: (topic: string | null) =>
|
|
topic ? `Topic ${topic}` : "Workflow topic details",
|
|
emptyState: {
|
|
eyebrow: "Workflow",
|
|
namingTitle: "Name this topic",
|
|
initialTitle: "Launch a topic and move it through the team",
|
|
namingDetail:
|
|
"Give the workstream a durable topic name on the left, then send the opening message to the leader.",
|
|
initialDetail:
|
|
"Each topic becomes a leader-owned thread. Start with a clear goal, then let the leader define the task graph and derived lanes from there.",
|
|
startFirstTopic: "+ Start first topic",
|
|
whatHappensNext: "What happens next",
|
|
strongFirstHandoff: "A strong first handoff",
|
|
exampleOpeningTitle: "Example opening",
|
|
creatingSideNote:
|
|
"Keep one topic per outcome. That makes the timeline easier to read when planning, building, and verification overlap.",
|
|
nonCreatingSideNote:
|
|
"Keep one topic per outcome. That makes the timeline easier to read when planning, building, and verification overlap.",
|
|
},
|
|
runningSummary: {
|
|
single: (role: string) => `${role} running`,
|
|
double: (left: string, right: string) => `${left} + ${right} running`,
|
|
multiple: (count: number) => `${count} agents running`,
|
|
},
|
|
topicSignals: {
|
|
running: (count: number) => `${count} running`,
|
|
waiting: (count: number) => `${count} queued`,
|
|
},
|
|
summary: {
|
|
eyebrow: "Active topic",
|
|
detail:
|
|
"See who owns the next move, which handoffs are still queued, and how this topic is moving through build and verification.",
|
|
runningLabel: "Running now",
|
|
waitingLabel: "Queued",
|
|
activeLabel: "In motion",
|
|
running: (count: number) => `${count} agents are still executing.`,
|
|
waiting: (count: number) => `${count} agents are waiting on the next handoff.`,
|
|
active: (count: number) => `${count} roles are part of the current flow.`,
|
|
},
|
|
board: {
|
|
detail:
|
|
"Roles stay pinned to fixed swimlanes while direct handoffs stack by time, so the handoff sequence stays readable even when traffic gets dense.",
|
|
hint:
|
|
"Select a lane header to inspect a role, or select a handoff row to inspect the direct exchange behind it.",
|
|
laneCount: (count: number) => `${count} msg${count !== 1 ? "s" : ""}`,
|
|
},
|
|
selection: {
|
|
eyebrow: "Board context",
|
|
emptyTitle: "Select a role or lane",
|
|
emptyDetail:
|
|
"Use the swimlane to choose a role header or a handoff row, then inspect the details here.",
|
|
messageEyebrow: "Message detail",
|
|
messageTitle: "Selected handoff",
|
|
messageDetail:
|
|
"Read the full message first, then use the recipient buttons to inspect each role's handling message without opening the whole lane.",
|
|
messageBody: "Full message",
|
|
sourceEyebrow: "Sender",
|
|
responseEyebrow: "Recipients",
|
|
responseTitle: (role: string) => `${role} handling message`,
|
|
responsePending: (role: string) => `${role} has not sent a handling message yet.`,
|
|
viewResponse: (role: string) => `View ${role} handling message`,
|
|
laneEyebrow: "Message lane",
|
|
laneTitle: (from: string, to: string) => `${from} to ${to}`,
|
|
laneDetail:
|
|
"This lane groups direct messages passed from the source role to the target role on the active topic.",
|
|
laneMessages: "Messages on this lane",
|
|
noLaneMessages: "No direct messages on this lane yet.",
|
|
openLane: (role: string) => `Open ${role} lane`,
|
|
openRole: (role: string) => `Open ${role}`,
|
|
threadTitle: "Latest thread updates",
|
|
threadDetail:
|
|
"Keep the newest cross-role updates visible while you inspect a single lane.",
|
|
showThread: "Show latest topic updates",
|
|
hideThread: "Hide latest topic updates",
|
|
},
|
|
focusTabs: {
|
|
label: "Workflow panels",
|
|
overview: "Overview",
|
|
roles: "Roles",
|
|
timeline: "Timeline",
|
|
},
|
|
nextStep: {
|
|
eyebrow: "Next move",
|
|
queuedTitle: (role: string) => `${role} has the baton`,
|
|
queuedDetail:
|
|
"That role already has the latest handoff. Open Roles to inspect the context, or send a correction only if the plan changed.",
|
|
runningTitle: (role: string) => `${role} is already working`,
|
|
runningDetail:
|
|
"Execution is in flight. Use Roles to inspect live output, or redirect the work only if priorities changed.",
|
|
recentTitle: (role: string) => `Route the next handoff to ${role}`,
|
|
recentDetail:
|
|
"Based on the latest activity, this is the clearest next owner for the topic.",
|
|
idleTitle: "Start with Product",
|
|
idleDetail:
|
|
"If ownership still feels fuzzy, send the next update to Product to freeze scope and route execution.",
|
|
inspectRole: (role: string) => `Inspect ${role}`,
|
|
},
|
|
composer: {
|
|
eyebrow: "Next handoff",
|
|
title: "Send the next update first",
|
|
detail:
|
|
"Messages from this page go straight to the leader. The leader decides how to decompose and dispatch the work.",
|
|
inspectRole: (role: string) => `Focus ${role}`,
|
|
},
|
|
humanTask: {
|
|
eyebrow: "Waiting On You",
|
|
title: "A role needs a human answer",
|
|
detail:
|
|
"This prompt was routed to the host-side user inbox instead of the Codex runtime. Answer here to push the workflow forward.",
|
|
fromLabel: (role: string) => `${role} is waiting for your reply`,
|
|
promptLabel: "Prompt",
|
|
responseLabel: "Your answer",
|
|
responseHint: (shortcut: string) => `${shortcut}+Enter to answer`,
|
|
placeholder: "Answer the question, clarify scope, or unblock the next handoff...",
|
|
send: "Send answer",
|
|
failed: "Couldn't send your answer.",
|
|
remaining: (count: number) => `${count} more pending question${count === 1 ? "" : "s"} after this one.`,
|
|
},
|
|
overview: {
|
|
recentEyebrow: "Recent activity",
|
|
recentTitle: "Latest events",
|
|
recentDetail:
|
|
"Scan the latest handoffs and runs here before diving into the full timeline.",
|
|
noRecentTitle: "No events yet",
|
|
noRecentDetail:
|
|
"Send the opening PRD and the first role runs will show up here.",
|
|
snapshotEyebrow: "Flow snapshot",
|
|
snapshotTitle: "Who is moving now",
|
|
snapshotDetail:
|
|
"Keep the current state readable without forcing the full role graph into the default view.",
|
|
runningTitle: "Running now",
|
|
waitingTitle: "Waiting next",
|
|
recentTitleShort: "Recently involved",
|
|
emptyRunning: "No one is running right now.",
|
|
emptyWaiting: "No queued handoff right now.",
|
|
emptyRecentRoles: "No recent role activity yet.",
|
|
openRoles: "Open role map",
|
|
openTimeline: "Open timeline",
|
|
},
|
|
sandbox: {
|
|
eyebrow: "Realtime swimlane",
|
|
title: "Handoff timeline",
|
|
detail:
|
|
"Each role keeps a fixed lane while direct handoffs stack by time. Execution state stays in the lane headers and role details.",
|
|
linkCount: (count: number) => `${count} lane${count !== 1 ? "s" : ""}`,
|
|
emptyTitle: "No handoffs yet",
|
|
emptyDetail:
|
|
"Messages will appear here once one role hands work to another. Running and failed executions stay visible in role details.",
|
|
},
|
|
roleState: {
|
|
running: "Running",
|
|
queued: "Queued",
|
|
recent: "Recent",
|
|
idle: "Idle",
|
|
},
|
|
inspector: {
|
|
eyebrow: "Role inspector",
|
|
title: "Role detail",
|
|
noSelection: "Select a role to inspect its handoffs, queue pressure, and current execution state.",
|
|
globalInbox: "Global inbox",
|
|
globalInboxValue: (count: number) => `${count} queued globally`,
|
|
lastSession: (value: string) => `Last session ${value}`,
|
|
sessionMissing: "No session recorded yet.",
|
|
latestInbound: "Latest inbound",
|
|
latestOutbound: "Latest outbound",
|
|
noInbound: "No inbound handoff for this topic yet.",
|
|
noOutbound: "No outbound handoff for this topic yet.",
|
|
currentRun: "Current run",
|
|
noCurrentRun: "No execution recorded for this topic yet.",
|
|
startedAt: (value: string) => `Started ${value}`,
|
|
completedAt: (value: string) => `Completed ${value}`,
|
|
inFlight: "Still running…",
|
|
exitCode: (value: number) => `Exit ${value}`,
|
|
liveOutput: "Live output",
|
|
waitingLiveOutput: "Waiting for live output...",
|
|
noLiveOutput: "No live output captured yet.",
|
|
},
|
|
timeline: {
|
|
eyebrow: "Event timeline",
|
|
title: "Topic events",
|
|
detail:
|
|
"Messages and runs are merged into one sequence so the operational story stays readable.",
|
|
count: (count: number) => `${count} events`,
|
|
emptyTitle: "No events yet",
|
|
emptyDetail:
|
|
"Send the opening PRD to start the topic. Role runs and replies will appear here as the work begins.",
|
|
dispatchRunning: "Run in flight",
|
|
dispatchSettled: (exitCode: number) => (exitCode === 0 ? "Run complete" : "Run failed"),
|
|
},
|
|
openingHandoff: {
|
|
eyebrow: "Opening Handoff",
|
|
creatingTitle: "Send the opening PRD",
|
|
regularTitle: "Route the next step",
|
|
creatingDetail:
|
|
"Your first message should name the outcome, who should act first, and what done looks like.",
|
|
regularDetail:
|
|
"Use the composer below to push this topic into the next phase with a concrete ask for the receiving role.",
|
|
coverPoints: "Cover these points",
|
|
exampleOpeningTitle: "Example opening",
|
|
exampleOpeningBody:
|
|
"Ship password reset. The leader should clarify scope, derive execution lanes, and start worker containers only after the task graph is ready.",
|
|
},
|
|
},
|
|
};
|
|
|
|
|
|
export type DeepWiden<T> = T extends (...args: infer A) => infer R
|
|
? (...args: A) => DeepWiden<R>
|
|
: T extends readonly (infer U)[]
|
|
? DeepWiden<U>[]
|
|
: T extends object
|
|
? { [K in keyof T]: DeepWiden<T[K]> }
|
|
: T extends string
|
|
? string
|
|
: T extends number
|
|
? number
|
|
: T extends boolean
|
|
? boolean
|
|
: T;
|
|
|
|
export type AppCopy = DeepWiden<typeof en>;
|