semanticembed 0.7.4__tar.gz → 0.7.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.claude/skills/analyze/SKILL.md +1 -1
- semanticembed-0.7.5/.github/CODEOWNERS +5 -0
- semanticembed-0.7.5/.github/dependabot.yml +21 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.github/workflows/ci.yml +11 -4
- semanticembed-0.7.5/.github/workflows/corpus.yml +42 -0
- semanticembed-0.7.5/.github/workflows/jev-drift.yml +40 -0
- semanticembed-0.7.5/.github/workflows/leak-guard.yml +88 -0
- semanticembed-0.7.5/.github/workflows/publish.yml +112 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/CHANGELOG.md +66 -2
- {semanticembed-0.7.4 → semanticembed-0.7.5}/PKG-INFO +54 -24
- {semanticembed-0.7.4 → semanticembed-0.7.5}/README.md +50 -20
- semanticembed-0.7.5/corpus/manifest.json +408 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/api_reference.md +24 -6
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/dimensions.md +5 -6
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/getting_started.md +18 -11
- semanticembed-0.7.5/docs/jev.md +122 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/output_format.md +1 -1
- semanticembed-0.7.5/docs/scoring_gaps.md +52 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/validation_methodology.md +13 -18
- {semanticembed-0.7.4 → semanticembed-0.7.5}/pyproject.toml +5 -3
- semanticembed-0.7.5/scripts/corpus_score.py +243 -0
- semanticembed-0.7.5/scripts/jev/canary_baseline.json +173 -0
- semanticembed-0.7.5/scripts/jev/canary_cases.json +54 -0
- semanticembed-0.7.5/scripts/jev/drift_canary.py +160 -0
- semanticembed-0.7.5/scripts/jev/edge_audit.py +193 -0
- semanticembed-0.7.5/scripts/jev/jev_client.py +108 -0
- semanticembed-0.7.5/scripts/jev/leak_guard.py +280 -0
- semanticembed-0.7.5/scripts/jev/questions.py +135 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/skill/SKILL.md +0 -1
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/__init__.py +1 -1
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/agent/README.md +1 -1
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/agent/agent.py +61 -17
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/client.py +1 -1
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/explain.py +1 -1
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/extract.py +1177 -167
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/find_edges.py +154 -3
- semanticembed-0.7.5/tests/conftest.py +15 -0
- semanticembed-0.7.5/tests/fixtures/crew_decorator/config/tasks.yaml +7 -0
- semanticembed-0.7.5/tests/fixtures/crew_decorator/crew.py +36 -0
- semanticembed-0.7.5/tests/fixtures/langgraph_command.py +42 -0
- semanticembed-0.7.5/tests/test_agent_isolation.py +128 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_client.py +42 -0
- semanticembed-0.7.5/tests/test_corpus_score.py +59 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_extract.py +24 -0
- semanticembed-0.7.5/tests/test_extract_gaps.py +319 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_extract_iac.py +22 -2
- semanticembed-0.7.5/tests/test_extract_ported.py +181 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_extract_regressions.py +24 -0
- semanticembed-0.7.5/tests/test_jev_scripts.py +212 -0
- semanticembed-0.7.5/tests/test_security_paths.py +189 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_skill.py +5 -4
- semanticembed-0.7.5/tests/test_skill_permissions.py +33 -0
- semanticembed-0.7.4/.github/workflows/publish.yml +0 -51
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/.gitignore +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/CODE_OF_CONDUCT.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/CONTRIBUTING.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/LICENSE +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/LICENSE-FAQ.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/SECURITY.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/input_format.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/docs/license_keys.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/README.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/ai_agent_pipeline.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/autogen_codereview.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/cicd_pipeline.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/crewai_content_pipeline.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/google_online_boutique.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/langgraph_research_agent.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/react/README.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/react/RadarChart.tsx +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/react/RiskTable.tsx +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/react/TopologySummary.tsx +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/react/useSemanticEmbed.ts +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/sample_pipeline.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/examples/weaveworks_sock_shop.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/.gitignore +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/DEPLOY.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/README.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/build.sh +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/autogen_codereview.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/autogen_codereview_after.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/boutique.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/boutique_after.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/crewai_content.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/crewai_content_after.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/langgraph_research.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/examples/langgraph_research_after.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/requirements.txt +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/smoke_test_phase_b.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/huggingface/smoke_test_phase_c.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/01_quickstart.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/02_dimensions.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/03_drift_detection.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/04_bring_your_own.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/05_ai_agent_pipelines.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/06_cicd_pipelines.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/07_opentelemetry.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/08_qwen_compression.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/09_quantum_reachability.ipynb +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/notebooks/qwen_compression_cookbook.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/skill/SETUP.md +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/skill/analyze.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/agent/__init__.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/agent/__main__.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/agent/gemini_agent.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/dedupe.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/exceptions.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/live.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/src/semanticembed/models.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/__init__.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/autogen_app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/cdk_app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/crewai_app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/docker-compose.yml +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/langgraph_app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/pulumi_app.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/stack.yaml +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/trace_jaeger.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/trace_otlp.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/fixtures/trace_zipkin.json +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_aclient.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_dedupe.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_extract_ai.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_extract_otel.py +0 -0
- {semanticembed-0.7.4 → semanticembed-0.7.5}/tests/test_live.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: analyze
|
|
3
3
|
description: Scan a repo for infrastructure files (docker-compose, k8s, terraform, GitHub Actions), extract edges, and run 6D structural risk analysis via SemanticEmbed.
|
|
4
|
-
allowed-tools:
|
|
4
|
+
allowed-tools: Read Glob
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# /analyze — Structural Risk Analysis
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Weekly update PRs for the pinned GitHub Actions and the Python dependencies.
|
|
2
|
+
version: 2
|
|
3
|
+
updates:
|
|
4
|
+
- package-ecosystem: github-actions
|
|
5
|
+
directory: /
|
|
6
|
+
schedule:
|
|
7
|
+
interval: weekly
|
|
8
|
+
groups:
|
|
9
|
+
actions:
|
|
10
|
+
patterns: ["*"]
|
|
11
|
+
- package-ecosystem: pip
|
|
12
|
+
directory: /
|
|
13
|
+
schedule:
|
|
14
|
+
interval: weekly
|
|
15
|
+
groups:
|
|
16
|
+
python:
|
|
17
|
+
patterns: ["*"]
|
|
18
|
+
- package-ecosystem: pip
|
|
19
|
+
directory: /huggingface
|
|
20
|
+
schedule:
|
|
21
|
+
interval: weekly
|
|
@@ -6,6 +6,9 @@ on:
|
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [main]
|
|
8
8
|
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
9
12
|
jobs:
|
|
10
13
|
test:
|
|
11
14
|
name: Test (${{ matrix.python-version }} on ${{ matrix.os }})
|
|
@@ -23,10 +26,12 @@ jobs:
|
|
|
23
26
|
python-version: "3.12"
|
|
24
27
|
|
|
25
28
|
steps:
|
|
26
|
-
- uses: actions/checkout@v4
|
|
29
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
27
32
|
|
|
28
33
|
- name: Set up Python ${{ matrix.python-version }}
|
|
29
|
-
uses: actions/setup-python@v5
|
|
34
|
+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
30
35
|
with:
|
|
31
36
|
python-version: ${{ matrix.python-version }}
|
|
32
37
|
cache: pip
|
|
@@ -43,9 +48,11 @@ jobs:
|
|
|
43
48
|
name: Build wheel + sdist
|
|
44
49
|
runs-on: ubuntu-latest
|
|
45
50
|
steps:
|
|
46
|
-
- uses: actions/checkout@v4
|
|
51
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
52
|
+
with:
|
|
53
|
+
persist-credentials: false
|
|
47
54
|
|
|
48
|
-
- uses: actions/setup-python@v5
|
|
55
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
49
56
|
with:
|
|
50
57
|
python-version: "3.12"
|
|
51
58
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Corpus
|
|
2
|
+
|
|
3
|
+
# Manual only. Cloning the pinned public repos is not part of every PR.
|
|
4
|
+
on:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
score:
|
|
12
|
+
name: Score pinned corpus
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment: jev # only jobs in this environment can read TYPESAFE_API_KEY
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
17
|
+
with:
|
|
18
|
+
persist-credentials: false
|
|
19
|
+
|
|
20
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Install
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e '.[dev,extract]'
|
|
28
|
+
|
|
29
|
+
- name: Score tuning and held-out extraction
|
|
30
|
+
run: python scripts/corpus_score.py --split all
|
|
31
|
+
|
|
32
|
+
# Report only: Jev judges every extracted edge, including edges that
|
|
33
|
+
# appear only at each repo's current HEAD. Skipped without the secret.
|
|
34
|
+
- name: Jev edge audit
|
|
35
|
+
env:
|
|
36
|
+
TYPESAFE_API_KEY: ${{ secrets.TYPESAFE_API_KEY }}
|
|
37
|
+
run: |
|
|
38
|
+
if [ -z "$TYPESAFE_API_KEY" ]; then
|
|
39
|
+
echo "::notice::TYPESAFE_API_KEY is not set; the Jev edge audit was not run."
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
python scripts/jev/edge_audit.py --log edge_audit_log.jsonl
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Jev drift
|
|
2
|
+
|
|
3
|
+
# Weekly check that the Jev model behind the leak guard still answers the
|
|
4
|
+
# fixed cases in scripts/jev/canary_cases.json the way it did when the
|
|
5
|
+
# guard was measured (scripts/jev/canary_baseline.json). Also reports, without
|
|
6
|
+
# failing, how the moving alias jev-latest answers, so a new model release
|
|
7
|
+
# shows up before the pinned version is changed.
|
|
8
|
+
#
|
|
9
|
+
# Needs the secret TYPESAFE_API_KEY in the `jev` environment. About 48 requests a run.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
schedule:
|
|
13
|
+
- cron: "17 6 * * 1"
|
|
14
|
+
workflow_dispatch:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
drift:
|
|
21
|
+
name: Compare with baseline
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
environment: jev # only jobs in this environment can read TYPESAFE_API_KEY
|
|
24
|
+
timeout-minutes: 10
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
27
|
+
with:
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
|
|
30
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.12"
|
|
33
|
+
|
|
34
|
+
- name: Install
|
|
35
|
+
run: python -m pip install "httpx==0.28.1"
|
|
36
|
+
|
|
37
|
+
- name: Run the drift check
|
|
38
|
+
env:
|
|
39
|
+
TYPESAFE_API_KEY: ${{ secrets.TYPESAFE_API_KEY }}
|
|
40
|
+
run: python -I scripts/jev/drift_canary.py --also jev-latest
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
name: Leak guard
|
|
2
|
+
|
|
3
|
+
# Checks the lines a pull request adds for internals of the hosted service:
|
|
4
|
+
# a risk flag's cutoff, the steps that compute a value, how the input graph
|
|
5
|
+
# is changed before scoring, or how ties are broken. Uses TypeSafe's Jev
|
|
6
|
+
# model (scripts/jev/leak_guard.py, measurements in docs/jev.md).
|
|
7
|
+
#
|
|
8
|
+
# Needs the secret TYPESAFE_API_KEY in the `jev` environment. Without it the check fails
|
|
9
|
+
# rather than passing unchecked. Pull requests from forks get no secrets, so
|
|
10
|
+
# they need a maintainer's review for this instead.
|
|
11
|
+
#
|
|
12
|
+
# The guard's code is taken from the base branch, never from the pull
|
|
13
|
+
# request, so a pull request cannot change what runs with the key.
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
pull_request:
|
|
17
|
+
branches: [main]
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
concurrency:
|
|
23
|
+
group: leak-guard-${{ github.event.pull_request.number }}
|
|
24
|
+
cancel-in-progress: true
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
leak-guard:
|
|
28
|
+
name: Check added lines
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment: jev # only jobs in this environment can read TYPESAFE_API_KEY
|
|
31
|
+
timeout-minutes: 15
|
|
32
|
+
steps:
|
|
33
|
+
- name: Check out the pull request (data only)
|
|
34
|
+
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
35
|
+
with:
|
|
36
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
path: pr
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
|
|
41
|
+
- name: Check out the guard from the base branch
|
|
42
|
+
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
43
|
+
with:
|
|
44
|
+
ref: ${{ github.event.pull_request.base.sha }}
|
|
45
|
+
path: trusted
|
|
46
|
+
persist-credentials: false
|
|
47
|
+
|
|
48
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
49
|
+
with:
|
|
50
|
+
python-version: "3.12"
|
|
51
|
+
|
|
52
|
+
- name: Install the guard's one dependency
|
|
53
|
+
run: python -m pip install "httpx==0.28.1"
|
|
54
|
+
|
|
55
|
+
- name: Run the leak guard
|
|
56
|
+
env:
|
|
57
|
+
TYPESAFE_API_KEY: ${{ secrets.TYPESAFE_API_KEY }}
|
|
58
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
59
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
|
60
|
+
FROM_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
|
61
|
+
ACTOR: ${{ github.event.pull_request.user.login }}
|
|
62
|
+
run: |
|
|
63
|
+
if [ ! -f trusted/scripts/jev/leak_guard.py ]; then
|
|
64
|
+
echo "::notice::The leak guard is not on the base branch yet. It checks pull requests once it is merged."
|
|
65
|
+
exit 0
|
|
66
|
+
fi
|
|
67
|
+
if [ -z "$TYPESAFE_API_KEY" ] && [ "$FROM_FORK" = "true" ]; then
|
|
68
|
+
echo "::error::Pull requests from forks get no secrets, so the leak guard cannot run. A maintainer must review the added lines."
|
|
69
|
+
exit 2
|
|
70
|
+
fi
|
|
71
|
+
if [ -z "$TYPESAFE_API_KEY" ] && [ "$ACTOR" = "dependabot[bot]" ]; then
|
|
72
|
+
echo "::notice::Dependabot pull requests get no repository secrets. Leak guard not run; review the version bumps by hand."
|
|
73
|
+
exit 0
|
|
74
|
+
fi
|
|
75
|
+
cd trusted
|
|
76
|
+
python -I scripts/jev/leak_guard.py --repo ../pr --base "$BASE_SHA" --head "$HEAD_SHA" \
|
|
77
|
+
--log ../leak_guard_log.jsonl --json-out ../leak_guard_results.json
|
|
78
|
+
|
|
79
|
+
- name: Keep the requests and answers
|
|
80
|
+
if: always()
|
|
81
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
82
|
+
with:
|
|
83
|
+
name: leak-guard-log
|
|
84
|
+
path: |
|
|
85
|
+
leak_guard_log.jsonl
|
|
86
|
+
leak_guard_results.json
|
|
87
|
+
if-no-files-found: ignore
|
|
88
|
+
retention-days: 30
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Runs on a tag push of the form `v*`: git tag v0.7.5 && git push origin v0.7.5
|
|
4
|
+
# Uses PyPI Trusted Publishing (OIDC), so no PyPI token is stored in GitHub.
|
|
5
|
+
#
|
|
6
|
+
# A release is published only when all of these hold:
|
|
7
|
+
# 1. the tagged commit is on main (a tag on an unreviewed branch is refused);
|
|
8
|
+
# 2. the tag matches pyproject.toml and semanticembed.__version__;
|
|
9
|
+
# 3. the full test suite passes on that commit;
|
|
10
|
+
# 4. someone approves the `pypi` environment. Set required reviewers in
|
|
11
|
+
# Settings -> Environments -> pypi, and restrict it to `v*` tags.
|
|
12
|
+
#
|
|
13
|
+
# One-time PyPI setup: pypi.org -> Account -> Publishing -> trusted publisher
|
|
14
|
+
# Project: semanticembed Owner: jmurray10 Repository: semanticembed-sdk
|
|
15
|
+
# Workflow: publish.yml Environment: pypi
|
|
16
|
+
#
|
|
17
|
+
# Actions are pinned to commit SHAs; Dependabot proposes updates.
|
|
18
|
+
|
|
19
|
+
on:
|
|
20
|
+
push:
|
|
21
|
+
tags:
|
|
22
|
+
- "v*"
|
|
23
|
+
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
|
|
27
|
+
concurrency:
|
|
28
|
+
group: publish
|
|
29
|
+
cancel-in-progress: false
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
verify:
|
|
33
|
+
name: Verify tag and run tests
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
37
|
+
with:
|
|
38
|
+
fetch-depth: 0
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
|
|
41
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.12"
|
|
44
|
+
|
|
45
|
+
- name: Tagged commit is on main
|
|
46
|
+
run: |
|
|
47
|
+
git fetch --no-tags origin main
|
|
48
|
+
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
|
|
49
|
+
echo "::error::Tag $GITHUB_REF_NAME points at a commit that is not on main"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
- name: Tag matches the package version
|
|
54
|
+
run: |
|
|
55
|
+
python - <<'EOF'
|
|
56
|
+
import os, pathlib, re, sys, tomllib
|
|
57
|
+
tag = os.environ["GITHUB_REF_NAME"].removeprefix("v")
|
|
58
|
+
pkg = tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"]
|
|
59
|
+
init = re.search(r"__version__\s*=\s*[\"']([^\"']+)",
|
|
60
|
+
pathlib.Path("src/semanticembed/__init__.py").read_text()).group(1)
|
|
61
|
+
if not tag == pkg == init:
|
|
62
|
+
sys.exit(f"::error::tag {tag}, pyproject.toml {pkg} and __version__ {init} must match")
|
|
63
|
+
print(f"version {tag}")
|
|
64
|
+
EOF
|
|
65
|
+
|
|
66
|
+
- name: Install
|
|
67
|
+
run: |
|
|
68
|
+
python -m pip install --upgrade pip
|
|
69
|
+
pip install -e '.[dev,extract]'
|
|
70
|
+
|
|
71
|
+
- name: Run pytest
|
|
72
|
+
run: pytest -q
|
|
73
|
+
|
|
74
|
+
build:
|
|
75
|
+
name: Build sdist + wheel
|
|
76
|
+
needs: verify
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
80
|
+
with:
|
|
81
|
+
persist-credentials: false
|
|
82
|
+
|
|
83
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
|
84
|
+
with:
|
|
85
|
+
python-version: "3.12"
|
|
86
|
+
|
|
87
|
+
- name: Build
|
|
88
|
+
run: |
|
|
89
|
+
python -m pip install --upgrade build twine
|
|
90
|
+
python -m build
|
|
91
|
+
python -m twine check dist/*
|
|
92
|
+
|
|
93
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
94
|
+
with:
|
|
95
|
+
name: dist
|
|
96
|
+
path: dist/
|
|
97
|
+
if-no-files-found: error
|
|
98
|
+
|
|
99
|
+
publish:
|
|
100
|
+
name: Publish
|
|
101
|
+
needs: build
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
environment: pypi
|
|
104
|
+
permissions:
|
|
105
|
+
id-token: write # trusted publishing; nothing else in this job can write
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
108
|
+
with:
|
|
109
|
+
name: dist
|
|
110
|
+
path: dist/
|
|
111
|
+
|
|
112
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
|
|
@@ -2,13 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the SemanticEmbed SDK.
|
|
4
4
|
|
|
5
|
+
## 0.7.5 — Security fixes, parser corrections
|
|
6
|
+
|
|
7
|
+
### Security
|
|
8
|
+
|
|
9
|
+
- **Agent no longer runs the scanned project's hooks.** `semanticembed-agent`
|
|
10
|
+
started the Claude Code CLI in your working directory with default
|
|
11
|
+
settings, so a cloned repo's `.claude/settings.json` hooks ran shell
|
|
12
|
+
commands with no prompt. The agent now loads no settings files, runs the
|
|
13
|
+
CLI in an empty temporary directory, and has no built-in tools (shell,
|
|
14
|
+
file read/write, web fetch). Requires `claude-agent-sdk>=0.1.60`; older
|
|
15
|
+
versions ignore `setting_sources=[]` and are refused at startup.
|
|
16
|
+
- **`extract.from_requirements`** follows `-r` only to files inside the
|
|
17
|
+
starting file's directory, after resolving symlinks. Lines of a file
|
|
18
|
+
outside it used to become node names sent to the API.
|
|
19
|
+
- **`find_edges()` LLM fallback** skips `node_modules`, `.venv`, `vendor`
|
|
20
|
+
and similar directories, skips files that resolve outside the scanned
|
|
21
|
+
path, and replaces secret-looking values with `[REDACTED]` before
|
|
22
|
+
sending file text to Anthropic or Google. README "What gets sent where"
|
|
23
|
+
now covers `find_edges()` and `explain()` / `ask()`.
|
|
24
|
+
- **Skills** no longer pre-approve shell commands.
|
|
25
|
+
- **Releases** publish only from a tag on `main` that matches the package
|
|
26
|
+
version, after the test suite passes, with approval on the `pypi`
|
|
27
|
+
environment. Workflow actions are pinned to commit SHAs; Dependabot is on.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **`extract.from_crewai`** reads `@CrewBase` / `@agent` / `@task` / `@crew`
|
|
32
|
+
crews: agent-to-task edges, the sequential task chain, YAML and inline
|
|
33
|
+
`context` dependencies, and `manager_agent` fan-out. crewAI-examples
|
|
34
|
+
`stock_analysis` goes from 0 to 7 edges and `surprise_trip` from 0 to 5.
|
|
35
|
+
- **`extract.from_langgraph`** reads `Command(goto=...)`,
|
|
36
|
+
`Command[Literal[...]]`, and `Send(...)`, and keeps a separate `START` /
|
|
37
|
+
`END` per `StateGraph`. A compiled subgraph mounted with `add_node`, or
|
|
38
|
+
invoked with `ainvoke` / `invoke` / `stream` / `astream`, is wired to the
|
|
39
|
+
caller. `open_deep_research` `deep_researcher.py` goes from 6 edges (three
|
|
40
|
+
graphs sharing one `START`) to 16.
|
|
41
|
+
- **`extract.from_terraform`** labels a resource `type.name` when its short
|
|
42
|
+
name is shared (`aws_vpc.this` vs `aws_internet_gateway.this`). On
|
|
43
|
+
terraform-aws-vpc this is 55 edges / 35 nodes with a `this` hub, then
|
|
44
|
+
119 edges / 96 nodes with no bare `this` once module blocks are included.
|
|
45
|
+
Correct keys put real modules over the free-tier 50-node cap.
|
|
46
|
+
- **`extract.from_directory`** takes `include` and `exclude` source labels.
|
|
47
|
+
The default still parses every recognized source, including GitHub Actions
|
|
48
|
+
and Python imports.
|
|
49
|
+
- **Kubernetes names that collide** (`Service` and `Deployment` both called
|
|
50
|
+
`frontend`) are labeled `Kind/name`. Same-name pairs used to become
|
|
51
|
+
self-loops and disappear. `GoogleCloudPlatform/microservices-demo`
|
|
52
|
+
`c7cb6d5` `release/` is 28 edges after that, not 17.
|
|
53
|
+
- **Pulumi / CDK kwargs** such as `vpc_security_group_ids=[group.id]` count
|
|
54
|
+
as a reference to `group`.
|
|
55
|
+
- **Python `from ._native import`** is resolved against the importing package.
|
|
56
|
+
- **Corpus check** (`corpus/manifest.json`, `scripts/corpus_score.py`):
|
|
57
|
+
held-out extraction precision 1.0 and recall 1.0 on 2026-11-04
|
|
58
|
+
(55/55 edges, 6 files). Tuning was 1.0 (59/59). The only pin behind
|
|
59
|
+
HEAD was this repo, and those labeled files did not change edges.
|
|
60
|
+
Hosted scoring notes are in `docs/scoring_gaps.md`. The 0.7.4 changelog line "vpc goes
|
|
61
|
+
from 2 to 56 edges" does not reproduce on vpc `b3abd6df`: the indexed-ref
|
|
62
|
+
parser before name disambiguation returned 55 edges. With module blocks
|
|
63
|
+
and brace-matched bodies, vpc `b3abd6df` is 119 edges / 96 nodes
|
|
64
|
+
(root `*.tf` files alone: 93 edges / 73 nodes). `pyproject.toml` and
|
|
65
|
+
`requirements.txt` are parsers. A `]` inside a requirement extra does
|
|
66
|
+
not end a multiline TOML array.
|
|
67
|
+
|
|
5
68
|
## 0.7.4 — Terraform count/for_each + Kubernetes auto-detect fixes
|
|
6
69
|
|
|
7
70
|
- **`extract.from_terraform`** now resolves `count` / `for_each`-indexed
|
|
8
71
|
references (`aws_subnet.this[0].id`, `aws_eip.nat[count.index].id`) — the
|
|
9
72
|
form real modules use almost universally. The ref regex previously matched
|
|
10
|
-
only `type.name.` and missed them.
|
|
11
|
-
|
|
73
|
+
only `type.name.` and missed them. The note below this release said
|
|
74
|
+
that went from 2 to 56 edges; a remeasure of vpc `b3abd6df` is under
|
|
75
|
+
Unreleased (119 edges / 96 nodes with the current parser).
|
|
12
76
|
- **`extract.from_directory`** now detects Kubernetes manifests by content
|
|
13
77
|
(`apiVersion` + `kind`) in any directory, not just conventional names like
|
|
14
78
|
`k8s/` / `manifests/`. Manifests under `release/` or `kubernetes-manifests/`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: semanticembed
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.5
|
|
4
4
|
Summary: 6D structural intelligence for directed graphs. Six numbers per node. Sub-millisecond.
|
|
5
5
|
Project-URL: Homepage, https://github.com/jmurray10/semanticembed-sdk
|
|
6
6
|
Project-URL: Documentation, https://github.com/jmurray10/semanticembed-sdk
|
|
@@ -22,13 +22,13 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
22
22
|
Requires-Python: >=3.9
|
|
23
23
|
Requires-Dist: httpx>=0.24
|
|
24
24
|
Provides-Extra: agent-claude
|
|
25
|
-
Requires-Dist: claude-agent-sdk; extra == 'agent-claude'
|
|
25
|
+
Requires-Dist: claude-agent-sdk>=0.1.60; extra == 'agent-claude'
|
|
26
26
|
Requires-Dist: pyyaml>=6.0; extra == 'agent-claude'
|
|
27
27
|
Provides-Extra: agent-gemini
|
|
28
28
|
Requires-Dist: google-genai; extra == 'agent-gemini'
|
|
29
29
|
Requires-Dist: pyyaml>=6.0; extra == 'agent-gemini'
|
|
30
30
|
Provides-Extra: all
|
|
31
|
-
Requires-Dist: claude-agent-sdk; extra == 'all'
|
|
31
|
+
Requires-Dist: claude-agent-sdk>=0.1.60; extra == 'all'
|
|
32
32
|
Requires-Dist: google-genai; extra == 'all'
|
|
33
33
|
Requires-Dist: pyyaml>=6.0; extra == 'all'
|
|
34
34
|
Provides-Extra: dev
|
|
@@ -63,7 +63,7 @@ SemanticEmbed computes a 6-dimensional structural encoding for every node in a d
|
|
|
63
63
|
> - **[Hugging Face Space](https://huggingface.co/spaces/jmurray10/semanticembed-agent-risk)** — zero-install. Paste a LangGraph / CrewAI / AutoGen file, get the encoding + risk findings.
|
|
64
64
|
> - **[Demo dashboard](https://semanticembed-dashboard.vercel.app/)** — interactive 6D explorer with 4 reference apps (sign-in required; click "Try Demo" on the login page for a no-account walkthrough).
|
|
65
65
|
|
|
66
|
-
> **
|
|
66
|
+
> **One private-environment blind test.** On one Dynatrace tenant (108 services, 569 topology-relevant incidents over 30 days), **79.6%** of those incidents (453/569) were on nodes the hosted scorer had flagged. That run is not reproducible from this repo: the matcher and the risk thresholds live in a private service. See [validation methodology](docs/validation_methodology.md). It is one tenant, not a general accuracy number.
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
@@ -72,10 +72,10 @@ SemanticEmbed computes a 6-dimensional structural encoding for every node in a d
|
|
|
72
72
|
Observability tools tell you **what broke**. SemanticEmbed tells you **what will break** — from topology alone.
|
|
73
73
|
|
|
74
74
|
- **No agents, no instrumentation** — just an edge list
|
|
75
|
-
- **Sub-millisecond server-side compute
|
|
75
|
+
- **Sub-millisecond server-side compute is not something this SDK can show.** `result.encoding_time_ms` is the HTTP round trip, not a kernel timer. The encode response has no separate compute-time field. From this environment on 2026-11-04 a 7-node graph returned in about 0.3–0.4 s, which is faster than the old "typically 0.5–2 s" line. A 100-node kernel time is not measurable on the free tier (the client refuses graphs over 50 nodes before the request).
|
|
76
76
|
- **Works on any directed graph** — AI agent pipelines, microservices, data workflows, CI/CD
|
|
77
77
|
- **Complementary structural axes** — six dimensions, each captures risk signals the others cannot
|
|
78
|
-
- **
|
|
78
|
+
- **16 deterministic edge parsers + 3 live connectors** — docker-compose, Kubernetes, GitHub Actions, Terraform, CloudFormation, CDK, Pulumi, Python imports, package.json, npm workspaces, pyproject.toml, requirements.txt, OTel JSON, LangGraph, CrewAI, AutoGen; plus Dynatrace, Honeycomb, and Datadog clients
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -91,39 +91,63 @@ pip install 'semanticembed[agent-claude]' # adds Claude agent CLI
|
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
|
94
|
-
## Quick Start
|
|
94
|
+
## Quick Start
|
|
95
|
+
|
|
96
|
+
`from_directory` discovers edges. `encode` sends the edge list to the hosted API. Risk text is produced on the server; this package only prints it.
|
|
97
|
+
|
|
98
|
+
The block below is the report the API returned on **2026-11-04** for this edge list. If the server scorer changes, the words change. It is not a fixture baked into the client.
|
|
95
99
|
|
|
96
100
|
```python
|
|
97
101
|
import semanticembed as se
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
edges = [
|
|
104
|
+
("frontend", "api-gateway"),
|
|
105
|
+
("api-gateway", "order-service"),
|
|
106
|
+
("api-gateway", "user-service"),
|
|
107
|
+
("order-service", "payment-service"),
|
|
108
|
+
("order-service", "inventory-service"),
|
|
109
|
+
("payment-service", "database"),
|
|
110
|
+
]
|
|
106
111
|
result = se.encode(edges)
|
|
107
|
-
print(result.table)
|
|
108
112
|
print(se.report(result))
|
|
109
113
|
```
|
|
110
114
|
|
|
111
|
-
Output:
|
|
115
|
+
Output (hosted API, 2026-11-04):
|
|
112
116
|
|
|
113
117
|
```
|
|
114
118
|
STRUCTURAL RISK REPORT
|
|
115
119
|
======================
|
|
116
120
|
|
|
117
|
-
|
|
118
|
-
-
|
|
121
|
+
SINGLE POINT OF FAILURE:
|
|
122
|
+
- order-service | order-service has high structural criticality (0.122) with limited lateral redundancy (independence=0.00). Failure here impacts 6 transitive path pairs.
|
|
123
|
+
- api-gateway | api-gateway has high structural criticality (0.102) with limited lateral redundancy (independence=0.50). Failure here impacts 5 transitive path pairs.
|
|
119
124
|
|
|
120
|
-
|
|
121
|
-
-
|
|
125
|
+
MONITORING GAP CANDIDATE:
|
|
126
|
+
- order-service | order-service has high criticality (0.122) but sits at depth 0.50, not at the service mesh edge. Likely missing from edge-level observability.
|
|
127
|
+
- api-gateway | api-gateway has high criticality (0.102) but sits at depth 0.25, not at the service mesh edge. Likely missing from edge-level observability.
|
|
128
|
+
- payment-service | payment-service has high criticality (0.061) but sits at depth 0.75, not at the service mesh edge. Likely missing from edge-level observability.
|
|
122
129
|
|
|
123
|
-
|
|
124
|
-
-
|
|
130
|
+
DEEP BOTTLENECK:
|
|
131
|
+
- order-service | order-service is a bottleneck deep in the pipeline (depth=0.50, criticality=0.122). Failures here are harder to diagnose from edge monitoring.
|
|
132
|
+
- payment-service | payment-service is a bottleneck deep in the pipeline (depth=0.75, criticality=0.061). Failures here are harder to diagnose from edge monitoring.
|
|
133
|
+
|
|
134
|
+
WHAT TO DO
|
|
135
|
+
----------
|
|
136
|
+
>> api-gateway, order-service: Add a redundant path or fallback service so this node is not the only option at its pipeline stage.
|
|
137
|
+
>> api-gateway, order-service, payment-service: Ensure this node has dedicated monitoring. It sits on critical paths but is not at the service edge, so it may be missing from your dashboards.
|
|
138
|
+
>> order-service, payment-service: Add health checks and timeouts. Deep bottlenecks are hard to diagnose from edge monitoring — ensure this node has dedicated alerting.
|
|
139
|
+
|
|
140
|
+
Total: 7 risks (5 critical, 2 warning, 0 info)
|
|
125
141
|
```
|
|
126
142
|
|
|
143
|
+
Directory scan is the same `encode` call after `edges, sources = se.extract.from_directory(".")`. The 16 parsers are docker-compose, Kubernetes, GitHub Actions, Terraform, CloudFormation, AWS CDK (Python), Pulumi (Python), Python imports, `package.json`, npm workspaces, `pyproject.toml`, `requirements.txt`, OpenTelemetry JSON, LangGraph, CrewAI, and AutoGen. The three live connectors are Dynatrace, Honeycomb, and Datadog; this check did not call those APIs.
|
|
144
|
+
|
|
145
|
+
**Held-out extraction, 2026-11-04.** Hand-labeled files. Micro precision **1.0**, recall **1.0** (55/55 edges, 6 files). Tuning was also 1.0 (59/59 edges, 13 files). Pinned SHAs are in [corpus/manifest.json](corpus/manifest.json). Re-run with `python scripts/corpus_score.py --split held-out`. The only pin that was behind HEAD was this repo (`a612cec` vs `4f1cec9`); the labeled files in it produced the same edges. `package.json` workspaces are covered by a unit test, not by a pinned monorepo.
|
|
146
|
+
|
|
147
|
+
Two held-out files sit in repos that also contain a tuning file (`crewAI-examples` recruitment crew, `pulumi/examples` S3 website). Those files were not used to edit the parsers.
|
|
148
|
+
|
|
149
|
+
What to expect from hosted scoring on the voting-app shape, identical twins, and cyclic LangGraph graphs is in [docs/scoring_gaps.md](docs/scoring_gaps.md). The client forwards the edge list unchanged; those outcomes come from the service, not from client bugs.
|
|
150
|
+
|
|
127
151
|
**Or try it without installing** — [open the Quickstart in Google Colab](https://colab.research.google.com/github/jmurray10/semanticembed-sdk/blob/main/notebooks/01_quickstart.ipynb).
|
|
128
152
|
|
|
129
153
|
---
|
|
@@ -228,6 +252,10 @@ edges = se.extract.from_github_actions(".github/workflows")
|
|
|
228
252
|
|
|
229
253
|
# From Terraform
|
|
230
254
|
edges = se.extract.from_terraform("infra/")
|
|
255
|
+
# Resource names that collide (`aws_vpc.this` and `aws_internet_gateway.this`)
|
|
256
|
+
# are labeled `type.name`. On terraform-aws-modules/terraform-aws-vpc
|
|
257
|
+
# `b3abd6df` that is 119 edges and 96 nodes, over the free-tier cap.
|
|
258
|
+
# The root `*.tf` files alone are 73 nodes. A license is required to encode them.
|
|
231
259
|
|
|
232
260
|
# From CloudFormation (YAML or JSON)
|
|
233
261
|
edges = se.extract.from_cloudformation("template.yaml")
|
|
@@ -415,8 +443,10 @@ The agent has 7 tools: scan, extract (docker-compose, k8s, Python imports), enco
|
|
|
415
443
|
|
|
416
444
|
Be explicit about data egress before pointing the agent at private architecture:
|
|
417
445
|
|
|
418
|
-
- **Claude agent** (`semanticembed-agent` / `python -m semanticembed.agent`): the LLM
|
|
446
|
+
- **Claude agent** (`semanticembed-agent` / `python -m semanticembed.agent`): the LLM sees your prompts and what the SemanticEmbed tools return: edge lists (node names), which parsers found them, encoding results, and error messages. That goes to **Anthropic's API** and is governed by Anthropic's data-use policies. The agent has no built-in tools (no shell, file read, or web fetch), and it does not load `.claude/settings.json`, hooks, or `CLAUDE.md` from the project it scans. Requires `claude-agent-sdk>=0.1.60`.
|
|
419
447
|
- **Gemini agent** (`semanticembed-gemini-agent` / `python -m semanticembed.agent.gemini_agent`): same data flow, sent to **Google's API** instead.
|
|
448
|
+
- **`find_edges()` LLM fallback**: only when the deterministic scan finds no edges, it sends the text of compose, Kubernetes, Terraform, GitHub Actions, `package.json`, `pyproject.toml`, `Pipfile` and `requirements.txt` files (up to 250 KB) to **Anthropic** (`provider="claude"`) or **Google** (`provider="gemini"`). It skips `node_modules`, `.venv`, `vendor` and similar directories, skips files that resolve outside the scanned path, and replaces secret-looking values (keys, tokens, passwords, URL credentials, Kubernetes `Secret` data) with `[REDACTED]`. Redaction is pattern-based and can miss a secret.
|
|
449
|
+
- **`explain()` / `ask()`**: send the encoding result (node names, the six values per node, risk flags, graph size) and your question to the model you name: **OpenAI**, **Anthropic**, or a local **Ollama** server. No file contents.
|
|
420
450
|
- **Claude Code skill** (`skill/analyze.py`): runs **inside Claude Code** — uses the parent agent for any natural-language extraction, the SDK for the deterministic scan + encoding. No second LLM, no Ollama dependency.
|
|
421
451
|
- **Cloud `encode()` call**: only the **edge list** (node names, e.g. `["frontend", "auth"]`) goes to the SemanticEmbed Railway endpoint. File contents are never sent.
|
|
422
452
|
|