fix: stop verify, reports and briefs from claiming more than pipe checked #1
4 changed files with 77 additions and 5 deletions
fix(guide): persist the yams report with its caution and provenance
`guide --yams` persists the markdown report, not the brief, and the markdown
had neither the brief's caution line ("static reachability claims ... confirm
each against the cited file") nor the [severity/confidence] of each finding -
so a report read back from the corpus presented every finding as equally
certain, with no framing. Its metadata still carried a stale `owner=pi` and
nothing to date or reproduce it.
The markdown now opens with the caution line, headings read
`### N. [severity/confidence] rule — location`, and the metadata records
`generated=<ISO-8601 UTC>` and, when the project is a git checkout,
`commit=<HEAD>`. `owner=pi` is gone.
commit
e2d84f5e75
|
|
@ -9,10 +9,12 @@ export 'src/guide.dart'
|
|||
buildGuidance,
|
||||
emitToYams,
|
||||
findYams,
|
||||
gitHead,
|
||||
rankFindings,
|
||||
ruleEpithet,
|
||||
ruleFix,
|
||||
ruleGlossary;
|
||||
ruleGlossary,
|
||||
yamsMetadata;
|
||||
export 'src/index.dart'
|
||||
show
|
||||
DiagnosticRecord,
|
||||
|
|
|
|||
|
|
@ -748,9 +748,11 @@ class GuideCommand extends Command<int> {
|
|||
final error = await emitToYams(
|
||||
name: name,
|
||||
content: guidance.markdown,
|
||||
metadata:
|
||||
'task=pipe-guide,phase=report,owner=pi,source=analysis,'
|
||||
'project=${p.basename(project.root)}',
|
||||
metadata: yamsMetadata(
|
||||
project: p.basename(project.root),
|
||||
generated: DateTime.now(),
|
||||
commit: await gitHead(project.root),
|
||||
),
|
||||
collection: 'pipe',
|
||||
);
|
||||
if (error != null) {
|
||||
|
|
|
|||
|
|
@ -515,9 +515,13 @@ Guidance buildGuidance({
|
|||
}
|
||||
|
||||
// --- markdown ----------------------------------------------------------
|
||||
// The markdown is what `--yams` persists, so it carries the same caution as
|
||||
// the brief: read later from the corpus, it has no other framing.
|
||||
final markdown = StringBuffer()
|
||||
..writeln('# pipe report — $root')
|
||||
..writeln()
|
||||
..writeln(cautionLine)
|
||||
..writeln()
|
||||
..write(coverageLine == null ? '' : '$coverageLine\n\n')
|
||||
..writeln(
|
||||
'${flow.unions.length} blocs/cubits, ${summary['stateVariants']} state '
|
||||
|
|
@ -529,7 +533,10 @@ Guidance buildGuidance({
|
|||
for (var i = 0; i < ranked.length; i++) {
|
||||
markdown
|
||||
..writeln()
|
||||
..writeln('### ${i + 1}. ${ranked[i].rule} — ${ranked[i].location}')
|
||||
..writeln(
|
||||
'### ${i + 1}. [${ranked[i].severity.name}/${ranked[i].confidence}] '
|
||||
'${ranked[i].rule} — ${ranked[i].location}',
|
||||
)
|
||||
..writeln()
|
||||
..writeln(ranked[i].message);
|
||||
if (ranked[i].evidence.isNotEmpty) {
|
||||
|
|
@ -580,6 +587,35 @@ Guidance buildGuidance({
|
|||
);
|
||||
}
|
||||
|
||||
/// Metadata for a report persisted to yams: what produced it, from which
|
||||
/// project, when, and - when the project is a git checkout - at which commit,
|
||||
/// so a report read back from the corpus can be dated and reproduced.
|
||||
String yamsMetadata({
|
||||
required String project,
|
||||
required DateTime generated,
|
||||
String? commit,
|
||||
}) => [
|
||||
'task=pipe-guide',
|
||||
'phase=report',
|
||||
'source=analysis',
|
||||
'project=$project',
|
||||
'generated=${generated.toUtc().toIso8601String()}',
|
||||
if (commit != null) 'commit=$commit',
|
||||
].join(',');
|
||||
|
||||
/// The HEAD commit of the git checkout at [root], or null when there is none
|
||||
/// (not a repository, or git is not installed).
|
||||
Future<String?> gitHead(String root) async {
|
||||
try {
|
||||
final result = await Process.run('git', ['-C', root, 'rev-parse', 'HEAD']);
|
||||
if (result.exitCode != 0) return null;
|
||||
final head = (result.stdout as String).trim();
|
||||
return RegExp(r'^[0-9a-f]{7,64}$').hasMatch(head) ? head : null;
|
||||
} on ProcessException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Locate the `yams` CLI on PATH, if present.
|
||||
String? findYams() {
|
||||
final path = Platform.environment['PATH'];
|
||||
|
|
|
|||
|
|
@ -143,6 +143,38 @@ void main() {
|
|||
}
|
||||
});
|
||||
|
||||
test('the persisted markdown carries its caution and each ranking', () {
|
||||
// --yams persists the markdown, not the brief, and it used to drop both
|
||||
// the caution line and the [severity/confidence] tag of every finding.
|
||||
final md = guidance().markdown;
|
||||
final lines = md.split('\n');
|
||||
expect(lines[2], startsWith('Static reachability claims'));
|
||||
final top = rankFindings(analysis.report.newFindings).first;
|
||||
expect(
|
||||
md,
|
||||
contains(
|
||||
'### 1. [${top.severity.name}/${top.confidence}] '
|
||||
'${top.rule} — ${top.location}',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('yams metadata records provenance, not a stale owner', () {
|
||||
final metadata = yamsMetadata(
|
||||
project: 'app',
|
||||
generated: DateTime.utc(2026, 9, 22, 12),
|
||||
commit: 'abc1234',
|
||||
);
|
||||
expect(metadata, contains('project=app'));
|
||||
expect(metadata, contains('generated=2026-09-22T12:00:00.000Z'));
|
||||
expect(metadata, contains('commit=abc1234'));
|
||||
expect(metadata, isNot(contains('owner=')));
|
||||
expect(
|
||||
yamsMetadata(project: 'app', generated: DateTime.utc(2026)),
|
||||
isNot(contains('commit=')),
|
||||
);
|
||||
});
|
||||
|
||||
test('json summary exposes counts and suppression notes', () {
|
||||
final summary = guidance().summary;
|
||||
expect(summary['findings'], analysis.report.findings.length);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue