mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-17 15:20:11 +02:00
fix(learnings): cross-project trust gate is an allowlist, not a denylist (#1745)
gstack-learnings-search --cross-project is documented as an allowlist — foreign learnings load only when user-stated/trusted, to stop one project's AI-generated learnings from injecting into another project's reviews. It was implemented as a denylist: `if (isCrossProject && e.trusted === false) continue`. Any row where `trusted` is missing/undefined (legacy rows from before the field existed, hand-edited rows, rows from other tools) passed `undefined === false` → false → admitted. Those rows leaked across projects. Flip to `e.trusted !== true`. Test: a foreign row with no `trusted` field is now excluded (true still included, false still excluded). Reported by @jbetala7. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,9 @@ beforeAll(() => {
|
||||
const otherEntries = [
|
||||
{ ts: '2026-05-04T00:00:00Z', skill: 'test', type: 'pattern', key: 'foreign-observed', insight: 'A foreign observed insight', confidence: 8, source: 'observed', trusted: false, files: [] },
|
||||
{ ts: '2026-05-05T00:00:00Z', skill: 'test', type: 'pattern', key: 'foreign-user', insight: 'A foreign user-stated insight', confidence: 8, source: 'user-stated', trusted: true, files: [] },
|
||||
// #1745: legacy row with NO `trusted` field at all (written before the field
|
||||
// existed). The old `=== false` denylist admitted these; the allowlist must exclude.
|
||||
{ ts: '2026-05-06T00:00:00Z', skill: 'test', type: 'pattern', key: 'foreign-legacy', insight: 'A foreign legacy insight with no trusted field', confidence: 8, source: 'observed', files: [] },
|
||||
];
|
||||
fs.writeFileSync(path.join(projDir, 'learnings.jsonl'), entries.map(e => JSON.stringify(e)).join('\n') + '\n');
|
||||
fs.writeFileSync(path.join(otherProjDir, 'learnings.jsonl'), otherEntries.map(e => JSON.stringify(e)).join('\n') + '\n');
|
||||
@@ -79,4 +82,11 @@ describe('gstack-learnings-search cross-project trust gating', () => {
|
||||
expect(out).toContain('[cross-project]');
|
||||
expect(out).not.toContain('foreign-observed');
|
||||
});
|
||||
|
||||
// #1745: the gate is an allowlist, not a denylist. A cross-project row with no
|
||||
// `trusted` field (legacy / hand-edited / other-tool) must NOT be imported.
|
||||
test('cross-project mode excludes foreign rows missing the trusted field (#1745)', () => {
|
||||
const out = run(['--cross-project', '--query', 'foreign']);
|
||||
expect(out).not.toContain('foreign-legacy');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user