From e03c2a299bdf95fec71d4963c07b1ca28637510c Mon Sep 17 00:00:00 2001 From: trvon Date: Sun, 30 Aug 2026 14:07:43 -0600 Subject: [PATCH 1/4] fix(fold): normalize imported finding paths --- src/fold.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/fold.rs b/src/fold.rs index a925752..a6afd96 100644 --- a/src/fold.rs +++ b/src/fold.rs @@ -207,19 +207,45 @@ fn native_backend(value: &Value) -> String { } fn find_file(building: &Building, path: &str) -> Option { - let normalized = path.replace('\\', "/"); + let normalized = normalize_lexical_path(path); building .nodes .iter() .filter(|node| node.kind == NodeKind::File) .find(|node| { node.path.as_deref().is_some_and(|candidate| { + let candidate = normalize_lexical_path(candidate); normalized == candidate || normalized.ends_with(&format!("/{candidate}")) }) }) .map(|node| node.id.clone()) } +fn normalize_lexical_path(path: &str) -> String { + let portable = path.replace('\\', "/"); + let absolute = portable.starts_with('/'); + let mut components = Vec::new(); + for component in portable.split('/') { + match component { + "" | "." => {} + ".." => { + if components.last().is_some_and(|previous| *previous != "..") { + components.pop(); + } else if !absolute { + components.push(component); + } + } + _ => components.push(component), + } + } + let normalized = components.join("/"); + if absolute { + format!("/{normalized}") + } else { + normalized + } +} + fn confidence_value(confidence: &str) -> f64 { match confidence { "concrete-witness" => 1.0, @@ -258,4 +284,52 @@ mod tests { assert_eq!(finding.attributes["confidence"], "proved"); assert_eq!(finding.attributes["backend"], "source"); } + + #[test] + fn normalizes_fold_paths_without_matching_a_missing_neighbor() { + let dir = tempfile::tempdir().unwrap(); + let header = dir.path().join("include/yams/core/types.h"); + fs::create_dir_all(header.parent().unwrap()).unwrap(); + fs::write(&header, "struct Type {};\n").unwrap(); + let report = dir.path().join("fold.sarif"); + fs::write( + &report, + r#"{ + "runs": [{ + "results": [ + { + "ruleId": "fold.valid", + "message": {"text": "valid"}, + "locations": [{"physicalLocation": { + "artifactLocation": {"uri": "../../include/yams/daemon/components/../../core/types.h"}, + "region": {"startLine": 1} + }}] + }, + { + "ruleId": "fold.missing", + "message": {"text": "missing"}, + "locations": [{"physicalLocation": { + "artifactLocation": {"uri": "../../include/yams/daemon/components/../../core/missing.h"}, + "region": {"startLine": 1} + }}] + } + ] + }] + }"#, + ) + .unwrap(); + + let mut building = scan(dir.path()).unwrap(); + assert_eq!(import_findings(&mut building, &report).unwrap(), 1); + assert_eq!( + building + .nodes + .iter() + .filter(|node| node.kind == NodeKind::Finding) + .count(), + 1 + ); + assert_eq!(building.diagnostics.len(), 1); + assert!(building.diagnostics[0].message.contains("missing.h")); + } } -- 2.52.0 From 2f162372c251719612c87aac3e16c32ed44426b2 Mon Sep 17 00:00:00 2001 From: trvon Date: Sun, 30 Aug 2026 14:07:53 -0600 Subject: [PATCH 2/4] bench: fingerprint benchmark working trees --- tests/benchmarks/README.md | 4 ++ tests/benchmarks/runner.py | 100 +++++++++++++++++++++++++++++--- tests/benchmarks/test_runner.py | 41 +++++++++++++ 3 files changed, 137 insertions(+), 8 deletions(-) diff --git a/tests/benchmarks/README.md b/tests/benchmarks/README.md index e28ba38..fa4087f 100644 --- a/tests/benchmarks/README.md +++ b/tests/benchmarks/README.md @@ -19,6 +19,10 @@ Brick's explicit `--exclude` option. Validate each resulting graph with YAMS's `tests/benchmarks/brick/contract.py`; the plan's broad count bounds are coverage guards, not precision or architecture grades. +`run_manifest.json` records Git provenance for both Brick and the corpus. Dirty +trees include a SHA-256 fingerprint over status, tracked diffs, and untracked +file contents so retained results identify the exact measured working state. + Before changing an extractor or score, add the expected positive and clean-negative cases, name one owner, and state the expected metric/identity delta. Use at least three repeats for performance claims. diff --git a/tests/benchmarks/runner.py b/tests/benchmarks/runner.py index ae97da2..44f6ba9 100755 --- a/tests/benchmarks/runner.py +++ b/tests/benchmarks/runner.py @@ -5,7 +5,9 @@ from __future__ import annotations import argparse import datetime as dt +import hashlib import json +import os import pathlib import platform import statistics @@ -17,6 +19,89 @@ ROOT = pathlib.Path(__file__).resolve().parents[2] PLANS = ROOT / "tests" / "benchmarks" / "plans" +def git_provenance(path: pathlib.Path) -> dict: + """Describe a Git worktree and fingerprint all tracked and untracked changes.""" + + discovered = subprocess.run( + ["git", "rev-parse", "--show-toplevel"], + cwd=path, + text=True, + capture_output=True, + check=False, + ) + if discovered.returncode != 0: + return { + "root": str(path.resolve()), + "revision": None, + "dirty": None, + "working_tree_fingerprint": None, + } + + repository = pathlib.Path(discovered.stdout.strip()).resolve() + revision = subprocess.run( + ["git", "rev-parse", "HEAD"], + cwd=repository, + text=True, + capture_output=True, + check=False, + ) + status = subprocess.run( + ["git", "status", "--porcelain=v1", "--untracked-files=all", "-z"], + cwd=repository, + capture_output=True, + check=False, + ) + if revision.returncode != 0 or status.returncode != 0: + return { + "root": str(repository), + "revision": None, + "dirty": None, + "working_tree_fingerprint": None, + } + + dirty = bool(status.stdout) + fingerprint = None + if dirty: + diff = subprocess.run( + ["git", "diff", "--binary", "HEAD"], + cwd=repository, + capture_output=True, + check=False, + ) + untracked = subprocess.run( + ["git", "ls-files", "--others", "--exclude-standard", "-z"], + cwd=repository, + capture_output=True, + check=False, + ) + if diff.returncode == 0 and untracked.returncode == 0: + digest = hashlib.sha256() + digest.update(b"status\0") + digest.update(status.stdout) + digest.update(b"diff\0") + digest.update(diff.stdout) + for encoded_path in filter(None, untracked.stdout.split(b"\0")): + entry = repository / os.fsdecode(encoded_path) + if entry.is_symlink(): + contents = os.fsencode(os.readlink(entry)) + elif entry.is_file(): + contents = entry.read_bytes() + else: + contents = b"" + digest.update(b"untracked\0") + digest.update(encoded_path) + digest.update(b"\0") + digest.update(contents) + fingerprint = digest.hexdigest() + + return { + "root": str(repository), + "revision": revision.stdout.strip(), + "dirty": dirty, + "working_tree_fingerprint": fingerprint, + } + + def load_plan(name: str) -> dict: path = PLANS / f"{name}.json" with path.open(encoding="utf-8") as handle: @@ -71,20 +156,19 @@ def run_plan( stamp = dt.datetime.now(dt.UTC).strftime("%Y%m%dT%H%M%SZ") artifact = out_dir or ROOT / "build" / "benchmarks" / name / stamp artifact.mkdir(parents=True, exist_ok=False) - revision = subprocess.run( - ["git", "rev-parse", "HEAD"], - cwd=ROOT, - text=True, - capture_output=True, - check=False, - ) + brick_provenance = git_provenance(ROOT) + corpus_provenance = git_provenance(corpus) manifest = { "schema_version": 1, "started_at": stamp, "plan": name, "corpus": str(corpus), "root": str(ROOT), - "revision": revision.stdout.strip() if revision.returncode == 0 else None, + "revision": brick_provenance["revision"], + "provenance": { + "brick": brick_provenance, + "corpus": corpus_provenance, + }, "host": { "platform": platform.platform(), "python": platform.python_version(), diff --git a/tests/benchmarks/test_runner.py b/tests/benchmarks/test_runner.py index 94a6532..843d5a4 100644 --- a/tests/benchmarks/test_runner.py +++ b/tests/benchmarks/test_runner.py @@ -5,6 +5,8 @@ from __future__ import annotations import importlib.util import pathlib +import subprocess +import tempfile import unittest HERE = pathlib.Path(__file__).resolve().parent @@ -15,6 +17,45 @@ SPEC.loader.exec_module(runner) class RunnerTests(unittest.TestCase): + def test_git_provenance_fingerprints_dirty_corpus_state(self) -> None: + with tempfile.TemporaryDirectory() as directory: + repository = pathlib.Path(directory) + subprocess.run(["git", "init", "--quiet"], cwd=repository, check=True) + subprocess.run( + ["git", "config", "user.email", "brick-tests@example.invalid"], + cwd=repository, + check=True, + ) + subprocess.run( + ["git", "config", "user.name", "Brick Tests"], cwd=repository, check=True + ) + subprocess.run( + ["git", "config", "commit.gpgsign", "false"], cwd=repository, check=True + ) + tracked = repository / "tracked.cpp" + tracked.write_text("int value = 1;\n", encoding="utf-8") + subprocess.run(["git", "add", "tracked.cpp"], cwd=repository, check=True) + subprocess.run( + ["git", "commit", "--quiet", "-m", "fixture"], cwd=repository, check=True + ) + + clean = runner.git_provenance(repository) + self.assertFalse(clean["dirty"]) + self.assertIsNone(clean["working_tree_fingerprint"]) + + tracked.write_text("int value = 2;\n", encoding="utf-8") + (repository / "untracked.dart").write_text("void main() {}\n", encoding="utf-8") + dirty = runner.git_provenance(repository) + self.assertTrue(dirty["dirty"]) + self.assertEqual(dirty["revision"], clean["revision"]) + self.assertRegex(dirty["working_tree_fingerprint"], r"^[0-9a-f]{64}$") + + (repository / "untracked.dart").write_text("void changed() {}\n", encoding="utf-8") + changed = runner.git_provenance(repository) + self.assertNotEqual( + changed["working_tree_fingerprint"], dirty["working_tree_fingerprint"] + ) + def test_external_corpus_and_build_arguments_are_explicit(self) -> None: corpus = pathlib.Path("/tmp/yams") plan = {"corpus": "tests/fixtures/mixed", "build_args": ["--exclude", "site"]} -- 2.52.0 From b6e51e5076d62f32c5e9d85845de3e4c337b2681 Mon Sep 17 00:00:00 2001 From: trvon Date: Sun, 30 Aug 2026 14:08:03 -0600 Subject: [PATCH 3/4] docs: clarify architecture evidence boundaries --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 3745b54..f87b095 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,11 @@ location so consumers can distinguish it from imported symbolic evidence. cargo run -- build ../fold --json fold.brick.json --html fold.brick.html +Exclude generated or checked-in output by exact directory component (repeatable): + + cargo run -- build ../yams --exclude site --exclude build \ + --json yams.brick.json --html yams.brick.html + Layer Fold findings onto the building: cargo run -- build ../fold \ @@ -22,6 +27,11 @@ Layer Fold findings onto the building: --json fold.brick.json \ --html fold.brick.html +Fold artifact paths are normalized lexically across `/`, `\\`, `.`, and `..` +components before repository-relative matching. Findings for excluded, +generated, or genuinely missing files remain diagnostics instead of being +attached to a neighboring source file. + Render an existing model or enforce an explicit experimental gate: cargo run -- render fold.brick.json --html fold.brick.html @@ -53,6 +63,13 @@ multiline signatures. Its score is not proof of correctness, maintainability, or security. Use the component metrics and evidence records; do not rank teams or repositories by the composite alone. +Unqualified calls such as `lock`, `size`, and `empty` may merge unrelated C++ +targets or remain external; recursion and overloads may also appear as lexical +self-cycles. File fan-out is therefore a decomposition signal, not proof of +semantic coupling. Scope architecture gates to production paths and verify each +candidate against source and tests. Cross-translation-unit and namespaced C++ +resolution remain priority adapter work. + The next serious analyzer milestone should consume compiler/YAMS/Fold graph facts through adapters while retaining the standalone lexical lane as a fast preview. See docs/architecture/graph-model.md and docs/ROADMAP.md. -- 2.52.0 From f26d5411813102cc8670c75e990bfad848baa17a Mon Sep 17 00:00:00 2001 From: trvon Date: Sun, 30 Aug 2026 14:08:16 -0600 Subject: [PATCH 4/4] chore: remove tracked Python bytecode --- .gitignore | 3 ++- .../architecture_summary.cpython-314.pyc | Bin 16102 -> 0 bytes .../__pycache__/runner.cpython-314.pyc | Bin 10540 -> 0 bytes 3 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 skills/brick-sast/scripts/__pycache__/architecture_summary.cpython-314.pyc delete mode 100644 tests/benchmarks/__pycache__/runner.cpython-314.pyc diff --git a/.gitignore b/.gitignore index 65223a6..29e6f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /build/ /brick.json /brick.html - +__pycache__/ +*.py[cod] diff --git a/skills/brick-sast/scripts/__pycache__/architecture_summary.cpython-314.pyc b/skills/brick-sast/scripts/__pycache__/architecture_summary.cpython-314.pyc deleted file mode 100644 index 4043705a2ebb3b1591c500a436f1729075145364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16102 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 diff --git a/tests/benchmarks/__pycache__/runner.cpython-314.pyc b/tests/benchmarks/__pycache__/runner.cpython-314.pyc deleted file mode 100644 index 1e11254ec19823493b1e289868f3428724d4f663..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10540 zcmbtaTW}lKd0qeuV1dPj1Of0)fC4W9MG%rmSrl~(C6T(5$dZB;g%k=AOA;1t-d$QE z>$pg#GokEegvQPoo;VYBCNrg)v}T^lhdyZBmrOG4fC4dq*L+Z#X{YHE6x*Z5?L+@_ z77MIUI!Y&p#JOMp^Pm6x|9AF~#cU+N{pRp{ul;)~LHrseWT%rNs?YvWMG$F%Aq3(! z!Kf~)E~y2z3&qu!HG&3*q@cy2PSD{{FX(Yd2^0=JK z>?Yb`czBV}%565EeFegM8!wZ6MG0O3R`wp8}SdNFeyKZhJ zkzhIZVv=*81zt2( zd*VfHDi%)g3ux~u`$v!v*Ff?!H$>7zkhrZL{R^NFo1p z)Mrpi;1!|>a(ejT6|TdK(!?CjL|%|E!O1zQR`OU%6;uVFcD+MXI9{RINmWR-qF&L2 zs(h1D&yjMAK;>-8X%u!7LAA^SDGg8){zfXJxQLsYfI(SXiZi6#;C&33})tq9Bnv2^apmcCW(shA*{4ukp#mm)aF!(Kq@?B~rlg$w)M@G$mU2 zg=ID#4!r@K1I)}((BE2fH1S3_7LB+O6T71kHX%fX)iJlI=hzer47b)&iMZn{_yoCA zNj@q>-(bCZQ5(26J~bnf$rKCBibfX6STYul0P3+MPnMfv>J(f9Bpu5u- zN(S@8)(5TGi|egLL(i_EXH&OlZF;!+_G;Fdx4PHK=NiJ;`&3VV=l-|v=NjC3efP%K zclCXnJs%x>ba3mH{J_|DWOv})o~0$%espVOt1s7jB5xVXQDb|0Y8D5YH=-$C6W)Lsr zt7QVCWk^N`KRrYFwICl196D`WH}cR3qE3=dUz!jhW6?W90Yp&k5*JP_i{!Epk8xysFkUP#8{z|SEN)0_{=F+HzCBu$hl z!q8Bn%q6O^M43vIb&sOgC*PqHVIYMh*O=^@Akw>M%En`Zz1VUBOEnMX~o&?1I2XB*w9# zdj~Pjp!*J7D=%lCBQQFT$b{I(sB%6--UeAl!Il(kyKtt&D-|IK4G5yTgkRwH3|t|M zN~zEUfp?VY(Vr3oqk&qaG8bxTm1$JVuTH6vm_7kLMV=jAxFv;J2GO-{5cT|O{0`j8qDhK`7LqFoL8Rl+M5tO60Xdrhxw{Z$dC^f# zt%lgh5?g6uM=k1#cn|}t3o&R!;nb*&@+vyb+D`@ZMyW8vXP(~GNZft_L8e_<68ySvF(<}2MZ^z?zpb58#ALj zR7XkQl)1mFca=N?o2Lt&6Wcc*#|o!sc04ms;nWW0F42x0>5$k)$@%E|!km8)Pw%Dj zRPQH|Sde5XYK)J#s86m4p-7ZlYf=hR_nYpiWP%l~lB5kK;nL*bcErbn1ErOCsYE>k zmH1ci+@6C@sXWLfqToP^f{U1|p0=QdA(T9;RMG-kd7xT|E(GLKWRMJ?OQ_Dt z<<$|f2{2bxyckuGtW%ND#e`h|-4S&zfb`KiH&<(cu9-R~uRPFHR{%+-dY7cMvnmB$ zJoR+>edbb-P*N%Qg7K8n1$6bnTE;y1g>{rBv7~2Oq0A9jD1j1g>f)Wxx@v#kTNiqlyMGS;Ml==X;z*W znVJp6glh6lI2Sa`uq8-?$}f2!dFLL z{pS%e++S)G?@#5UIvs!+!iEZ%_pG0t}jC^8BGT zl7)3naV9}CMY0O&?ZbmI-N6_#1<++)=kPvO1G@+tLIuwo2E7t~1E8CS50aVg88y+hI7 z5p?{X_72ctoI&FvNd69D)|oN}A*C=!Ps{6J+=$zh=4j9mI4hUdLZ&-NGY5iJ#xplA z=LQ>ZYh=Te>4Ew7DCg_1$`}{${nbB{))oYSOIhp1HmPPfJH5*CRLk7?>Uhn;7J0l> z>)b>&zcp}Cj@Lq2ddPbu^Vkv?&cI_e3iJhA;UxA4n}H71IRnoafZ}Zminj&Z7>{yp zwH-^fr`oWrr9r=Jp1Um1B506DXAairHg`oX4_uRDwGjBKU2dhIuXk=*u2U;#2IjuL zPwpW&y@SD4*pp_)7c}^dsSc1ULw~eP)cm0`5k~X>(W7nIBV{K8wdy+$U<637Gz^lNK?kMk$M|mFLoH6&BrS}`X@!rU6 z@1@@By)(DCL(qmpSH$e3S1syOVGh6?9uT1WfC7Y)cfF*jS-2MwNrAmDh?a$L3TynJ z|E5+1u$GtEg}WS5R74{$0C38JEi7Q$S0uS)QV=OX8>0w1ngWm^$wLMpGy(!9MO|uD zSO#0V5sd8+7{bv-fJreFg|N#gvTp=YW#o{S#@Uev))=v-!;poKgM$oc1-8FoZN4?_ z5VFXl{{ccz)FzS@w>6Jy=Dc@?#CClhW7ta2j+6~R}czG9e* zMm82s@vx>ij}0PGCz-r!ofXr^Eu|%(*S#2y0u~HZHlB1>EalT;W37)+oQ*`o3DKg= ziq@sW_eHA=sfDB|W2*`b!*DzWrrVkgVO&ET%O_)Run|nKH50!ASOT{yrJ6hvKwZPG zVNzzJ(dT9)fDV#0q^{%npfY!yN2TG!5abH98fSLa4QSIDdCu#2WtrW6dM5DVjPq=K&z)S?Dnc1Ou#H#@i zFe)zdKRIKccp(BD4)X)FBgI`s z-CHDPm4Q&vc#n$;YzQ3-4&mUUHnI{=0kF>@8p3%&voNJtZc(za!4yOqqG)2knujt8 z;Y1@r2?wuA1c&r<(K0Su+m#yO6f*UpUw{E35+`Wjl|s}31iJz}u89GRiVmLuCl;_7 zQCHzI4cPyp1}uAT7lu$dWL$FSa<5@iXoN0$;|BuHv719uWt z)=4}r>MJJ%29Wp~pUosE@JP`E1PxH%uW}N&Mj@es!Qj7y7HH}G7Rb3Y@wt&OIWn{F zoCO@%(pj{;lC!+>WBVq#dGqfqh3;31=CeEIvw8D)da^_}K0N*4^ux1npT$V;=(cm4 z%C(N?E$4F7xjmER;nfFMA5K4*{_xz7CO??Wn>rWtj?l!GH0Fq zuxF$BheMmE3T?-?dkSr59y&?C&iXoxUed zU*732Yc-9=vX#cewGcW>uEA5#dWxifhxG4JriaG20e;yS-=+FC?FGuWtuJc`?cvV} zwN?jsgtak!vD9EsU*5AdXUXh0erPS)4zBA;4K3N=#^lE6=CNG+kwU|fb#2MooV~oU zxN&pyMy_qRU>#m3_iWCh&GW?O$=iC@^?SC?Y-DpHZySZUz3cs{?@g6VO?wUYQlq2P z?kd@ufhrE;y5VyR(cE5i_CIm<=bhfoiv{QKmQZkl5%CU>SfFn(do6wvPY(?Y!gEquU#^nMiiz{ns+DJ-WT)I0f_j>O!C_nk|63CdU)H zqtw#9ei`_}fgpBr;Cw{pxkbDeW} z%Y2TS|J70Su<^70P2Kt%nOM>4$yq%=>rY?IS;n4HEr=g6D>lA2oVoYzsS?%x;f)`U z6+I(QJR@7L<~^skU(a`rm#CHxJ=vun3@Re6*^v^}k$nvS?#yxQl^wKIm%dn*IIpLm z?J1Inci>o5IB#S_wM!k?m@QD=t&52Bj>w#+vt%pc=;Z>{7j(WPuvo zx`(PClB!b#-Ia}GgJnY1VDdNXu|{*eJ(&MbNyol*U9aR1=odK*TiF{Y}Oer ztI)u7*#?IxLl?B|MY4Z~1Y&MC=g9tDavT8A^z`$%3iu0HFK71t&u;+3p!B)sKT40-?sRQrLCwYS`qI;h_FwYU0$3w`WgL#Kcj z!I-aiN)YcWdZ7LvJrMf=oU(bF(!i_nJ`g9P!4Mt5OHW{((nCj*YAtcs91^Ltj})YA1q7*9<-%XqrCIOTp$Lh1C?hM)`cw1A=Id zff=?Cj)nMm@-EBWfCd~Q4mXOLcFC{sHH%MajY#HTd#zCFRACOT9jFy9hq(kO#PA(U zWsdF?QtDyWk$?@~Er@c0$CN4>8xn-PNT8V>!7C>4$CtAXhNC+v`I0@gnptO__ zO(+g6aeZWC;`e8f#1GI$TnRs*V#;AfpA*n3L&yt*2Vcu@@F@U?G&xCkMfx0GAbd}t zs|-WK@D;-i#>eWPG&d5x&PweNbjkr1Mes;^R5VCQVIXoA~-Y%J(}AV}cL0kflM z?s;PF$(#E?A+)s=ZT&m8{>^VZw&!g9dD~?AYKgQK$+jJ`Eqij8>@PKT6dU_@8v8f3 z`NpC2l@e(wlI=TWdv`^R7w(pWBYuQ(R`szn>kLGap80eoxx?_j# z$kSb*titCAZ+`pD%%AS+5A0c6vaY<bQRbZG z=q@$5$TBEDXHReXVy$H6kS3Nc5?H2W+P$an!3W>&0XmJGt3Ly?%3*5WNTR`3& zqA-g_0kjB#er>hi{Yq1m%q*4|5NCIFUFC8DH3XlDKFC zlBgN_drM1Q2?z*U!eSH?H4-u+Ug4@d`$60 z54@Q_Z$oc@U)