fix(agent): align World Packet with reviewer feedback and voice parity

Reuse one context/contacts/tracking owner in voice and World Packet. Compare voice outputs after stripping presentation fields; remove the unconsumed fingerprint API pending an actual caller. Document the exported packet boundary and reject null options safely.

Review guidance: asturksever on origin #880; Windows parity diagnosis by quanticsoul4772. Existing source ownership retained.
This commit is contained in:
Kevin Rajan committed 2026-10-17 13:12:46 -05:00
1 parent 83fc895442
commit 1c4c903ac6
5 files changed
+34 -181

No files matched your search

+9 -39
View File
@@ -6,7 +6,7 @@ import {
} from '../data/layerSnapshot.js';
import { contextModeWord } from '../contextModePolicy.js';
const TRACKABLE_FAMILIES = Object.freeze([
export const TRACKABLE_FAMILIES = Object.freeze([
{ layerId: 'flights', kind: 'aircraft' },
{ layerId: 'military', kind: 'aircraft' },
{ layerId: 'ais-live-vessels', kind: 'vessel' },
@@ -24,37 +24,6 @@ const NESTED_CONTEXT_RESULT_FIELDS = Object.freeze([
'contextRollback',
]);
const NON_SEMANTIC_PACKET_KEYS = new Set(['note', 'ageLabel', 'generatedAt']);
function semanticPacketValue(value) {
if (Array.isArray(value)) return value.map(semanticPacketValue);
if (!value || typeof value !== 'object') return value;
const out = {};
for (const key of Object.keys(value).sort()) {
if (NON_SEMANTIC_PACKET_KEYS.has(key)) continue;
out[key] = semanticPacketValue(value[key]);
}
return out;
}
/**
* Stable semantic fingerprint for change detection, not authentication.
*
* Presentation-only narration/age labels are excluded. Feed state, source,
* lastUpdate, camera, context, tracked entities, and other semantic state stay
* inside the digest.
*/
export function semanticWorldPacketFingerprint(packet) {
const canonical = JSON.stringify(semanticPacketValue(packet));
let hash = 0xcbf29ce484222325n;
const prime = 0x100000001b3n;
for (let i = 0; i < canonical.length; i += 1) {
hash ^= BigInt(canonical.charCodeAt(i));
hash = BigInt.asUintN(64, hash * prime);
}
return `fnv1a64:${hash.toString(16).padStart(16, '0')}`;
}
/**
* Translate context-mode payloads into the public tool vocabulary while
* retaining the internal id beside each translated field.
@@ -124,13 +93,14 @@ export function activeContactsWindow(dataManager) {
* This performs no network requests and intentionally mirrors the historical
* get_current_view_state payload so voice can delegate without behavior drift.
*/
export function getWorldPacket({
viewer,
styleManager,
dataManager,
sceneDirector = null,
now = Date.now(),
} = {}) {
export function getWorldPacket(options = {}) {
const {
viewer,
styleManager,
dataManager,
sceneDirector = null,
now = Date.now(),
} = options ?? {};
if (!viewer?.camera?.positionWC)
throw new TypeError('World Packet requires a viewer camera');
if (!dataManager || typeof dataManager.getAll !== 'function')