Skip to content

Commit a4f8f97

Browse files
committed
Fix Codex exec flags and ledger chat
1 parent 2d2baac commit a4f8f97

11 files changed

Lines changed: 154 additions & 20 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Download packaged builds from GitHub Releases:
88

99
https://github.com/TerminallyLazy/MISCONDUCT/releases/latest
1010

11-
Current app metadata in this checkout is `0.1.18`. The public latest release page may
12-
still show older assets until tag `v0.1.18` is pushed and the desktop release workflow
13-
publishes new artifacts.
11+
Current app metadata in this checkout is `0.1.19`. The public latest release page
12+
is updated by pushing the matching release tag and letting the desktop workflow
13+
publish the new artifacts.
1414

1515
The GitHub Actions workflow `.github/workflows/release-desktop.yml` is configured to build macOS arm64, Windows x86_64, and Linux x86_64 packages from release tags.
1616

RELEASE_WORKFLOW_NOTE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ It builds:
88
- Windows x86_64 NSIS installer
99
- Linux x86_64 AppImage/DEB
1010

11-
Push a release tag such as `v0.1.18` or run the workflow manually from GitHub Actions to produce MISCONDUCT release artifacts.
11+
Push a release tag such as `v0.1.19` or run the workflow manually from GitHub Actions to produce MISCONDUCT release artifacts.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "misconduct-desktop",
3-
"version": "0.1.18",
3+
"version": "0.1.19",
44
"private": true,
55
"type": "module",
66
"scripts": {

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "misconduct_desktop"
3-
version = "0.1.18"
3+
version = "0.1.19"
44
edition = "2021"
55

66
[build-dependencies]

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"productName": "MISCONDUCT",
3-
"version": "0.1.18",
3+
"version": "0.1.19",
44
"identifier": "dev.misconduct.desktop",
55
"build": {
66
"beforeDevCommand": "npm run dev",

src/main.tsx

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,73 @@ function providerLabel(provider?: string) {
12611261
return 'MISCONDUCT';
12621262
}
12631263

1264+
function phaseAgentLabel(stage?: string) {
1265+
const value = String(stage || '').toLowerCase();
1266+
if (value === 'conductor') return 'Conductor';
1267+
if (value === 'build' || value === 'builder') return 'Builder';
1268+
if (value === 'judge' || value === 'review') return 'Judge';
1269+
if (value === 'refiner' || value === 'refine') return 'Refiner';
1270+
if (value === 'retry') return 'Stage Manager';
1271+
return 'MISCONDUCT';
1272+
}
1273+
1274+
function eventAgentName(event: OrchestrationEvent) {
1275+
const data = event.data;
1276+
if (!data || typeof data !== 'object' || Array.isArray(data)) return '';
1277+
const profile = data.agent_profile;
1278+
if (!profile || typeof profile !== 'object' || Array.isArray(profile)) return '';
1279+
return stringField(profile as Record<string, unknown>, 'name');
1280+
}
1281+
1282+
function eventSpeaker(event: OrchestrationEvent) {
1283+
const type = String(event.type || '').toLowerCase();
1284+
const action = String(event.action || '').toLowerCase();
1285+
const agentName = eventAgentName(event);
1286+
1287+
if (type.includes('operator')) return 'Operator';
1288+
if (type.includes('retry')) return 'Stage Manager';
1289+
if (type === 'agent.event' && (action === 'stdout' || action === 'turn_completed')) {
1290+
return agentName || phaseAgentLabel(event.stage);
1291+
}
1292+
if (type === 'agent.event' && (action === 'stderr' || action === 'turn_failed' || action === 'session_started')) {
1293+
return 'Codex Runner';
1294+
}
1295+
if (agentName) return agentName;
1296+
if (event.stage) return phaseAgentLabel(event.stage);
1297+
return providerLabel(event.provider);
1298+
}
1299+
1300+
function eventReadableType(event: OrchestrationEvent) {
1301+
const type = String(event.type || '').toLowerCase();
1302+
const action = String(event.action || '').toLowerCase();
1303+
1304+
if (type === 'operator.issue.action.accepted') return 'Operator accepted action';
1305+
if (type === 'issue.stage.started') return `${phaseAgentLabel(event.stage)} started`;
1306+
if (type === 'issue.stage.completed') return `${phaseAgentLabel(event.stage)} completed`;
1307+
if (type === 'issue.stage.blocked') return `${phaseAgentLabel(event.stage)} blocked`;
1308+
if (type === 'issue.score.ready') return 'Conductor score ready';
1309+
if (type === 'issue.judge.verdict') return 'Judge verdict';
1310+
if (type === 'issue.execution.completed') return 'Movement completed';
1311+
if (type === 'issue.execution.failed') return 'Movement failed';
1312+
if (type === 'issue.retry.scheduled') return 'Retry scheduled';
1313+
if (type === 'agent.event' && action === 'session_started') return 'Subprocess started';
1314+
if (type === 'agent.event' && action === 'stdout') return 'Agent output';
1315+
if (type === 'agent.event' && action === 'stderr') return 'Runner output';
1316+
if (type === 'agent.event' && action === 'turn_completed') return 'Turn completed';
1317+
if (type === 'agent.event' && action === 'turn_failed') return 'Turn failed';
1318+
return event.type || 'Event';
1319+
}
1320+
1321+
function eventTone(event: OrchestrationEvent) {
1322+
const combined = `${event.status || ''} ${event.type || ''} ${event.action || ''}`.toLowerCase();
1323+
if (combined.match(/fail|error|stderr|block|reject/)) return 'danger';
1324+
if (combined.match(/retry|refin|attention/)) return 'warning';
1325+
if (combined.match(/judge|review|verdict/)) return 'review';
1326+
if (combined.match(/complete|pass|approved|ready/)) return 'success';
1327+
if (combined.match(/start|running|accepted/)) return 'active';
1328+
return 'neutral';
1329+
}
1330+
12641331
function authPhaseLabel(phase?: string) {
12651332
const normalized = String(phase || '').replace(/_/g, ' ');
12661333
if (!normalized) return 'auth phase unknown';
@@ -2383,8 +2450,7 @@ function MovementEvents({ card, debugPayload, liveEvents }: { card: Card; debugP
23832450
const ids = [event.issue_id, event.issue_identifier].filter(Boolean);
23842451
return ids.includes(card.backendId) || ids.includes(card.identifier);
23852452
})
2386-
.slice(-18)
2387-
.reverse();
2453+
.slice(-24);
23882454
const events = [
23892455
['Movement', card.movement],
23902456
['Status', card.status],
@@ -2400,14 +2466,42 @@ function MovementEvents({ card, debugPayload, liveEvents }: { card: Card; debugP
24002466
<div className="movementTimeline">
24012467
{events.map(([label, value]) => <div className="timelineRow" key={label}><b>{label}</b><span>{value}</span></div>)}
24022468
<div className="liveMovementLedger">
2403-
<h3>Live pit ledger</h3>
2404-
{movementEvents.length ? movementEvents.map(event => <EventRow event={event} key={event.id} />) : <p className="subtle">No live events for this movement yet.</p>}
2469+
<h3>Agent conversation</h3>
2470+
{movementEvents.length ? <EventConversation events={movementEvents} /> : <p className="subtle">No live events for this movement yet.</p>}
24052471
</div>
24062472
{debugPayload && <pre className="debugPanel inline">{debugPayload}</pre>}
24072473
</div>
24082474
);
24092475
}
24102476

2477+
function EventConversation({ events }: { events: OrchestrationEvent[] }) {
2478+
return (
2479+
<div className="eventConversation" aria-label="Movement agent conversation">
2480+
{events.map(event => <EventBubble event={event} key={event.id} />)}
2481+
</div>
2482+
);
2483+
}
2484+
2485+
function EventBubble({ event }: { event: OrchestrationEvent }) {
2486+
const speaker = eventSpeaker(event);
2487+
const own = speaker === 'Operator' || speaker === 'Conductor' || speaker === 'Workflow Conductor';
2488+
const tone = eventTone(event);
2489+
const message = event.message || event.action || 'Event received';
2490+
2491+
return (
2492+
<div className={`eventBubbleRow ${own ? 'own' : ''}`}>
2493+
<div className={`agentBubble ${tone}`}>
2494+
<div className="speechMeta">
2495+
<b>{speaker}</b>
2496+
<span>{formatEventTime(event.occurred_at)}</span>
2497+
</div>
2498+
<p>{message}</p>
2499+
<small>{eventReadableType(event)} · {providerLabel(event.provider)}</small>
2500+
</div>
2501+
</div>
2502+
);
2503+
}
2504+
24112505
function MovementTools({ card, busy, onDebug, onMove, onAction }: { card: Card; busy: boolean; onDebug: (id: string) => void; onMove: (id: string, target: string) => void; onAction: (id: string, action: string) => void }) {
24122506
return (
24132507
<div className="movementTools">
@@ -3080,9 +3174,9 @@ function EventRow({ event }: { event: OrchestrationEvent }) {
30803174
return (
30813175
<div className="eventRow">
30823176
<div className="eventMain">
3083-
<span className={`eventDot ${statusClass(event.status || event.type)}`} />
3177+
<span className={`eventDot ${eventTone(event)}`} />
30843178
<div>
3085-
<b>{event.type}</b>
3179+
<b>{eventReadableType(event)}</b>
30863180
<small>{providerLabel(event.provider)} · {event.stage || 'system'} · {formatEventTime(event.occurred_at)}</small>
30873181
</div>
30883182
</div>

src/styles.css

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,46 @@ code { color: #584174; background: #fff2bd; padding: 1px 5px; border: 2px solid
572572
background: #fff8e8;
573573
}
574574
.liveMovementLedger h3 { margin: 0; font-size: 14px; }
575+
.eventConversation {
576+
display: grid;
577+
gap: 9px;
578+
max-height: 360px;
579+
overflow: auto;
580+
padding-right: 2px;
581+
}
582+
.eventBubbleRow { display: flex; justify-content: flex-start; }
583+
.eventBubbleRow.own { justify-content: flex-end; }
584+
.agentBubble {
585+
width: min(100%, 310px);
586+
display: grid;
587+
gap: 5px;
588+
padding: 9px 10px;
589+
border: 3px solid var(--ink);
590+
background: #fffdf5;
591+
box-shadow: 3px 3px 0 #0002;
592+
}
593+
.agentBubble p {
594+
margin: 0;
595+
line-height: 1.35;
596+
overflow-wrap: anywhere;
597+
color: var(--ink-2);
598+
}
599+
.agentBubble small {
600+
display: block;
601+
min-width: 0;
602+
overflow: hidden;
603+
text-overflow: ellipsis;
604+
white-space: nowrap;
605+
color: var(--muted);
606+
font-size: 10px;
607+
font-weight: 900;
608+
text-transform: uppercase;
609+
}
610+
.agentBubble.active { background: #d7edf2; }
611+
.agentBubble.success { background: #dcefb6; }
612+
.agentBubble.warning { background: #ffe58a; }
613+
.agentBubble.review { background: #e7daf8; }
614+
.agentBubble.danger { background: #ffd4d0; }
575615
.debugPanel.inline { margin: 0; max-height: 180px; }
576616
.scoreArtifact {
577617
display: grid;

symphony_elixir/lib/symphony/agent_runner/codex.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ defmodule Symphony.AgentRunner.Codex do
22
@behaviour Symphony.AgentRunner
33
@codex_exec_args [
44
"exec",
5-
"--ask-for-approval",
6-
"never",
5+
"-c",
6+
"approval_policy=\"never\"",
77
"--sandbox",
88
"workspace-write",
99
"--skip-git-repo-check",

0 commit comments

Comments
 (0)