diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..0369261 --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,18 @@ +name: Profile quality + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + static: + name: Static integrity + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 + - run: python3 scripts/check_text.py + - run: python3 scripts/check_profile.py diff --git a/profile/README.md b/profile/README.md index 0b9f3ea..1ed4ab4 100644 --- a/profile/README.md +++ b/profile/README.md @@ -6,11 +6,13 @@

-

Meaning flows through graphs.
GraphABI finds where it breaks.

+

Semantic Compatibility Infrastructure for agent graphs.

+ +

Your schema passed.
Your agent still broke.

- Semantic Compatibility Infrastructure for agent graphs.
- Find the first incompatible edge, inspect the recorded witness, and trace everything downstream. + GraphABI finds the first edge where meaning changed, shows the recorded witness,
+ and maps every downstream node that may be affected.

![GraphABI semantic pulse stopping at researcher to verifier and revealing the affected path and trace-backed witness](assets/demo.gif) @@ -19,6 +21,10 @@ uvx --from git+https://github.com/graphabi/graphabi graphabi demo --allow-breaking ``` +| Explicit contracts | Trace-backed evidence | Honest uncertainty | +|---|---|---| +| Consumers state the assumptions they rely on. | Every verdict points to an observed run and witness. | Missing evidence stays unknown. It never becomes a pass. | +

Repository · @@ -29,4 +35,4 @@ uvx --from git+https://github.com/graphabi/graphabi graphabi demo --allow-breaki Security

-

Public alpha · Apache-2.0 · Local and deterministic by default · No API key required

+

One project · Public alpha · Apache-2.0 · Local and deterministic by default

diff --git a/scripts/check_profile.py b/scripts/check_profile.py new file mode 100644 index 0000000..132c32a --- /dev/null +++ b/scripts/check_profile.py @@ -0,0 +1,39 @@ +"""Verify the organization profile's small public contract.""" + +from __future__ import annotations + +from pathlib import Path +from xml.etree import ElementTree + +ROOT = Path(__file__).parents[1] + + +def main() -> int: + readme = (ROOT / "profile/README.md").read_text(encoding="utf-8") + required = ( + "Explicit contracts", + "Trace-backed evidence", + "Honest uncertainty", + "https://github.com/graphabi/graphabi", + "https://graphabi.github.io", + "CONTRIBUTING.md", + "/security/policy", + "uvx --from git+https://github.com/graphabi/graphabi", + ) + missing = [item for item in required if item not in readme] + for name in ("logo-dark.svg", "logo-light.svg"): + ElementTree.parse(ROOT / "profile/assets" / name) + gif = (ROOT / "profile/assets/demo.gif").read_bytes() + if not gif.startswith((b"GIF87a", b"GIF89a")): + missing.append("valid demo.gif") + if missing: + print("Organization profile verification failed:") + for item in missing: + print(f"- missing {item}") + return 1 + print("Organization profile links, principles, command, and assets are present.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/check_text.py b/scripts/check_text.py new file mode 100644 index 0000000..67b2fcc --- /dev/null +++ b/scripts/check_text.py @@ -0,0 +1,36 @@ +"""Reject prohibited punctuation and private paths in tracked text.""" + +from __future__ import annotations + +import subprocess +from pathlib import Path + +ROOT = Path(__file__).parents[1] + + +def main() -> int: + names = subprocess.check_output(["git", "ls-files", "-z"], cwd=ROOT).split(b"\0") + offenders: list[str] = [] + mac_user_prefix = "/" + "Users" + "/" + windows_user_prefix = "C:" + "\\" + "Users" + "\\" + for name in names: + if not name: + continue + path = ROOT / name.decode() + try: + text = path.read_text(encoding="utf-8") + except (UnicodeDecodeError, OSError): + continue + if chr(0x2014) in text or mac_user_prefix in text or windows_user_prefix in text: + offenders.append(str(path.relative_to(ROOT))) + if offenders: + print("Tracked public text contains prohibited content:") + for offender in offenders: + print(f"- {offender}") + return 1 + print("Tracked public text contains no em dash or private absolute path.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())