This commit is contained in:
legop3
2026-02-27 23:22:32 -05:00
parent ae52dc8335
commit 99b10f7310
2 changed files with 44 additions and 32 deletions
+3
View File
@@ -27,6 +27,7 @@ Environment facts:
- Docks on carpet-side beam by TV stand; another dock at concrete workbench. - Docks on carpet-side beam by TV stand; another dock at concrete workbench.
- "Call Carpet" phone button on that beam. - "Call Carpet" phone button on that beam.
- Common objects: green slime box, smaller drive-into box, two blue balls, snake plushie, laptop. - Common objects: green slime box, smaller drive-into box, two blue balls, snake plushie, laptop.
- Do not mention room objects unless they appear in recent chat/event context.
Rover context: Rover context:
- Context uses compact keys. - Context uses compact keys.
@@ -34,6 +35,7 @@ Rover context:
- `rn` keys: `st bl dk ch wg hz ab at`. - `rn` keys: `st bl dk ch wg hz ab at`.
- SNAPSHOT rover keys: `id drv st bl dk ch wg ct hz mb as ab at`. - SNAPSHOT rover keys: `id drv st bl dk ch wg ct hz mb as ab at`.
- `goal` in SNAPSHOT FINAL is the community goal (may be `none`). - `goal` in SNAPSHOT FINAL is the community goal (may be `none`).
- Values are readable words or 0/1 booleans, not cryptic codes.
- activity_score may appear for internal significance only. - activity_score may appear for internal significance only.
EVENT rule: EVENT rule:
@@ -59,6 +61,7 @@ Anti-repeat:
- Avoid back-to-back same rover + same event type unless clearly new angle. - Avoid back-to-back same rover + same event type unless clearly new angle.
- If line could be reused by swapping only a name, SKIP. - If line could be reused by swapping only a name, SKIP.
- Avoid repeating opener patterns. - Avoid repeating opener patterns.
- If your last line made the same core claim, SKIP.
Grounding: Grounding:
- Use timeline for flow; use SNAPSHOT FINAL as truth. - Use timeline for flow; use SNAPSHOT FINAL as truth.
+41 -32
View File
@@ -835,67 +835,75 @@ function parseModelOutput(rawContent) {
}; };
} }
function normalizeDuplicateKey(text) {
return String(text || '')
.toLowerCase()
.replace(/[^a-z0-9\s]/g, ' ')
.replace(/\s+/g, ' ')
.trim();
}
function encBool(value) { function encBool(value) {
return value ? '1' : '0'; return value ? '1' : '0';
} }
function encStatus(value) { function encStatus(value) {
const map = { const map = {
charging: 'cg', charging: 'charging',
docked: 'dk', docked: 'docked',
driving: 'dr', driving: 'driving',
'active-idle': 'ai', 'active-idle': 'active_idle',
idle: 'id', idle: 'idle',
unknown: 'un', unknown: 'unknown',
}; };
return map[String(value || 'unknown')] || 'un'; return map[String(value || 'unknown')] || 'unknown';
} }
function encHazard(value) { function encHazard(value) {
const map = { const map = {
normal: 'n', normal: 'normal',
cliff: 'c', cliff: 'cliff',
hot_left: 'hl', hot_left: 'hot_left',
hot_right: 'hr', hot_right: 'hot_right',
}; };
return map[String(value || 'normal')] || 'n'; return map[String(value || 'normal')] || 'normal';
} }
function encContact(value) { function encContact(value) {
const map = { const map = {
clear: 'c', clear: 'clear',
wall_brush: 'wb', wall_brush: 'wall_brush',
bumps_recent: 'br', bumps_recent: 'bumps_recent',
}; };
return map[String(value || 'clear')] || 'c'; return map[String(value || 'clear')] || 'clear';
} }
function encMobility(value) { function encMobility(value) {
const map = { const map = {
normal: 'n', normal: 'normal',
lifted: 'l', lifted: 'lifted',
}; };
return map[String(value || 'normal')] || 'n'; return map[String(value || 'normal')] || 'normal';
} }
function encActivityBand(value) { function encActivityBand(value) {
const map = { const map = {
idle: 'i', idle: 'idle',
low: 'l', low: 'low',
medium: 'm', medium: 'medium',
high: 'h', high: 'high',
intense: 'x', intense: 'intense',
}; };
return map[String(value || 'idle')] || 'i'; return map[String(value || 'idle')] || 'idle';
} }
function encActivityTrend(value) { function encActivityTrend(value) {
const map = { const map = {
rising: 'r', rising: 'rising',
steady: 's', steady: 'steady',
falling: 'f', falling: 'falling',
}; };
return map[String(value || 'steady')] || 's'; return map[String(value || 'steady')] || 'steady';
} }
function formatChatRoverCtx(ctx) { function formatChatRoverCtx(ctx) {
@@ -1169,12 +1177,13 @@ async function runTick() {
updatePhase('decision_post', { updatePhase('decision_post', {
lastGeneratedText: text, lastGeneratedText: text,
}); });
const recentBotMessages = getRecentMessages(80, { includeSystem: true }) const recentBotMessages = getRecentMessages(120, { includeSystem: true })
.filter((entry) => Number(entry?.ts) >= contextResetAt) .filter((entry) => Number(entry?.ts) >= contextResetAt)
.filter((entry) => entry?.system) .filter((entry) => entry?.system)
.slice(-MAX_BOT_MESSAGES); .slice(-Math.max(3, MAX_BOT_MESSAGES));
const duplicateKey = normalizeDuplicateKey(text);
const duplicate = recentBotMessages.some( const duplicate = recentBotMessages.some(
(entry) => String(entry?.text || '').trim().toLowerCase() === text.toLowerCase(), (entry) => normalizeDuplicateKey(entry?.text) === duplicateKey,
); );
if (duplicate) { if (duplicate) {
logger.info('Commentary tick skipped duplicate output', { tickId, text }); logger.info('Commentary tick skipped duplicate output', { tickId, text });