Skip to content

Commit c04324a

Browse files
committed
Track D: structure Pine revision metadata summaries
1 parent 7f18adb commit c04324a

File tree

8 files changed

+177
-3
lines changed

8 files changed

+177
-3
lines changed

docs/CHAT_CONTINUITY_IMPLEMENTATION_PLAN.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,17 @@ This is the next Pine-facing implementation slice after the current Logs / Profi
16741674

16751675
#### Slice D-next-2 — Pine Version History top visible revision metadata summaries
16761676

1677+
**Status:** First slice completed in working tree
1678+
1679+
**Delivered so far**
1680+
- extended `src/main/tradingview/pine-workflows.js` with a `provenance-summary` evidence mode for `pine-version-history`
1681+
- Version History metadata requests such as `summarize the top visible revision metadata` now preserve or auto-append bounded `get_text` provenance-summary readback
1682+
- extended prompt/seam/execution coverage in:
1683+
- `src/main/ai-service/message-builder.js`
1684+
- `scripts/test-tradingview-pine-data-workflows.js`
1685+
- `scripts/test-windows-observation-flow.js`
1686+
- `scripts/test-bug-fixes.js`
1687+
16771688
**Why this is second**
16781689
- the UI access path is already implemented, but the current behavior is still just raw visible text gathering
16791690
- the next value is structural summarization of the top visible revisions, not merely reopening the panel

scripts/test-bug-fixes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ test('pine workflow encodes diagnostics and compile-result evidence modes', () =
249249
assert(pineWorkflowContent.includes('pineEvidenceMode'), 'Pine get_text steps should preserve evidence mode metadata');
250250
assert(pineWorkflowContent.includes('compile-result text for a bounded diagnostics summary'), 'Pine workflows should use compile-result-specific readback wording');
251251
assert(pineWorkflowContent.includes('diagnostics and warnings text'), 'Pine workflows should use diagnostics-specific readback wording');
252+
assert(pineWorkflowContent.includes('provenance-summary'), 'Pine workflows should support version-history provenance-summary evidence mode');
253+
assert(pineWorkflowContent.includes('top visible Pine Version History revision metadata'), 'Pine workflows should use provenance-summary-specific readback wording');
252254
});
253255

254256
test('system prompt includes Pine diagnostics guidance', () => {
@@ -258,6 +260,8 @@ test('system prompt includes Pine diagnostics guidance', () => {
258260
const systemPromptContent = fs.readFileSync(systemPromptPath, 'utf8');
259261

260262
assert(systemPromptContent.includes('TradingView Pine diagnostics rule'), 'System prompt should include Pine diagnostics guidance');
263+
assert(systemPromptContent.includes('visible revision/provenance details'), 'System prompt should steer Pine provenance requests toward verified Version History text');
264+
assert(systemPromptContent.includes('treat visible Pine Version History entries as bounded audit/provenance evidence only'), 'Pine provenance guidance should prevent overclaiming from visible revision history');
261265
assert(systemPromptContent.includes('compile success'), 'System prompt should mention compile success bounds');
262266
assert(systemPromptContent.includes('realtime rollback'), 'System prompt should mention Pine execution-model caveats');
263267
});

scripts/test-pine-diagnostics-bounds.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ async function main() {
6363
assert(evidenceMessage.content.includes('Rule: Surface visible compiler errors and warnings as bounded diagnostics evidence; do not infer hidden causes or chart-state effects unless the visible text states them.'));
6464
assert(evidenceMessage.content.includes('mention Pine execution-model caveats such as realtime rollback, confirmed vs unconfirmed bars, and indicator vs strategy recalculation differences'));
6565
});
66+
67+
await test('pine provenance prompt bounds visible revision metadata inferences', async () => {
68+
const evidenceMessage = await buildPineEvidenceMessage('open pine version history in tradingview and summarize the top visible revision metadata');
69+
70+
assert(evidenceMessage, 'pine evidence block should be injected');
71+
assert(evidenceMessage.content.includes('requestKind: provenance-summary'));
72+
assert(evidenceMessage.content.includes('Treat Pine Version History as bounded provenance evidence only'));
73+
assert(evidenceMessage.content.includes('Do not infer hidden diffs, full script history, authorship, or runtime/chart behavior from the visible revision list alone.'));
74+
});
6675
}
6776

6877
main().catch((error) => {

scripts/test-tradingview-pine-data-workflows.js

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ const path = require('path');
66
const {
77
inferTradingViewPineIntent,
88
buildTradingViewPineWorkflowActions,
9-
maybeRewriteTradingViewPineWorkflow
9+
maybeRewriteTradingViewPineWorkflow,
10+
inferPineVersionHistoryEvidenceMode
1011
} = require(path.join(__dirname, '..', 'src', 'main', 'tradingview', 'pine-workflows.js'));
1112

1213
function test(name, fn) {
@@ -92,6 +93,23 @@ test('pine workflow recognizes pine version history provenance requests', () =>
9293
assert.strictEqual(intent.wantsEvidenceReadback, true);
9394
});
9495

96+
test('pine workflow classifies version history metadata summary requests', () => {
97+
const mode = inferPineVersionHistoryEvidenceMode('open pine version history in tradingview and summarize the top visible revision metadata');
98+
99+
assert.strictEqual(mode, 'provenance-summary');
100+
});
101+
102+
test('pine workflow recognizes visible revision metadata requests', () => {
103+
const intent = inferTradingViewPineIntent('open pine version history in tradingview and summarize the top visible revision metadata', [
104+
{ type: 'key', key: 'alt+h' }
105+
]);
106+
107+
assert(intent, 'intent should be inferred');
108+
assert.strictEqual(intent.surfaceTarget, 'pine-version-history');
109+
assert.strictEqual(intent.wantsEvidenceReadback, true);
110+
assert.strictEqual(intent.pineEvidenceMode, 'provenance-summary');
111+
});
112+
95113
test('open pine logs and read output stays verification-first', () => {
96114
const rewritten = buildTradingViewPineWorkflowActions({
97115
appName: 'TradingView',
@@ -228,6 +246,25 @@ test('open pine version history and read revisions stays verification-first', ()
228246
assert.strictEqual(rewritten[4].text, 'Pine Version History');
229247
});
230248

249+
test('open pine version history and summarize visible revision metadata stays verification-first', () => {
250+
const rewritten = buildTradingViewPineWorkflowActions({
251+
appName: 'TradingView',
252+
surfaceTarget: 'pine-version-history',
253+
verifyKind: 'panel-visible',
254+
openerIndex: 0,
255+
wantsEvidenceReadback: true,
256+
pineEvidenceMode: 'provenance-summary',
257+
requiresObservedChange: false
258+
}, [
259+
{ type: 'key', key: 'alt+h', reason: 'Open Pine Version History' }
260+
]);
261+
262+
assert.strictEqual(rewritten[4].type, 'get_text');
263+
assert.strictEqual(rewritten[4].text, 'Pine Version History');
264+
assert.strictEqual(rewritten[4].pineEvidenceMode, 'provenance-summary');
265+
assert(/top visible Pine Version History revision metadata/i.test(rewritten[4].reason), 'version-history metadata readback should use provenance-summary wording');
266+
});
267+
231268
test('pine evidence-gathering workflow preserves trailing get_text read step', () => {
232269
const rewritten = maybeRewriteTradingViewPineWorkflow([
233270
{ type: 'key', key: 'ctrl+shift+l' },
@@ -288,6 +325,22 @@ test('pine version history workflow preserves trailing get_text read step', () =
288325
assert.strictEqual(rewritten[2].verify.target, 'pine-version-history');
289326
});
290327

328+
test('pine version history metadata workflow preserves trailing get_text read step', () => {
329+
const rewritten = maybeRewriteTradingViewPineWorkflow([
330+
{ type: 'key', key: 'alt+h' },
331+
{ type: 'get_text', text: 'Pine Version History', reason: 'Read top visible Pine Version History revision metadata', pineEvidenceMode: 'provenance-summary' }
332+
], {
333+
userMessage: 'open pine version history in tradingview and summarize the top visible revision metadata'
334+
});
335+
336+
assert(Array.isArray(rewritten), 'workflow should rewrite');
337+
const readSteps = rewritten.filter((action) => action?.type === 'get_text');
338+
assert.strictEqual(readSteps.length, 1, 'explicit version-history metadata readback step should be preserved without duplication');
339+
assert.strictEqual(readSteps[0].text, 'Pine Version History');
340+
assert.strictEqual(readSteps[0].pineEvidenceMode, 'provenance-summary');
341+
assert.strictEqual(rewritten[2].verify.target, 'pine-version-history');
342+
});
343+
291344
test('pine workflow does not hijack speculative chart-analysis prompts', () => {
292345
const rewritten = maybeRewriteTradingViewPineWorkflow([
293346
{ type: 'screenshot' }

scripts/test-windows-observation-flow.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,20 @@ async function run() {
358358
assert.strictEqual(rewritten[4].text, 'Pine Version History');
359359
});
360360

361+
await testAsync('low-signal TradingView Pine Version History metadata request rewrites to provenance-summary get_text', async () => {
362+
const rewritten = aiService.rewriteActionsForReliability([
363+
{ type: 'key', key: 'alt+h' }
364+
], {
365+
userMessage: 'open pine version history in tradingview and summarize the top visible revision metadata'
366+
});
367+
368+
assert(Array.isArray(rewritten), 'pine version history metadata rewrite should return an action array');
369+
assert.strictEqual(rewritten[2].verify.target, 'pine-version-history');
370+
assert.strictEqual(rewritten[4].type, 'get_text');
371+
assert.strictEqual(rewritten[4].text, 'Pine Version History');
372+
assert.strictEqual(rewritten[4].pineEvidenceMode, 'provenance-summary');
373+
});
374+
361375
await testAsync('verified pine logs workflow allows bounded evidence gathering without screenshot loop', async () => {
362376
const executed = [];
363377
const foregroundSequence = [
@@ -514,6 +528,60 @@ async function run() {
514528
});
515529
});
516530

531+
await testAsync('verified pine version history metadata workflow preserves top visible revision text without screenshot loop', async () => {
532+
const executed = [];
533+
const evidenceModes = [];
534+
const foregroundSequence = [
535+
{ success: true, hwnd: 777, title: 'TradingView', processName: 'tradingview', windowKind: 'main' },
536+
{ success: true, hwnd: 891, title: 'Pine Version History - TradingView', processName: 'tradingview', windowKind: 'owned' },
537+
{ success: true, hwnd: 891, title: 'Pine Version History - TradingView', processName: 'tradingview', windowKind: 'owned' },
538+
{ success: true, hwnd: 891, title: 'Pine Version History - TradingView', processName: 'tradingview', windowKind: 'owned' }
539+
];
540+
541+
await withPatchedSystemAutomation({
542+
resolveWindowHandle: async (action) => action?.processName === 'tradingview' ? 777 : 0,
543+
getForegroundWindowHandle: async () => 777,
544+
getForegroundWindowInfo: async () => {
545+
return foregroundSequence.shift() || { success: true, hwnd: 891, title: 'Pine Version History - TradingView', processName: 'tradingview', windowKind: 'owned' };
546+
},
547+
focusWindow: async () => ({ success: true }),
548+
getRunningProcessesByNames: async () => ([{ pid: 4242, processName: 'tradingview', mainWindowTitle: 'TradingView', startTime: '2026-03-23T00:00:00Z' }])
549+
}, async () => {
550+
const execResult = await aiService.executeActions({
551+
thought: 'Open Pine Version History and summarize the top visible revision metadata',
552+
verification: 'TradingView should show Pine Version History before text is read',
553+
actions: [
554+
{ type: 'focus_window', title: 'TradingView', processName: 'tradingview' },
555+
{ type: 'key', key: 'alt+h', reason: 'Open Pine Version History', verify: { kind: 'panel-visible', appName: 'TradingView', target: 'pine-version-history', keywords: ['pine version history', 'version history', 'pine'] } },
556+
{ type: 'get_text', text: 'Pine Version History', reason: 'Read top visible Pine Version History revision metadata', pineEvidenceMode: 'provenance-summary' }
557+
]
558+
}, null, null, {
559+
userMessage: 'open pine version history in tradingview and summarize the top visible revision metadata',
560+
actionExecutor: async (action) => {
561+
executed.push(action.type);
562+
if (action.type === 'get_text') {
563+
evidenceModes.push(action.pineEvidenceMode || null);
564+
return {
565+
success: true,
566+
action: action.type,
567+
text: 'Revision 18 saved 2m ago; Revision 17 saved 18m ago; showing 2 visible revisions',
568+
method: 'TextPattern',
569+
message: 'Got text via TextPattern: "Revision 18 saved 2m ago; Revision 17 saved 18m ago; showing 2 visible revisions"'
570+
};
571+
}
572+
return { success: true, action: action.type, message: 'executed' };
573+
}
574+
});
575+
576+
assert.strictEqual(execResult.success, true, 'Execution should proceed after Pine Version History metadata view is observed');
577+
assert.deepStrictEqual(executed, ['focus_window', 'key', 'get_text'], 'Version History metadata summary should continue to read text after panel verification');
578+
assert.deepStrictEqual(evidenceModes, ['provenance-summary'], 'Version History metadata workflow should preserve provenance-summary evidence mode');
579+
assert.strictEqual(execResult.observationCheckpoints[0].verified, true, 'Pine Version History panel observation should pass');
580+
assert.strictEqual(execResult.results[2].text, 'Revision 18 saved 2m ago; Revision 17 saved 18m ago; showing 2 visible revisions', 'Version History metadata text should be preserved on the get_text result');
581+
assert(!execResult.screenshotCaptured, 'Pine Version History metadata gathering should not require a screenshot loop');
582+
});
583+
});
584+
517585
await testAsync('verified pine editor diagnostics workflow gathers compile text without screenshot loop', async () => {
518586
const executed = [];
519587
const evidenceModes = [];

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ function inferPineEvidenceRequestKind(userMessage = '') {
4646
return 'generic-status';
4747
}
4848

49+
if (/\b(version history|revision|revisions|provenance|history|versions)\b/.test(text)
50+
&& /\b(latest|top|visible|recent|metadata|summary|summarize|details)\b/.test(text)) {
51+
return 'provenance-summary';
52+
}
53+
4954
return null;
5055
}
5156

@@ -78,6 +83,11 @@ function buildPineEvidenceConstraint({ foreground, userMessage }) {
7883
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.');
7984
}
8085

86+
if (requestKind === 'provenance-summary') {
87+
lines.push('- Rule: Treat Pine Version History as bounded provenance evidence only; summarize only the top visible revision labels, relative times, and other metadata that are directly visible.');
88+
lines.push('- Rule: Do not infer hidden diffs, full script history, authorship, or runtime/chart behavior from the visible revision list alone.');
89+
}
90+
8191
lines.push('- Rule: If the user asks for Pine runtime or strategy diagnosis, mention Pine execution-model caveats such as realtime rollback, confirmed vs unconfirmed bars, and indicator vs strategy recalculation differences before inferring behavior from compile status alone.');
8292
return lines.join('\n');
8393
}

src/main/ai-service/system-prompt.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ When the user asks you to DO something, respond with a JSON action block:
229229
- **Continuity rule**: if the active page title or recent action output indicates the requested browser objective is already achieved, acknowledge completion and avoid proposing additional screenshot steps.
230230
- **TradingView Pine evidence rule**: if the user wants concrete Pine output, errors, profiler-style evidence, visible Pine Editor status/output, or visible revision/provenance details, prefer \`open/show Pine Editor, Logs, Profiler, or Version History\` + verified panel opening + \`get_text\` before relying on screenshot analysis.
231231
- **TradingView Pine diagnostics rule**: treat visible Pine Editor compile results, compiler errors, warnings, and diagnostics as bounded text evidence. Do not turn \`no errors\` into claims about runtime correctness, market validity, or trading edge.
232+
- **TradingView Pine provenance rule**: treat visible Pine Version History entries as bounded audit/provenance evidence only. Summarize top visible revision labels, relative times, and other directly visible metadata, but do not infer hidden diffs, full script history, authorship, or runtime/chart behavior from the visible list alone.
232233
- **TradingView Pine line-budget rule**: Pine scripts are limited to 500 lines. Do not propose pasting or generating Pine scripts longer than 500 lines; prefer bounded edits, read visible line/status hints first when needed, and mention the limit explicitly when it affects read/write guidance.
233234
- **If you need to interact with web content inside an app** (like VS Code panels, browser tabs): Use keyboard shortcuts or coordinate-based clicks since web UI may not appear in UIA tree
234235

src/main/tradingview/pine-workflows.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ function inferPineEditorEvidenceMode(raw = '') {
6262
return 'generic-status';
6363
}
6464

65+
function inferPineVersionHistoryEvidenceMode(raw = '') {
66+
const normalized = normalizeTextForMatch(raw);
67+
if (!normalized) return 'generic-provenance';
68+
69+
const mentionsMetadataSummary = /\b(latest|top|visible|recent|newest|metadata|summary|summarize|revision metadata|provenance details|revision details)\b/.test(normalized);
70+
const mentionsRevisionList = /\b(revision|revisions|version history|history|versions|changes|provenance)\b/.test(normalized);
71+
if (mentionsRevisionList && mentionsMetadataSummary) return 'provenance-summary';
72+
73+
return 'generic-provenance';
74+
}
75+
6576
function buildPineReadbackStep(surfaceTarget, evidenceMode = null) {
6677
if (surfaceTarget === 'pine-editor') {
6778
const mode = evidenceMode || 'generic-status';
@@ -97,10 +108,14 @@ function buildPineReadbackStep(surfaceTarget, evidenceMode = null) {
97108
}
98109

99110
if (surfaceTarget === 'pine-version-history') {
111+
const mode = evidenceMode || 'generic-provenance';
100112
return {
101113
type: 'get_text',
102114
text: 'Pine Version History',
103-
reason: 'Read visible Pine Version History entries for bounded provenance gathering'
115+
reason: mode === 'provenance-summary'
116+
? 'Read top visible Pine Version History revision metadata for a bounded provenance summary'
117+
: 'Read visible Pine Version History entries for bounded provenance gathering',
118+
pineEvidenceMode: mode
104119
};
105120
}
106121

@@ -156,6 +171,8 @@ function inferTradingViewPineIntent(userMessage = '', actions = []) {
156171
const wantsEvidenceReadback = inferPineEvidenceReadIntent(raw, surface.target);
157172
const pineEvidenceMode = surface.target === 'pine-editor' && wantsEvidenceReadback
158173
? inferPineEditorEvidenceMode(raw)
174+
: surface.target === 'pine-version-history' && wantsEvidenceReadback
175+
? inferPineVersionHistoryEvidenceMode(raw)
159176
: null;
160177

161178
const existingWorkflowSignal = Array.isArray(actions) && actions.some((action) => /pine/.test(String(action?.verify?.target || '')));
@@ -262,5 +279,6 @@ function maybeRewriteTradingViewPineWorkflow(actions, context = {}) {
262279
module.exports = {
263280
inferTradingViewPineIntent,
264281
buildTradingViewPineWorkflowActions,
265-
maybeRewriteTradingViewPineWorkflow
282+
maybeRewriteTradingViewPineWorkflow,
283+
inferPineVersionHistoryEvidenceMode
266284
};

0 commit comments

Comments
 (0)