fix: wire generated_by_model into observation write path
The generated_by_model column was added to the observations table in the Phase 0 governance schema migration but never wired into the INSERT statements. All 3,878+ observations in production have this field NULL. This fix threads the model ID from each agent (SDKAgent, GeminiAgent, OpenRouterAgent) through processAgentResponse() into storeObservation(), storeObservations(), and storeObservationsAndMarkComplete(). Unblocks Thompson Sampling RFC (#1571) which needs {obs_type}:{model} as the bandit arm key. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1517,7 +1517,8 @@ export class SessionStore {
|
|||||||
},
|
},
|
||||||
promptNumber?: number,
|
promptNumber?: number,
|
||||||
discoveryTokens: number = 0,
|
discoveryTokens: number = 0,
|
||||||
overrideTimestampEpoch?: number
|
overrideTimestampEpoch?: number,
|
||||||
|
generatedByModel?: string
|
||||||
): { id: number; createdAtEpoch: number } {
|
): { id: number; createdAtEpoch: number } {
|
||||||
// Use override timestamp if provided (for processing backlog messages with original timestamps)
|
// Use override timestamp if provided (for processing backlog messages with original timestamps)
|
||||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||||
@@ -1533,8 +1534,9 @@ export class SessionStore {
|
|||||||
const stmt = this.db.prepare(`
|
const stmt = this.db.prepare(`
|
||||||
INSERT INTO observations
|
INSERT INTO observations
|
||||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
generated_by_model)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const result = stmt.run(
|
const result = stmt.run(
|
||||||
@@ -1552,7 +1554,8 @@ export class SessionStore {
|
|||||||
discoveryTokens,
|
discoveryTokens,
|
||||||
contentHash,
|
contentHash,
|
||||||
timestampIso,
|
timestampIso,
|
||||||
timestampEpoch
|
timestampEpoch,
|
||||||
|
generatedByModel || null
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -1651,7 +1654,8 @@ export class SessionStore {
|
|||||||
} | null,
|
} | null,
|
||||||
promptNumber?: number,
|
promptNumber?: number,
|
||||||
discoveryTokens: number = 0,
|
discoveryTokens: number = 0,
|
||||||
overrideTimestampEpoch?: number
|
overrideTimestampEpoch?: number,
|
||||||
|
generatedByModel?: string
|
||||||
): { observationIds: number[]; summaryId: number | null; createdAtEpoch: number } {
|
): { observationIds: number[]; summaryId: number | null; createdAtEpoch: number } {
|
||||||
// Use override timestamp if provided
|
// Use override timestamp if provided
|
||||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||||
@@ -1665,8 +1669,9 @@ export class SessionStore {
|
|||||||
const obsStmt = this.db.prepare(`
|
const obsStmt = this.db.prepare(`
|
||||||
INSERT INTO observations
|
INSERT INTO observations
|
||||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
generated_by_model)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
for (const observation of observations) {
|
for (const observation of observations) {
|
||||||
@@ -1693,7 +1698,8 @@ export class SessionStore {
|
|||||||
discoveryTokens,
|
discoveryTokens,
|
||||||
contentHash,
|
contentHash,
|
||||||
timestampIso,
|
timestampIso,
|
||||||
timestampEpoch
|
timestampEpoch,
|
||||||
|
generatedByModel || null
|
||||||
);
|
);
|
||||||
observationIds.push(Number(result.lastInsertRowid));
|
observationIds.push(Number(result.lastInsertRowid));
|
||||||
}
|
}
|
||||||
@@ -1780,7 +1786,8 @@ export class SessionStore {
|
|||||||
_pendingStore: PendingMessageStore,
|
_pendingStore: PendingMessageStore,
|
||||||
promptNumber?: number,
|
promptNumber?: number,
|
||||||
discoveryTokens: number = 0,
|
discoveryTokens: number = 0,
|
||||||
overrideTimestampEpoch?: number
|
overrideTimestampEpoch?: number,
|
||||||
|
generatedByModel?: string
|
||||||
): { observationIds: number[]; summaryId?: number; createdAtEpoch: number } {
|
): { observationIds: number[]; summaryId?: number; createdAtEpoch: number } {
|
||||||
// Use override timestamp if provided
|
// Use override timestamp if provided
|
||||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||||
@@ -1794,8 +1801,9 @@ export class SessionStore {
|
|||||||
const obsStmt = this.db.prepare(`
|
const obsStmt = this.db.prepare(`
|
||||||
INSERT INTO observations
|
INSERT INTO observations
|
||||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
generated_by_model)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
for (const observation of observations) {
|
for (const observation of observations) {
|
||||||
@@ -1822,7 +1830,8 @@ export class SessionStore {
|
|||||||
discoveryTokens,
|
discoveryTokens,
|
||||||
contentHash,
|
contentHash,
|
||||||
timestampIso,
|
timestampIso,
|
||||||
timestampEpoch
|
timestampEpoch,
|
||||||
|
generatedByModel || null
|
||||||
);
|
);
|
||||||
observationIds.push(Number(result.lastInsertRowid));
|
observationIds.push(Number(result.lastInsertRowid));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,9 @@ export class GeminiAgent {
|
|||||||
worker,
|
worker,
|
||||||
tokensUsed,
|
tokensUsed,
|
||||||
null,
|
null,
|
||||||
'Gemini'
|
'Gemini',
|
||||||
|
undefined,
|
||||||
|
model
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.error('SDK', 'Empty Gemini init response - session may lack context', {
|
logger.error('SDK', 'Empty Gemini init response - session may lack context', {
|
||||||
@@ -248,7 +250,8 @@ export class GeminiAgent {
|
|||||||
tokensUsed,
|
tokensUsed,
|
||||||
originalTimestamp,
|
originalTimestamp,
|
||||||
'Gemini',
|
'Gemini',
|
||||||
lastCwd
|
lastCwd,
|
||||||
|
model
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.warn('SDK', 'Empty Gemini observation response, skipping processing to preserve message', {
|
logger.warn('SDK', 'Empty Gemini observation response, skipping processing to preserve message', {
|
||||||
@@ -298,7 +301,8 @@ export class GeminiAgent {
|
|||||||
tokensUsed,
|
tokensUsed,
|
||||||
originalTimestamp,
|
originalTimestamp,
|
||||||
'Gemini',
|
'Gemini',
|
||||||
lastCwd
|
lastCwd,
|
||||||
|
model
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.warn('SDK', 'Empty Gemini summary response, skipping processing to preserve message', {
|
logger.warn('SDK', 'Empty Gemini summary response, skipping processing to preserve message', {
|
||||||
|
|||||||
@@ -131,7 +131,8 @@ export class OpenRouterAgent {
|
|||||||
tokensUsed,
|
tokensUsed,
|
||||||
null,
|
null,
|
||||||
'OpenRouter',
|
'OpenRouter',
|
||||||
undefined // No lastCwd yet - before message processing
|
undefined, // No lastCwd yet - before message processing
|
||||||
|
model
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.error('SDK', 'Empty OpenRouter init response - session may lack context', {
|
logger.error('SDK', 'Empty OpenRouter init response - session may lack context', {
|
||||||
@@ -202,7 +203,8 @@ export class OpenRouterAgent {
|
|||||||
tokensUsed,
|
tokensUsed,
|
||||||
originalTimestamp,
|
originalTimestamp,
|
||||||
'OpenRouter',
|
'OpenRouter',
|
||||||
lastCwd
|
lastCwd,
|
||||||
|
model
|
||||||
);
|
);
|
||||||
|
|
||||||
} else if (message.type === 'summarize') {
|
} else if (message.type === 'summarize') {
|
||||||
@@ -244,7 +246,8 @@ export class OpenRouterAgent {
|
|||||||
tokensUsed,
|
tokensUsed,
|
||||||
originalTimestamp,
|
originalTimestamp,
|
||||||
'OpenRouter',
|
'OpenRouter',
|
||||||
lastCwd
|
lastCwd,
|
||||||
|
model
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,7 +270,8 @@ export class SDKAgent {
|
|||||||
discoveryTokens,
|
discoveryTokens,
|
||||||
originalTimestamp,
|
originalTimestamp,
|
||||||
'SDK',
|
'SDK',
|
||||||
cwdTracker.lastCwd
|
cwdTracker.lastCwd,
|
||||||
|
modelId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ export async function processAgentResponse(
|
|||||||
discoveryTokens: number,
|
discoveryTokens: number,
|
||||||
originalTimestamp: number | null,
|
originalTimestamp: number | null,
|
||||||
agentName: string,
|
agentName: string,
|
||||||
projectRoot?: string
|
projectRoot?: string,
|
||||||
|
modelId?: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Track generator activity for stale detection (Issue #1099)
|
// Track generator activity for stale detection (Issue #1099)
|
||||||
session.lastGeneratorActivity = Date.now();
|
session.lastGeneratorActivity = Date.now();
|
||||||
@@ -102,7 +103,8 @@ export async function processAgentResponse(
|
|||||||
summaryForStore,
|
summaryForStore,
|
||||||
session.lastPromptNumber,
|
session.lastPromptNumber,
|
||||||
discoveryTokens,
|
discoveryTokens,
|
||||||
originalTimestamp ?? undefined
|
originalTimestamp ?? undefined,
|
||||||
|
modelId
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log storage result with IDs for end-to-end traceability
|
// Log storage result with IDs for end-to-end traceability
|
||||||
|
|||||||
Reference in New Issue
Block a user