From f0c67c00dc7cd51588deb22740658e7059556b9c Mon Sep 17 00:00:00 2001
From: Pim Hutting
Date: Mon, 12 Jan 2026 12:49:00 +0100
Subject: [PATCH] fix: update goals and trigger/norms.. correctly
feat: N25B-400
---
src/pages/MonitoringPage/Components.tsx | 35 ++++++---
src/pages/MonitoringPage/MonitoringPage.tsx | 87 +++++++++++++++------
2 files changed, 88 insertions(+), 34 deletions(-)
diff --git a/src/pages/MonitoringPage/Components.tsx b/src/pages/MonitoringPage/Components.tsx
index c60a702..f1adffa 100644
--- a/src/pages/MonitoringPage/Components.tsx
+++ b/src/pages/MonitoringPage/Components.tsx
@@ -106,24 +106,34 @@ interface StatusListProps {
title: string;
items: any[];
type: 'goal' | 'trigger' | 'norm'| 'cond_norm';
+ activeIds: Record;
+ currentGoalIndex?: number;
}
// --- STATUS LIST COMPONENT ---
-export const StatusList: React.FC = ({ title, items, type }) => {
-
+export const StatusList: React.FC = ({
+ title,
+ items,
+ type,
+ activeIds,
+ currentGoalIndex // Destructure this prop
+}) => {
return (
{title}
{items.map((item, idx) => {
- let isAchieved = item.achieved;
+ const isActive = !!activeIds[item.id];
const showIndicator = type !== 'norm';
- const canOverride = showIndicator && !isAchieved;
- const isCurrentGoal = type === 'goal' && item.isCurrent;
+ const canOverride = showIndicator && !isActive;
+
+ // HIGHLIGHT LOGIC:
+ // If this is the "Goals" list, check if the current index matches
+ const isCurrentGoal = type === 'goal' && idx === currentGoalIndex;
+
const handleOverrideClick = () => {
if (!canOverride) return;
- let contextValue = String(item.id);
- sendUserInterrupt("override", contextValue);
+ sendUserInterrupt("override", String(item.id));
};
return (
@@ -133,18 +143,23 @@ export const StatusList: React.FC = ({ title, items, type }) =>
className={`${styles.statusIndicator} ${canOverride ? styles.clickable : ''}`}
onClick={handleOverrideClick}
>
- {isAchieved ? "✔️" : "❌"}
+ {isActive ? "✔️" : "❌"}
)}
-
{item.description || item.label || item.norm}
+ {isCurrentGoal && " (Current)"}
);
diff --git a/src/pages/MonitoringPage/MonitoringPage.tsx b/src/pages/MonitoringPage/MonitoringPage.tsx
index e63eaee..47b3570 100644
--- a/src/pages/MonitoringPage/MonitoringPage.tsx
+++ b/src/pages/MonitoringPage/MonitoringPage.tsx
@@ -22,6 +22,7 @@ const MonitoringPage: React.FC = () => {
const phaseIds = getPhaseIds();
const [phaseIndex, setPhaseIndex] = React.useState(0);
+ const isFinished = phaseIndex >= phaseIds.length; //determines if experiment is over
const handleStreamUpdate = React.useCallback((data: any) => {
// Check for phase updates
@@ -34,19 +35,29 @@ const MonitoringPage: React.FC = () => {
}
}
else if (data.type === 'goal_update') {
- // We find which goal in the current phase matches this ID
- const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]);
+ const currentPhaseGoals = getGoalsInPhase(phaseIds[phaseIndex]) as any[];
const gIndex = currentPhaseGoals.findIndex((g: any) => g.id === data.id);
- if (gIndex !== -1) {
- setGoalIndex(gIndex);
- console.log(`Goal index updated to ${gIndex} for goal ID ${data.id}`);
- }
- setActiveIds((prev) => ({
- ...prev,
- [data.id]: true
- }));
+ if (gIndex !== -1) {
+ //set current goal to the goal that is just started
+ setGoalIndex(gIndex);
+
+ // All previous goals are set to "active" which means they are achieved
+ setActiveIds((prev) => {
+ const nextState = { ...prev };
+
+ // We loop until i is LESS than gIndex.
+ // This leaves currentPhaseGoals[gIndex] as isActive: false.
+ for (let i = 0; i < gIndex; i++) {
+ nextState[currentPhaseGoals[i].id ] = true;
+ }
+
+ return nextState;
+ });
+
+ console.log(`Now pursuing goal: ${data.id}. Previous goals marked achieved.`);
}
+ }
else if (data.type === 'trigger_update') {
setActiveIds((prev) => ({
@@ -54,7 +65,19 @@ const MonitoringPage: React.FC = () => {
[data.id]: data.achieved // data.id is de key, achieved is true/false
}));
}
- }, [getPhaseIds]);
+ else if (data.type === 'cond_norms_state_update') {
+ setActiveIds((prev) => {
+ const nextState = { ...prev };
+
+ data.norms.forEach((normUpdate: { id: string; active: boolean }) => {
+ nextState[normUpdate.id] = normUpdate.active;
+ });
+
+ return nextState;
+ });
+ console.log("Updated conditional norms state:", data.norms);
+ }
+}, [getPhaseIds]);
useExperimentLogger(handleStreamUpdate);
@@ -74,30 +97,39 @@ const MonitoringPage: React.FC = () => {
const triggers = (getTriggersInPhase(phaseId) as any[]).map(t => ({
...t,
label: (() => {
- // Determine the Condition Prefix
- let prefix = t.label; // Default fallback
+
+ let prefix = "";
if (t.condition?.keyword) {
prefix = `if keywords said: "${t.condition.keyword}"`;
} else if (t.condition?.name) {
prefix = `if LLM belief: ${t.condition.name}`;
+ } else { //fallback
+ prefix = t.label || "Trigger";
}
- // Format the Plan Steps
- // We check if plan exists and has steps
+
const stepLabels = t.plan?.steps?.map((step: any) => {
-
- return step.label || step.name || "Action";
+ if (step.text) {
+ return `say: "${step.text}"`;
+ }
+ if (step.gesture) {
+ return `perform gesture: ${step.gesture.name || step.gesture.type}`;
+ }
+ if (step.goal) {
+ return `perform LLM: ${step.goal}`;
+ }
+ return "Action"; // Fallback
}) || [];
const planText = stepLabels.length > 0
? `➔ Do: ${stepLabels.join(", ")}`
: "➔ (No actions set)";
- // "If [Condition] ➔ Do: [Steps]"
return `${prefix} ${planText}`;
})(),
- achieved: activeIds[t.id] ?? false
+ isActive: activeIds[t.id] ?? false
}));
+
const norms = (getNormsInPhase(phaseId) as NormNodeData[])
.filter(n => !n.condition)
.map(n => ({
@@ -186,11 +218,18 @@ const MonitoringPage: React.FC = () => {
-
-
-
-
-
+ {isFinished ? (
+
+
All phases have been successfully completed.
+
+ ) : (
+ <>
+
+
+
+
+ >
+ )}
{/* LOGS */}