Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1219a06
docs: refresh README public surface
seonghobae Sep 1, 2026
415a411
docs: repair Pages navigation
seonghobae Sep 1, 2026
47352b5
docs: add authoritative Pages landing source
seonghobae Sep 1, 2026
63e3d7a
fix(pages): publish the intended landing source
seonghobae Sep 1, 2026
8ecc367
test(pages): bind publication to authoritative landing
seonghobae Sep 1, 2026
ced23d9
ci(pages): validate the public landing contract
seonghobae Sep 1, 2026
2239319
docs: remove unpublished duplicate landing source
seonghobae Sep 1, 2026
c86daf8
test(pages): include landing in publisher fixtures
Sep 1, 2026
3ee5b07
test(ci): require explicit hosted runner images
seonghobae Sep 1, 2026
cb9ef1c
fix(ci): pin test runners to Ubuntu 24.04
seonghobae Sep 1, 2026
8f70c48
fix(ci): pin Pages runners to Ubuntu 24.04
seonghobae Sep 1, 2026
3836855
fix(ci): pin PROV-O runner to Ubuntu 24.04
seonghobae Sep 1, 2026
35b226b
fix(security): scope SRI exception to canonical metadata
seonghobae Sep 1, 2026
85a03a3
test(ci): inspect job-level runner declarations
seonghobae Sep 1, 2026
c00bd31
docs: make LineageWeave README product-first
seonghobae Sep 1, 2026
032a991
docs: align stack quickstart with home env contract
seonghobae Sep 1, 2026
7540eb9
chore(ci): adopt protected docs-only Tests paths on public-surface br…
seonghobae Sep 3, 2026
72cdf7f
chore(stack): converge public-surface branch with protected main
seonghobae Sep 3, 2026
de3d7a7
chore(public): converge public surface with protected main
seonghobae Sep 3, 2026
01895d1
test(public): expose #931/#908 workflow convergence RED
seonghobae Sep 4, 2026
53cbd8b
fix(public): preserve Draft admission with pinned hosted runners
seonghobae Sep 4, 2026
5e085c3
fix(public): pin PROV-O runner without reopening Draft admission
seonghobae Sep 4, 2026
00e90e0
fix(public): converge Pages publication with Draft admission
seonghobae Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .github/workflows/ontology-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,30 @@ on:
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft, closed]
branches: [main]
paths:
- "docs/index.html"
- "docs/ontology/**"
- "scripts/build_ontology_site.py"
- "scripts/publish_ontology_site.py"
- "scripts/ontology_site_contract.py"
- "tests/test_ontology.py"
- "tests/test_ontology_site.py"
- "tests/test_publish_ontology_site.py"
- "tests/test_public_landing.py"
- ".github/workflows/ontology-pages.yml"
- "pyproject.toml"
- "uv.lock"
push:
branches: [main]
paths:
- "docs/index.html"
- "docs/ontology/**"
- "scripts/build_ontology_site.py"
- "scripts/publish_ontology_site.py"
- "scripts/ontology_site_contract.py"
- "tests/test_ontology.py"
- "tests/test_ontology_site.py"
- "tests/test_publish_ontology_site.py"
- "tests/test_public_landing.py"
- ".github/workflows/ontology-pages.yml"
- "pyproject.toml"
- "uv.lock"
Expand All @@ -41,7 +45,7 @@ jobs:
validate:
name: Validate ontology publication
if: github.event_name == 'pull_request' && github.event.action != 'closed' && github.event.pull_request.draft == false
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
Expand All @@ -66,7 +70,7 @@ jobs:
run: |
uv run --frozen python -m pytest -q tests/test_ontology.py
uv run --frozen python -m coverage run --branch \
-m pytest -q tests/test_ontology_site.py tests/test_publish_ontology_site.py
-m pytest -q tests/test_ontology_site.py tests/test_publish_ontology_site.py tests/test_public_landing.py
uv run --frozen python -m coverage report \
--include=scripts/build_ontology_site.py,scripts/publish_ontology_site.py \
--fail-under=100
Expand All @@ -80,11 +84,12 @@ jobs:
scripts/build_ontology_site.py scripts/publish_ontology_site.py
scripts/ontology_site_contract.py
tests/test_ontology_site.py tests/test_publish_ontology_site.py
tests/test_public_landing.py

publish:
name: Publish ontology to GitHub Pages
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
permissions:
contents: read
pages: write
Expand Down Expand Up @@ -116,7 +121,7 @@ jobs:
run: |
uv run --frozen python -m pytest -q tests/test_ontology.py
uv run --frozen python -m coverage run --branch \
-m pytest -q tests/test_ontology_site.py tests/test_publish_ontology_site.py
-m pytest -q tests/test_ontology_site.py tests/test_publish_ontology_site.py tests/test_public_landing.py
uv run --frozen python -m coverage report \
--include=scripts/build_ontology_site.py,scripts/publish_ontology_site.py \
--fail-under=100
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prov-o-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
standards-contract:
name: Registry, inference, coverage, PostgreSQL
if: github.event_name != 'pull_request' || (github.event.action != 'closed' && github.event.pull_request.draft == false)
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
pytest:
name: Full test suite
if: github.event_name != 'pull_request' || (github.event.action != 'closed' && github.event.pull_request.draft == false)
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:16-alpine@sha256:57c72fd2a128e416c7fcc499958864df5301e940bca0a56f58fddf30ffc07777
Expand Down Expand Up @@ -66,7 +66,7 @@ jobs:
frontend:
name: Frontend lint, test, build
if: github.event_name != 'pull_request' || (github.event.action != 'closed' && github.event.pull_request.draft == false)
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # actions/checkout@v7
Expand Down
305 changes: 128 additions & 177 deletions README.md

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>LineageWeave</title>
<meta name="description" content="Evidence-bound lineage reconstruction and branching history for scattered enterprise records.">
<!-- nosemgrep: html.security.audit.missing-integrity.missing-integrity -- canonical metadata fetches no subresource -->
<link rel="canonical" href="https://contextualwisdomlab.github.io/LineageWeave/">
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
<style>
:root { color-scheme: light dark; font-family: Inter, ui-sans-serif, system-ui, sans-serif; line-height: 1.55; }
* { box-sizing: border-box; }
body { margin: 0; color: #172033; background: #f5f7fb; }
a { color: #174ea6; }
a:focus-visible { outline: 3px solid #f2b705; outline-offset: 3px; }
header { color: white; background: #102a43; padding: 3rem max(1.25rem, calc((100vw - 70rem)/2)); }
header p { max-width: 70ch; color: #d9e8f5; }
main { max-width: 70rem; margin: 0 auto; padding: 2rem 1.25rem 4rem; }
.actions { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); margin: 1.5rem 0 2rem; }
.actions a { display: block; padding: 1rem; border: 1px solid #c8d2df; border-radius: .75rem; background: #fff; text-decoration: none; font-weight: 700; }
.boundary { padding: 1rem 1.25rem; border-left: .35rem solid #2b6cb0; background: #eaf2fb; }
footer { border-top: 1px solid #c8d2df; padding: 2rem 1.25rem; text-align: center; }
@media (prefers-color-scheme: dark) {
body { color: #e8eef5; background: #0b1522; }
header { background: #06111d; }
a { color: #8fc2ff; }
.actions a { background: #122236; border-color: #38516a; }
.boundary { background: #102a43; }
footer { border-color: #38516a; }
}
</style>
</head>
<body>
<header>
<h1>LineageWeave</h1>
<p>Evidence-bound lineage reconstruction and branching history for scattered enterprise records.</p>
</header>
<main>
<p>Use LineageWeave when related records do not carry reliable explicit cross-record links and you need to inspect how events, claims, posts, and decisions relate over time without turning inferred lineage into source-system truth.</p>
<nav class="actions" aria-label="LineageWeave public navigation">
<a href="ontology/">Ontology</a>
<a href="https://github.com/ContextualWisdomLab/LineageWeave">Repository</a>
<a href="https://github.com/ContextualWisdomLab/LineageWeave/blob/main/README.md">README</a>
<a href="https://github.com/ContextualWisdomLab/LineageWeave/blob/main/ARCHITECTURE.md">Architecture</a>
<a href="https://github.com/ContextualWisdomLab/LineageWeave/releases">Releases</a>
<a href="https://deepwiki.com/ContextualWisdomLab/LineageWeave">Ask DeepWiki</a>
</nav>
<section class="boundary" aria-labelledby="boundary-heading">
<h2 id="boundary-heading">Evidence boundary</h2>
<p>Published source and release evidence remain authoritative. Lineage inference, retrieval, and model-assisted adjudication do not silently become source-system truth, authentication authority, tenant authority, measurement authority, or provider-routing authority.</p>
</section>
</main>
<footer><p>ContextualWisdomLab / LineageWeave</p></footer>
</body>
</html>
30 changes: 0 additions & 30 deletions docs/index.md

This file was deleted.

5 changes: 5 additions & 0 deletions scripts/publish_ontology_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
PROV_PROFILE_RELATIVE_PATH = Path("docs/ontology/prov-o-support-profile.ttl")
COMPATIBILITY_RELATIVE_PATH = Path("docs/ontology/namespace-compatibility.ttl")
SHAPES_RELATIVE_PATH = Path("docs/ontology/lineageweave-kg-shapes.ttl")
LANDING_RELATIVE_PATH = Path("docs/index.html")
#: ADR 0207: the repository-case namespace is canonical and the
#: lowercase form is the deprecated compatibility vocabulary.
CANONICAL_NAMESPACE = "https://contextualwisdomlab.github.io/LineageWeave/ontology#"
Expand Down Expand Up @@ -217,6 +218,7 @@ def publish_site(repository_root: Path, output_dir: Path) -> None:
profile = root / PROV_PROFILE_RELATIVE_PATH
compatibility_source = root / COMPATIBILITY_RELATIVE_PATH
shapes_source = root / SHAPES_RELATIVE_PATH
landing_source = root / LANDING_RELATIVE_PATH
if not source.is_file():
raise FileNotFoundError(f"ontology source is missing: {source}")
if not profile.is_file():
Expand All @@ -227,6 +229,8 @@ def publish_site(repository_root: Path, output_dir: Path) -> None:
)
if not shapes_source.is_file():
raise FileNotFoundError(f"SHACL shapes graph is missing: {shapes_source}")
if not landing_source.is_file():
raise FileNotFoundError(f"public landing source is missing: {landing_source}")

output = _validate_output_directory(output_dir, source, profile)
renderer = _load_renderer(root)
Expand All @@ -242,6 +246,7 @@ def publish_site(repository_root: Path, output_dir: Path) -> None:
shutil.rmtree(output)
try:
renderer.build_site(root, output)
shutil.copyfile(landing_source, output / "index.html")
except BaseException:
shutil.rmtree(output, ignore_errors=True)
raise
Expand Down
53 changes: 53 additions & 0 deletions tests/test_github_hosted_runner_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Repository-owned Linux workflows use an explicit supported hosted image."""

from pathlib import Path


ROOT = Path(__file__).resolve().parents[1]
EXPECTED_JOB_COUNTS = {
ROOT / ".github" / "workflows" / "tests.yml": 2,
ROOT / ".github" / "workflows" / "ontology-pages.yml": 2,
ROOT / ".github" / "workflows" / "prov-o-contract.yml": 1,
}


def _job_level_runners(path: Path) -> dict[str, str]:
"""Return literal ``jobs.<job>.runs-on`` declarations from one workflow.

GitHub workflow job keys are two spaces below the top-level ``jobs`` map and
their scalar ``runs-on`` declarations are four spaces below it. Restricting
extraction to those structural levels prevents comments, shell heredocs, and
unrelated strings from satisfying this repository contract without adding a
YAML parser solely for a CI-policy test.
"""
runners: dict[str, str] = {}
current_job: str | None = None
in_jobs = False

for raw_line in path.read_text(encoding="utf-8").splitlines():
if raw_line == "jobs:":
in_jobs = True
current_job = None
continue
if not in_jobs:
continue
if raw_line and not raw_line.startswith(" ") and not raw_line.startswith("#"):
break
if raw_line.startswith(" ") and not raw_line.startswith(" "):
stripped = raw_line.strip()
if stripped and not stripped.startswith("#") and stripped.endswith(":"):
current_job = stripped[:-1]
continue
if current_job is not None and raw_line.startswith(" runs-on:"):
value = raw_line.split(":", 1)[1].split("#", 1)[0].strip().strip("'\"")
runners[current_job] = value

return runners


def test_repository_workflows_pin_ubuntu_2404() -> None:
"""Require every actual repository-owned Linux job to pin Ubuntu 24.04."""
for path, expected_count in EXPECTED_JOB_COUNTS.items():
runners = _job_level_runners(path)
assert len(runners) == expected_count, (path, runners)
assert set(runners.values()) == {"ubuntu-24.04"}, (path, runners)
56 changes: 56 additions & 0 deletions tests/test_public_landing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Tests for the authoritative LineageWeave GitHub Pages landing source."""

from __future__ import annotations

import importlib.util
from pathlib import Path

import pytest

ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "scripts" / "publish_ontology_site.py"


def _load_publisher():
spec = importlib.util.spec_from_file_location("publish_ontology_site_landing", SCRIPT)
if spec is None or spec.loader is None:
raise AssertionError("ontology publisher could not be loaded")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


def test_publication_copies_the_authoritative_landing_with_durable_navigation(
tmp_path: Path,
) -> None:
publisher = _load_publisher()
output = tmp_path / "site"

publisher.publish_site(ROOT, output)

source = (ROOT / publisher.LANDING_RELATIVE_PATH).read_text(encoding="utf-8")
published = (output / "index.html").read_text(encoding="utf-8")
assert published == source
for target in (
'href="ontology/"',
'href="https://github.com/ContextualWisdomLab/LineageWeave"',
'href="https://github.com/ContextualWisdomLab/LineageWeave/blob/main/README.md"',
'href="https://github.com/ContextualWisdomLab/LineageWeave/blob/main/ARCHITECTURE.md"',
'href="https://github.com/ContextualWisdomLab/LineageWeave/releases"',
'href="https://deepwiki.com/ContextualWisdomLab/LineageWeave"',
):
assert target in published


def test_publication_fails_closed_without_the_authoritative_landing(
tmp_path: Path,
monkeypatch,
) -> None:
publisher = _load_publisher()
output = tmp_path / "site"
monkeypatch.setattr(publisher, "LANDING_RELATIVE_PATH", Path("docs/missing-index.html"))

with pytest.raises(FileNotFoundError, match="public landing source"):
publisher.publish_site(ROOT, output)

assert not output.exists()
3 changes: 3 additions & 0 deletions tests/test_publish_ontology_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def _repository_fixture(tmp_path: Path) -> Path:
"lineageweave-kg-shapes.ttl",
):
(ontology_dir / name).write_bytes((ROOT / "docs" / "ontology" / name).read_bytes())
(repository / "docs" / "index.html").write_bytes(
(ROOT / "docs" / "index.html").read_bytes()
)
(scripts_dir / "build_ontology_site.py").write_bytes(
(ROOT / "scripts" / "build_ontology_site.py").read_bytes()
)
Expand Down
Loading