desktop: a Fix button on scan and validate findings storebound can fix itself. Findings carry action { method, args } (cli/lib/fix-actions.ts); privacy-labels runs scan.write (scan --write-only, the dialog shows the config diff), Play listing gaps play.listing, a missing App Store localization or copyright apple.listing (editable version only), the App Review contact apple.review_details; each a dry run, the native dialog, then the confirmed run. --write-only is forbidden for MCP tools; tests pin the mapping, the round trip on a fixture and that no fix reaches a submit, release or publish

This commit is contained in:
CRTkafa 2026-10-15 06:14:49 +08:00
parent bd83d036ba
commit 992f5bcc0e
18 changed files with 257 additions and 37 deletions

View file

@ -5,6 +5,7 @@ import { existsSync, readFileSync } from 'node:fs';
import { join, relative, resolve } from 'node:path';
import { CONFIG_NAMES, loadConfig, type ShipConfig } from '../config';
import { reviewDemoAccount } from '../credentials';
import { scanFixAction } from '../fix-actions';
import { proposeDeclarations, type Proposal } from './declare';
import { detectProject, ECO_LABEL, type ProjectFacts, type Stack, where } from './project';
import type { OriginalityReport } from '../originality';
@ -62,6 +63,10 @@ export async function runScan(dir: string, o: { config?: string } = {}): Promise
return { type: d.type, missing: [...new Set(missing)].join(', '), evidence: d.evidence };
}).filter(d => d.missing) : [];
const findings = scanRules({ facts, config, configFile, listings, demoAccount: !!reviewDemoAccount(dir), labelGaps: declarations.labelGaps, dataMerges });
for (const f of findings) {
const action = f.accepted ? undefined : scanFixAction(f.rule, { configPath, declarationsChanged: declarations.changed });
if (action) f.action = action;
}
const counts = { blocker: 0, high: 0, medium: 0, low: 0, accepted: 0 };
for (const f of findings) { if (f.accepted) counts.accepted++; else counts[f.severity]++; }
const notes: string[] = [];