fix: the My Resources diagnostics survive a deploy
Some checks failed
Forgejo Android APK / Root app tests (push) Successful in 47s
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Android APK / Build signed APK (push) Successful in 2m5s
Forgejo Docker Build / Build Docker image (push) Successful in 17s
Forgejo Docker Build / Deploy to the host (push) Failing after 0s
Some checks failed
Forgejo Android APK / Root app tests (push) Successful in 47s
Forgejo Docker Build / Root app tests (push) Successful in 52s
Forgejo Android APK / Build signed APK (push) Successful in 2m5s
Forgejo Docker Build / Build Docker image (push) Successful in 17s
Forgejo Docker Build / Deploy to the host (push) Failing after 0s
logRefine writes the one line that answers "did that modification change anything" — path, before and after size, CHANGED=yes/no, figures, model, instruction. It went to console, so it lived in the container's stdout and was destroyed the next time the container was recreated. That cost a diagnosis today: a modification came back unchanged, the user asked why, and the evidence had already been deleted by a deploy. The deck-fallback warnings and the deck-vocabulary gaps had the same problem, and those exist specifically to be read later — the vocabulary gaps are meant to show which shapes to build next, which is a question about weeks, not about one container. All of them now go through logger, which writes the dated file in the scribe-logs volume and ships to Loki when it is configured, and carries the event as structured data rather than only as a formatted string. console.error is left alone: those are failures, and logger.error already echoes to the console. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
This commit is contained in:
parent
c9b6d6b3c9
commit
491a2b0811
2 changed files with 17 additions and 7 deletions
|
|
@ -24,6 +24,13 @@ var resourceImages = require('../utils/resourceImages');
|
|||
var deckSchema = require('../utils/deckSchema');
|
||||
var deckBuild = require('../utils/deckBuild');
|
||||
var deckReview = require('../utils/deckReview');
|
||||
// The diagnostics below are the record of what a generation or a modification
|
||||
// actually did. console goes to the container's stdout, which is destroyed every
|
||||
// time the container is recreated — so the one question these exist to answer,
|
||||
// "did that modification change anything", became unanswerable after any deploy.
|
||||
// logger writes to the dated file in the scribe-logs volume, and to Loki when it
|
||||
// is configured, so the record outlives the container.
|
||||
var logger = require('../utils/logger');
|
||||
var webSearch = require('../utils/webSearch');
|
||||
var pubmedSearch = require('../utils/pubmedSearch');
|
||||
var documentExport = require('../utils/documentExport');
|
||||
|
|
@ -375,20 +382,21 @@ router.post('/my-resources/generate', async function (req, res) {
|
|||
// plain-markdown deck is a materially worse artifact to fall back to
|
||||
// after a single unlucky reply.
|
||||
var firstFailure = deckFailure(ai && ai.content);
|
||||
console.warn('[my-resources] deck reply was not usable (' + firstFailure + '); asking once more');
|
||||
logger.warn('[my-resources] deck reply was not usable (' + firstFailure + '); asking once more',
|
||||
{ topic: topic, attempt: 1, model: ai && ai.model });
|
||||
var retryGaps = [];
|
||||
ai = await callAI([{ role: 'user', content: prompt }], options);
|
||||
deck = deckBuild.parse(ai && ai.content, retryGaps);
|
||||
reportVocabularyGaps(retryGaps, topic);
|
||||
if (deck) console.log('[my-resources] the second deck attempt parsed');
|
||||
if (deck) logger.info('[my-resources] the second deck attempt parsed', { topic: topic });
|
||||
}
|
||||
|
||||
if (deckMode && !deck) {
|
||||
// Twice is enough. Falling back to markdown beats saving nothing, and
|
||||
// beats saving the model's apology.
|
||||
deckFallback = deckFailure(ai && ai.content);
|
||||
console.warn('[my-resources] deck reply was not usable twice (' + deckFallback +
|
||||
'); retrying as markdown');
|
||||
logger.warn('[my-resources] deck reply was not usable twice (' + deckFallback +
|
||||
'); retrying as markdown', { topic: topic, attempt: 2, model: ai && ai.model });
|
||||
var plain = buildPrompt({
|
||||
topic: topic, kind: kind, refinement: refinement, corpusContext: corpus.context,
|
||||
literature: sources.literature, webFindings: sources.webFindings,
|
||||
|
|
@ -706,7 +714,8 @@ function logRefine(event) {
|
|||
}
|
||||
parts.push('instruction="' + String(event.instructions || '').slice(0, 70).replace(/\s+/g, ' ') + '"');
|
||||
var line = parts.join(' ');
|
||||
if (event.outcome !== 'applied' || event.unchanged) console.warn(line); else console.log(line);
|
||||
if (event.outcome !== 'applied' || event.unchanged) logger.warn(line, event);
|
||||
else logger.info(line, event);
|
||||
try {
|
||||
require('../utils/metrics').resourceRefines.inc({
|
||||
path: event.path,
|
||||
|
|
@ -727,7 +736,7 @@ function reportVocabularyGaps(gaps, topic) {
|
|||
try {
|
||||
require('../utils/metrics').deckVocabularyGaps.inc({ wanted: gap.wanted });
|
||||
} catch (e) { /* metrics are never worth an error here */ }
|
||||
console.warn('[deck-vocabulary] wanted "' + gap.wanted + '" (' + gap.detail +
|
||||
logger.warn('[deck-vocabulary] wanted "' + gap.wanted + '" (' + gap.detail +
|
||||
') while generating: ' + String(topic || '').slice(0, 80));
|
||||
});
|
||||
}
|
||||
|
|
@ -753,7 +762,7 @@ async function collectFigures(ids, user, dir) {
|
|||
out.push(file);
|
||||
} catch (e) {
|
||||
// Still generating, failed, or deleted. The deck is fine without it.
|
||||
console.warn('[my-resources] figure unavailable for export:', e.message);
|
||||
logger.warn('[my-resources] figure unavailable for export', { error: e.message });
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ function router(t, overrides = {}) {
|
|||
'../utils/documentExport': { FORMATS: {}, isSupported: () => false, filename: () => 'x', mimeFor: () => '', render: async () => ({}), renderDeck: async () => ({}) },
|
||||
'../utils/generatedImages': { service: () => ({ get: async () => null, asset: async () => null }), workflows: ['my_resources'] },
|
||||
'../utils/learningRetrieval': { retrieve: async () => ({ context: '', sources: [], reason: null }) },
|
||||
'../utils/logger': quiet,
|
||||
'../utils/metrics': { resourceRefines: { inc() {} }, resourceVocabularyGaps: { inc() {} } },
|
||||
'../utils/pubmedSearch': { isAvailable: async () => false, search: async () => ({ results: [] }), formatForPrompt: () => '' },
|
||||
'../utils/webSearch': { isAvailable: async () => false, search: async () => ({ results: [] }), formatForPrompt: () => '' },
|
||||
|
|
|
|||
Loading…
Reference in a new issue