Context
Filed per Feature #295 spec FR-011 (specs/295-f292-verification-runs/spec.md): "risk-scores.sarif carries no regen claim, with the generator-parameterization gap filed as a follow-up enhancement Issue." This is an ALWAYS-file task (T016), independent of whether Feature #295's own Cat 6 gate (T013) passes or fails — it documents a structural limitation of scripts/generate-risk-scores-sarif.py that blocks any future example baseline from carrying a byte-identity regen claim for its risk-scores.sarif, the way examples/multi-tenant-rag-app/threats.sarif does for FR-011's narrower threats.sarif claim (via the now URI-corrected generate-threats-sarif.py).
Current state (verified against scripts/generate-risk-scores-sarif.py at HEAD)
No CLI — confirmed no argparse import and no sys.argv usage anywhere in the file. All paths are module-level constants:
# lines 39-42
SAMPLE = REPO_ROOT / "examples/agentic-app/sample-report"
RISK_MD = SAMPLE / "risk-scores.md"
THREATS_MD = SAMPLE / "threats.md"
OUT_SARIF = SAMPLE / "risk-scores.sarif"
# lines 44-46
SOURCE_THREATS_URI = (
"examples/agentic-app/test-output/2026-04-26T03-39-12-F3-wave3/threats.md"
)
Every path — input risk-scores.md, input threats.md, output risk-scores.sarif, and the SARIF artifactLocation.uri value itself — is hardcoded to the agentic-app baseline. Running this script against any other example's risk-scores.md (e.g. examples/multi-tenant-rag-app/risk-scores.md) is not possible without editing the script in place.
Hardcoded findings-count gate, main():
# line 535
if len(findings) < 80:
print(
f"FAIL: parsed only {len(findings)} findings from risk-scores.md Section 2",
file=sys.stderr,
)
return 1
This assumes the agentic-app baseline's finding count (≥80) as a universal sanity floor. multi-tenant-rag-app's own current-pipeline run produced 43 deduplicated findings — well under 80 — so this gate would hard-fail against a legitimately smaller, correctly-generated baseline, not just against parse errors.
Impact
Every additional example baseline that wants a risk-scores.sarif regen-byte-identity claim (matching the pattern this feature establishes for threats.sarif via FR-011/FR-014) is blocked by this generator until it is parameterized. examples/multi-tenant-rag-app/ is the immediate motivating case (Feature #295), but the gap is generic — it blocks every future baseline, not just this one.
Suggested remediation (not prescriptive — implementer's choice)
- Add CLI arguments for input
risk-scores.md path, input threats.md path, output risk-scores.sarif path, and the SARIF source URI (mirroring the input/derived-URI pattern FR-014 just added to generate-threats-sarif.py), defaulting to today's agentic-app constants for backward compatibility with existing callers/tests.
- Replace the fixed
>= 80 floor with either a --min-findings CLI option (default preserving 80 for agentic-app callers) or a purely structural check (len(findings) > 0, matching this feature's own fail-closed convention — contracts oi-extraction-contract.md §2 / regen-byte-identity-contract.md §1.4 — rather than a magic-number heuristic tied to one specific baseline's size).
Scope note
Out of scope for Feature #295 itself (FR-020 scope fence: no generator changes beyond FR-014's URI derivation in generate-threats-sarif.py). risk-scores.sarif for multi-tenant-rag-app carries no regen claim as a result, and is not part of that feature's 5-artifact baseline claim structure (data-model.md entity 4: presence-only, no regen claim) — independent of whether T013's Cat 6 gate passes.
References
specs/295-f292-verification-runs/spec.md FR-011, Scope "Out" section
specs/295-f292-verification-runs/data-model.md entity 4, entity 7
scripts/generate-risk-scores-sarif.py:39-46,535
Context
Filed per Feature #295 spec FR-011 (
specs/295-f292-verification-runs/spec.md): "risk-scores.sarifcarries no regen claim, with the generator-parameterization gap filed as a follow-up enhancement Issue." This is an ALWAYS-file task (T016), independent of whether Feature #295's own Cat 6 gate (T013) passes or fails — it documents a structural limitation ofscripts/generate-risk-scores-sarif.pythat blocks any future example baseline from carrying a byte-identity regen claim for itsrisk-scores.sarif, the wayexamples/multi-tenant-rag-app/threats.sarifdoes for FR-011's narrowerthreats.sarifclaim (via the now URI-correctedgenerate-threats-sarif.py).Current state (verified against
scripts/generate-risk-scores-sarif.pyat HEAD)No CLI — confirmed no
argparseimport and nosys.argvusage anywhere in the file. All paths are module-level constants:Every path — input
risk-scores.md, inputthreats.md, outputrisk-scores.sarif, and the SARIFartifactLocation.urivalue itself — is hardcoded to theagentic-appbaseline. Running this script against any other example'srisk-scores.md(e.g.examples/multi-tenant-rag-app/risk-scores.md) is not possible without editing the script in place.Hardcoded findings-count gate,
main():This assumes the
agentic-appbaseline's finding count (≥80) as a universal sanity floor.multi-tenant-rag-app's own current-pipeline run produced 43 deduplicated findings — well under 80 — so this gate would hard-fail against a legitimately smaller, correctly-generated baseline, not just against parse errors.Impact
Every additional example baseline that wants a
risk-scores.sarifregen-byte-identity claim (matching the pattern this feature establishes forthreats.sarifvia FR-011/FR-014) is blocked by this generator until it is parameterized.examples/multi-tenant-rag-app/is the immediate motivating case (Feature #295), but the gap is generic — it blocks every future baseline, not just this one.Suggested remediation (not prescriptive — implementer's choice)
risk-scores.mdpath, inputthreats.mdpath, outputrisk-scores.sarifpath, and the SARIF source URI (mirroring theinput/derived-URI pattern FR-014 just added togenerate-threats-sarif.py), defaulting to today'sagentic-appconstants for backward compatibility with existing callers/tests.>= 80floor with either a--min-findingsCLI option (default preserving80foragentic-appcallers) or a purely structural check (len(findings) > 0, matching this feature's own fail-closed convention — contractsoi-extraction-contract.md§2 /regen-byte-identity-contract.md§1.4 — rather than a magic-number heuristic tied to one specific baseline's size).Scope note
Out of scope for Feature #295 itself (FR-020 scope fence: no generator changes beyond FR-014's URI derivation in
generate-threats-sarif.py).risk-scores.sarifformulti-tenant-rag-appcarries no regen claim as a result, and is not part of that feature's 5-artifact baseline claim structure (data-model.md entity 4: presence-only, no regen claim) — independent of whether T013's Cat 6 gate passes.References
specs/295-f292-verification-runs/spec.mdFR-011, Scope "Out" sectionspecs/295-f292-verification-runs/data-model.mdentity 4, entity 7scripts/generate-risk-scores-sarif.py:39-46,535