Skip to content

Commit 745f12d

Browse files
committed
Structure Pine editor diagnostics summaries
1 parent 996621d commit 745f12d

9 files changed

+434
-5
lines changed

scripts/test-bug-fixes.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,15 @@ test('ai-service gates TradingView follow-up typing on post-key observation chec
415415
assert(tradingViewPineContent.includes("text: 'Pine Editor'"), 'TradingView Pine workflows should support bounded Pine Editor status/output readback');
416416
assert(tradingViewPineContent.includes('wantsEvidenceReadback'), 'TradingView Pine workflows should detect Pine evidence-gathering requests');
417417
assert(systemAutomationContent.includes('buildPineEditorSafeAuthoringSummary'), 'system-automation should structure Pine Editor safe-authoring inspection summaries');
418+
assert(systemAutomationContent.includes('buildPineEditorDiagnosticsStructuredSummary'), 'system-automation should structure Pine Editor diagnostics summaries');
418419
assert(systemAutomationContent.includes("pineEvidenceMode === 'safe-authoring-inspect'"), 'system-automation should attach structured Pine summaries for safe-authoring-inspect readbacks');
420+
assert(systemAutomationContent.includes("action?.pineEvidenceMode === 'compile-result'"), 'system-automation should structure compile-result Pine Editor reads');
421+
assert(systemAutomationContent.includes("action?.pineEvidenceMode === 'diagnostics'"), 'system-automation should structure diagnostics Pine Editor reads');
422+
assert(systemAutomationContent.includes("action?.pineEvidenceMode === 'line-budget'"), 'system-automation should structure line-budget Pine Editor reads');
423+
assert(systemAutomationContent.includes("action?.pineEvidenceMode === 'generic-status'"), 'system-automation should structure generic-status Pine Editor reads');
419424
assert(sessionIntentStateContent.includes('pineAuthoringState'), 'session intent continuity context should expose Pine authoring state');
425+
assert(sessionIntentStateContent.includes('pineCompileStatus'), 'session intent continuity context should expose Pine compile status');
426+
assert(sessionIntentStateContent.includes('Visible Pine compiler errors are present'), 'session intent continuity should recommend fixing visible compiler errors first');
420427
assert(sessionIntentStateContent.includes('avoid overwriting it implicitly'), 'session intent continuity should recommend non-destructive Pine next steps when script content is already visible');
421428
assert(chatContinuityStateContent.includes('normalizePineStructuredSummary'), 'chat continuity mapper should preserve Pine structured summary fields');
422429
assert(tradingViewPaperContent.includes("target: 'paper-trading-panel'"), 'TradingView Paper workflows should encode paper-trading-panel verification metadata');

scripts/test-chat-continuity-state.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,52 @@ test('continuity mapper preserves Pine safe-authoring structured summary facts',
204204
'script-body-visible'
205205
]);
206206
});
207+
208+
test('continuity mapper preserves Pine diagnostics structured summary facts', () => {
209+
const turnRecord = buildChatContinuityTurnRecord({
210+
actionData: {
211+
thought: 'Inspect Pine diagnostics',
212+
actions: [
213+
{ type: 'focus_window', title: 'TradingView', processName: 'tradingview' },
214+
{ type: 'key', key: 'ctrl+e', reason: 'Open Pine Editor', verify: { kind: 'panel-visible', target: 'pine-editor' } },
215+
{ type: 'get_text', text: 'Pine Editor', reason: 'Read visible diagnostics' }
216+
]
217+
},
218+
execResult: {
219+
success: true,
220+
results: [
221+
{ success: true, action: 'focus_window', message: 'focused' },
222+
{ success: true, action: 'key', message: 'editor opened' },
223+
{
224+
success: true,
225+
action: 'get_text',
226+
message: 'diagnostics inspected',
227+
pineStructuredSummary: {
228+
evidenceMode: 'diagnostics',
229+
compileStatus: 'errors-visible',
230+
errorCountEstimate: 1,
231+
warningCountEstimate: 1,
232+
lineBudgetSignal: 'unknown-line-budget',
233+
statusSignals: ['compile-errors-visible', 'warnings-visible'],
234+
topVisibleDiagnostics: ['Compiler error at line 42: mismatched input.', 'Warning: script has unused variable.'],
235+
compactSummary: 'status=errors-visible | errors=1 | warnings=1'
236+
}
237+
}
238+
]
239+
},
240+
details: {
241+
userMessage: 'open pine editor in tradingview and check diagnostics',
242+
executionIntent: 'Inspect Pine diagnostics.',
243+
nextRecommendedStep: 'Fix the visible compiler errors before continuing.'
244+
}
245+
});
246+
247+
assert.strictEqual(turnRecord.results[2].pineStructuredSummary.compileStatus, 'errors-visible');
248+
assert.strictEqual(turnRecord.results[2].pineStructuredSummary.errorCountEstimate, 1);
249+
assert.strictEqual(turnRecord.results[2].pineStructuredSummary.warningCountEstimate, 1);
250+
assert.deepStrictEqual(turnRecord.results[2].pineStructuredSummary.statusSignals, ['compile-errors-visible', 'warnings-visible']);
251+
assert.deepStrictEqual(turnRecord.results[2].pineStructuredSummary.topVisibleDiagnostics, [
252+
'Compiler error at line 42: mismatched input.',
253+
'Warning: script has unused variable.'
254+
]);
255+
});

scripts/test-pine-diagnostics-bounds.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,28 @@ async function main() {
7373
assert(evidenceMessage.content.includes('latest visible revision label, latest visible relative time, visible revision count, and visible recency signal'));
7474
assert(evidenceMessage.content.includes('Do not infer hidden diffs, full script history, authorship, or runtime/chart behavior from the visible revision list alone.'));
7575
});
76+
77+
await test('pine line-budget prompt bounds visible count-hint inferences', async () => {
78+
const evidenceMessage = await buildPineEvidenceMessage('open pine editor in tradingview and check the line budget');
79+
80+
assert(evidenceMessage, 'pine evidence block should be injected');
81+
assert(evidenceMessage.content.includes('requestKind: line-budget'));
82+
assert(evidenceMessage.content.includes('Treat visible line-count hints as bounded editor evidence'));
83+
assert(evidenceMessage.content.includes('do not infer hidden script size beyond what the editor text shows'));
84+
});
85+
86+
await test('pine generic-status prompt keeps status-only claims bounded', async () => {
87+
const evidenceMessage = await buildPineEvidenceMessage('open pine editor in tradingview and show the visible status text');
88+
89+
assert(evidenceMessage, 'pine evidence block should be injected');
90+
assert(evidenceMessage.content.includes('requestKind: generic-status'));
91+
assert(evidenceMessage.content.includes('bounded editor evidence only'));
92+
assert(evidenceMessage.content.includes('do not turn generic status text into runtime, chart, or market claims'));
93+
});
7694
}
7795

7896
main().catch((error) => {
7997
console.error('FAIL pine diagnostics bounds');
8098
console.error(error.stack || error.message);
8199
process.exit(1);
82-
});
100+
});
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env node
2+
3+
const assert = require('assert');
4+
const path = require('path');
5+
6+
const systemAutomation = require(path.join(__dirname, '..', 'src', 'main', 'system-automation.js'));
7+
8+
function test(name, fn) {
9+
try {
10+
fn();
11+
console.log(`PASS ${name}`);
12+
} catch (error) {
13+
console.error(`FAIL ${name}`);
14+
console.error(error.stack || error.message);
15+
process.exitCode = 1;
16+
}
17+
}
18+
19+
async function testAsync(name, fn) {
20+
try {
21+
await fn();
22+
console.log(`PASS ${name}`);
23+
} catch (error) {
24+
console.error(`FAIL ${name}`);
25+
console.error(error.stack || error.message);
26+
process.exitCode = 1;
27+
}
28+
}
29+
30+
test('Pine compile-result summary stays bounded to visible compiler status', () => {
31+
const summary = systemAutomation.buildPineEditorDiagnosticsStructuredSummary(
32+
'Compiler: no errors. Status: strategy loaded.',
33+
'compile-result'
34+
);
35+
36+
assert(summary, 'summary should be returned');
37+
assert.strictEqual(summary.evidenceMode, 'compile-result');
38+
assert.strictEqual(summary.compileStatus, 'success');
39+
assert.strictEqual(summary.errorCountEstimate, 0);
40+
assert.strictEqual(summary.warningCountEstimate, 0);
41+
assert(summary.statusSignals.includes('compile-success-visible'));
42+
assert(summary.topVisibleDiagnostics.includes('Compiler: no errors. Status: strategy loaded.'));
43+
});
44+
45+
test('Pine diagnostics summary surfaces visible compiler errors and warnings', () => {
46+
const summary = systemAutomation.buildPineEditorDiagnosticsStructuredSummary(
47+
'Compiler error at line 42: mismatched input. Warning: script has unused variable.',
48+
'diagnostics'
49+
);
50+
51+
assert(summary, 'summary should be returned');
52+
assert.strictEqual(summary.evidenceMode, 'diagnostics');
53+
assert.strictEqual(summary.compileStatus, 'errors-visible');
54+
assert.strictEqual(summary.errorCountEstimate, 1);
55+
assert.strictEqual(summary.warningCountEstimate, 1);
56+
assert(summary.statusSignals.includes('compile-errors-visible'));
57+
assert(summary.statusSignals.includes('warnings-visible'));
58+
assert.deepStrictEqual(summary.topVisibleDiagnostics, [
59+
'Compiler error at line 42: mismatched input. Warning: script has unused variable.'
60+
]);
61+
});
62+
63+
test('Pine line-budget summary exposes visible count hints and limit pressure', () => {
64+
const summary = systemAutomation.buildPineEditorDiagnosticsStructuredSummary(
65+
'Line count: 487 / 500 lines. Warning: script is close to the Pine limit.',
66+
'line-budget'
67+
);
68+
69+
assert(summary, 'summary should be returned');
70+
assert.strictEqual(summary.evidenceMode, 'line-budget');
71+
assert.strictEqual(summary.visibleLineCountEstimate, 487);
72+
assert.strictEqual(summary.lineBudgetSignal, 'near-limit-visible');
73+
assert.strictEqual(summary.warningCountEstimate, 1);
74+
assert(summary.statusSignals.includes('line-budget-hint-visible'));
75+
assert(summary.statusSignals.includes('near-limit-visible'));
76+
});
77+
78+
testAsync('GET_TEXT attaches Pine structured summary for compile-result mode', async () => {
79+
const uiAutomation = require(path.join(__dirname, '..', 'src', 'main', 'ui-automation'));
80+
const originalGetElementText = uiAutomation.getElementText;
81+
82+
uiAutomation.getElementText = async () => ({
83+
success: true,
84+
text: 'Compiler: no errors. Status: strategy loaded.',
85+
method: 'TextPattern'
86+
});
87+
88+
try {
89+
const result = await systemAutomation.executeAction({
90+
type: 'get_text',
91+
text: 'Pine Editor',
92+
pineEvidenceMode: 'compile-result'
93+
});
94+
95+
assert.strictEqual(result.success, true);
96+
assert.strictEqual(result.pineStructuredSummary.evidenceMode, 'compile-result');
97+
assert.strictEqual(result.pineStructuredSummary.compileStatus, 'success');
98+
assert(result.message.includes('status=success'));
99+
} finally {
100+
uiAutomation.getElementText = originalGetElementText;
101+
}
102+
});

scripts/test-session-intent-state.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,98 @@ test('session intent continuity recommends bounded new-script drafting for empty
411411

412412
fs.rmSync(tempDir, { recursive: true, force: true });
413413
});
414+
415+
test('session intent continuity surfaces Pine diagnostics state and recovery guidance', () => {
416+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'liku-session-intent-'));
417+
const stateFile = path.join(tempDir, 'session-intent-state.json');
418+
const store = createSessionIntentStateStore({ stateFile });
419+
420+
const recorded = store.recordExecutedTurn({
421+
userMessage: 'open pine editor in tradingview and check diagnostics',
422+
executionIntent: 'Inspect visible Pine diagnostics.',
423+
committedSubgoal: 'Inspect the visible Pine diagnostics state',
424+
actionPlan: [
425+
{ type: 'focus_window', title: 'TradingView', processName: 'tradingview' },
426+
{ type: 'key', key: 'ctrl+e', verifyKind: 'panel-visible', verifyTarget: 'pine-editor' },
427+
{ type: 'get_text', text: 'Pine Editor' }
428+
],
429+
results: [
430+
{ type: 'focus_window', success: true, message: 'focused' },
431+
{ type: 'key', success: true, message: 'editor opened' },
432+
{
433+
type: 'get_text',
434+
success: true,
435+
message: 'diagnostics inspected',
436+
pineStructuredSummary: {
437+
evidenceMode: 'diagnostics',
438+
compileStatus: 'errors-visible',
439+
errorCountEstimate: 1,
440+
warningCountEstimate: 1,
441+
lineBudgetSignal: 'unknown-line-budget',
442+
statusSignals: ['compile-errors-visible', 'warnings-visible'],
443+
topVisibleDiagnostics: ['Compiler error at line 42: mismatched input.', 'Warning: script has unused variable.'],
444+
compactSummary: 'status=errors-visible | errors=1 | warnings=1'
445+
}
446+
}
447+
],
448+
success: true,
449+
verification: { status: 'verified' }
450+
}, {
451+
cwd: path.join(__dirname, '..')
452+
});
453+
454+
assert(/fix the visible errors/i.test(recorded.chatContinuity.lastTurn.nextRecommendedStep));
455+
456+
const continuityContext = formatChatContinuityContext(recorded);
457+
assert(continuityContext.includes('pineCompileStatus: errors-visible'));
458+
assert(continuityContext.includes('pineErrorCountEstimate: 1'));
459+
assert(continuityContext.includes('pineWarningCountEstimate: 1'));
460+
assert(continuityContext.includes('pineTopVisibleDiagnostics: Compiler error at line 42: mismatched input. | Warning: script has unused variable.'));
461+
462+
fs.rmSync(tempDir, { recursive: true, force: true });
463+
});
464+
465+
test('session intent continuity recommends targeted edits under Pine line-budget pressure', () => {
466+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'liku-session-intent-'));
467+
const stateFile = path.join(tempDir, 'session-intent-state.json');
468+
const store = createSessionIntentStateStore({ stateFile });
469+
470+
const recorded = store.recordExecutedTurn({
471+
userMessage: 'open pine editor in tradingview and check the line budget',
472+
executionIntent: 'Inspect visible Pine line-budget hints.',
473+
committedSubgoal: 'Inspect visible Pine line-budget hints',
474+
actionPlan: [
475+
{ type: 'focus_window', title: 'TradingView', processName: 'tradingview' },
476+
{ type: 'key', key: 'ctrl+e', verifyKind: 'panel-visible', verifyTarget: 'pine-editor' },
477+
{ type: 'get_text', text: 'Pine Editor' }
478+
],
479+
results: [
480+
{ type: 'focus_window', success: true, message: 'focused' },
481+
{ type: 'key', success: true, message: 'editor opened' },
482+
{
483+
type: 'get_text',
484+
success: true,
485+
message: 'line budget inspected',
486+
pineStructuredSummary: {
487+
evidenceMode: 'line-budget',
488+
compileStatus: 'status-only',
489+
errorCountEstimate: 0,
490+
warningCountEstimate: 1,
491+
visibleLineCountEstimate: 487,
492+
lineBudgetSignal: 'near-limit-visible',
493+
statusSignals: ['line-budget-hint-visible', 'near-limit-visible'],
494+
topVisibleDiagnostics: ['Line count: 487 / 500 lines.', 'Warning: script is close to the Pine limit.'],
495+
compactSummary: 'status=status-only | errors=0 | warnings=1 | lines=487 | budget=near-limit-visible'
496+
}
497+
}
498+
],
499+
success: true,
500+
verification: { status: 'verified' }
501+
}, {
502+
cwd: path.join(__dirname, '..')
503+
});
504+
505+
assert(/targeted edits/i.test(recorded.chatContinuity.lastTurn.nextRecommendedStep));
506+
507+
fs.rmSync(tempDir, { recursive: true, force: true });
508+
});

src/main/ai-service/message-builder.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ function buildPineEvidenceConstraint({ foreground, userMessage }) {
9797

9898
if (requestKind === 'line-budget') {
9999
lines.push('- Rule: Pine scripts are capped at 500 lines in TradingView. Treat visible line-count hints as bounded editor evidence, and prefer targeted edits over full rewrites when the budget is tight.');
100+
lines.push('- Rule: Summarize only the visible line-count or budget hints; do not infer hidden script size beyond what the editor text shows.');
101+
}
102+
103+
if (requestKind === 'generic-status') {
104+
lines.push('- Rule: Treat visible Pine Editor status/output text as bounded editor evidence only; do not turn generic status text into runtime, chart, or market claims.');
100105
}
101106

102107
if (requestKind === 'provenance-summary') {

src/main/chat-continuity-state.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@ function normalizePineStructuredSummary(summary) {
5353
editorVisibleState: normalizeText(summary.editorVisibleState, 60),
5454
visibleScriptKind: normalizeText(summary.visibleScriptKind, 40),
5555
visibleLineCountEstimate: safeNumber(summary.visibleLineCountEstimate),
56+
compileStatus: normalizeText(summary.compileStatus, 40),
57+
errorCountEstimate: safeNumber(summary.errorCountEstimate),
58+
warningCountEstimate: safeNumber(summary.warningCountEstimate),
59+
lineBudgetSignal: normalizeText(summary.lineBudgetSignal, 60),
5660
visibleSignals: normalizeEvidenceList(summary.visibleSignals, 40),
61+
statusSignals: normalizeEvidenceList(summary.statusSignals, 40),
62+
topVisibleDiagnostics: normalizeEvidenceList(summary.topVisibleDiagnostics, 140),
5763
latestVisibleRevisionLabel: normalizeText(summary.latestVisibleRevisionLabel, 80),
5864
latestVisibleRevisionNumber: safeNumber(summary.latestVisibleRevisionNumber),
5965
latestVisibleRelativeTime: normalizeText(summary.latestVisibleRelativeTime, 80),
@@ -67,7 +73,13 @@ function normalizePineStructuredSummary(summary) {
6773
&& !normalized.editorVisibleState
6874
&& !normalized.visibleScriptKind
6975
&& normalized.visibleLineCountEstimate === null
76+
&& !normalized.compileStatus
77+
&& normalized.errorCountEstimate === null
78+
&& normalized.warningCountEstimate === null
79+
&& !normalized.lineBudgetSignal
7080
&& normalized.visibleSignals.length === 0
81+
&& normalized.statusSignals.length === 0
82+
&& normalized.topVisibleDiagnostics.length === 0
7183
&& !normalized.latestVisibleRevisionLabel
7284
&& normalized.latestVisibleRevisionNumber === null
7385
&& !normalized.latestVisibleRelativeTime

0 commit comments

Comments
 (0)