org-knowledge-layer 0.4.0__tar.gz → 0.4.1__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.
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.coverage +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/workflows/ci.yml +12 -0
- {org_knowledge_layer-0.4.0/ci → org_knowledge_layer-0.4.1/.github/workflows}/okl-verify.yml +34 -8
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CHANGELOG.md +27 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/PKG-INFO +27 -1
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/README.md +26 -0
- {org_knowledge_layer-0.4.0/src/okl/scaffold → org_knowledge_layer-0.4.1}/ci/okl-verify.yml +34 -8
- org_knowledge_layer-0.4.1/ci/review-agent.sh +133 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/pyproject.toml +1 -1
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/MANIFEST.md +8 -0
- org_knowledge_layer-0.4.1/src/okl/scaffold/ci/dependabot.yml +17 -0
- org_knowledge_layer-0.4.1/src/okl/scaffold/ci/method-gates.yml +74 -0
- {org_knowledge_layer-0.4.0/.github/workflows → org_knowledge_layer-0.4.1/src/okl/scaffold/ci}/okl-verify.yml +34 -8
- org_knowledge_layer-0.4.1/src/okl/scaffold/ci/review-agent.sh +133 -0
- org_knowledge_layer-0.4.1/src/okl/scaffold/claude/agents/architecture-reviewer.md +41 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold_cmd.py +5 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/tests/test_okl.py +44 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/tests/test_scaffold.py +89 -0
- org_knowledge_layer-0.4.0/src/okl/scaffold/ci/method-gates.yml +0 -32
- {org_knowledge_layer-0.4.0/src/okl/scaffold/claude → org_knowledge_layer-0.4.1/.claude}/agents/architecture-reviewer.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/hooks/stop-okl-encode.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/hooks/userpromptsubmit-okl-check.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/settings.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/dependabot.yml +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/pull_request_template.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/workflows/publish.yml +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.gitignore +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/AGENTS.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CLAUDE.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CONTRIBUTING.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/LICENSE +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/SECURITY.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/ci/check-diagram-figures.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/DEPLOY.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/ab-results-chart.png +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/ab-results-chart.svg +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/decisions/2026-07-17-flat-retrieval-until-scale.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/decisions/2026-07-21-subject-tags-controlled-vocabulary.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-how-it-works.excalidraw +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-how-it-works.svg +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-sixth-surface.excalidraw +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-sixth-surface.svg +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/01-memory-that-outlives-the-run.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/02-dont-let-a-step-grade-itself.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/03-enforcement-or-good-intentions.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/REPORT.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/ab_harness.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260829-2300.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260829-2315.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260830-0003.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260830-0148.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260901-0133.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260901-1238.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/briefed-userpromptsubmit-lint.yml +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/control-lint.yml +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/hook.log +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/service-record-500.log +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-briefed-pretooluse.txt +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-briefed-userpromptsubmit.txt +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-control.txt +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/tasks.jsonl +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-canon-size.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-diagram-pairs.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-doc-orphans.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-links.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-retractions.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-tombstones.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/run-gates.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/hooks/stop-okl-encode.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/hooks/userpromptsubmit-okl-check.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-canon.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-decisions.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-review-surfaces.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/frontend-canon.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-deeptime-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-enforcement-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-eval-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/rag-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/react-defects.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/__init__.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/__main__.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/bootstrap.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/cli.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/client.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/core.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/drift.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/mcp_server.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/check-rules.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/feature-spec.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/seed-from-codebase.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/seed-from-docs.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/rules/example-area.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/RECOMMENDED-COMPANIONS.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/encoding-loop/SKILL.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/verify-before-claiming/SKILL.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/cases.jsonl +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/run_evals.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-canon-size.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-diagram-pairs.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-doc-orphans.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-links.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-retractions.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-tombstones.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/run-gates.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/hooks.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/stop-okl-encode.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/userpromptsubmit-okl-check.sh +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/plugin/plugin.json +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/architecture.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/messaging.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/performance-and-data.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/security.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/geospatial/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/geospatial/rules/geospatial-ml.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/fastapi-backend.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/project-structure.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/rag-pipeline.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/react/README.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/react/rules/frontend.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/registries/RETRACTIONS.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/registries/tombstones.txt +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/root/CLAUDE.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/root/METHOD.md +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/seed.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/service.py +0 -0
- {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/store.py +0 -0
|
Binary file
|
|
@@ -78,6 +78,18 @@ jobs:
|
|
|
78
78
|
# key for organization-owned repositories, so it would break for anyone who forks
|
|
79
79
|
# this into an org. The binary has no such condition, and pinning the release keeps
|
|
80
80
|
# a new detection rule from retro-failing a branch that changed nothing.
|
|
81
|
+
# The reviewer okl ships, run on okl. It was listed as a review surface with nothing
|
|
82
|
+
# triggering it — the "enforcement surface that only runs on-demand runs never"
|
|
83
|
+
# failure this repo's own store names. Off unless REVIEW_CMD is set, so it costs
|
|
84
|
+
# nothing until someone decides it should.
|
|
85
|
+
- name: Architecture review (off unless REVIEW_CMD is set)
|
|
86
|
+
if: github.event_name == 'pull_request'
|
|
87
|
+
env:
|
|
88
|
+
REVIEW_CMD: ${{ vars.REVIEW_CMD }}
|
|
89
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
90
|
+
REVIEW_BASE_REF: origin/${{ github.base_ref }}
|
|
91
|
+
run: bash ci/review-agent.sh
|
|
92
|
+
|
|
81
93
|
- name: Secret scan — gitleaks
|
|
82
94
|
env:
|
|
83
95
|
GITLEAKS_VERSION: "8.30.1"
|
|
@@ -16,16 +16,45 @@ on:
|
|
|
16
16
|
push:
|
|
17
17
|
branches: [main]
|
|
18
18
|
|
|
19
|
+
# Least privilege: this workflow reads code and reports a status. It never writes.
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: okl-verify-${{ github.ref }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
defaults:
|
|
28
|
+
run:
|
|
29
|
+
# Without pipefail a run block continues past a failed segment of a pipeline, so a
|
|
30
|
+
# green step can hide a red command.
|
|
31
|
+
shell: bash -euo pipefail {0}
|
|
32
|
+
|
|
19
33
|
jobs:
|
|
20
34
|
okl-verify:
|
|
21
35
|
runs-on: ubuntu-latest
|
|
36
|
+
env:
|
|
37
|
+
# Set at job level so every okl command below resolves the shared layer from the
|
|
38
|
+
# environment. This replaces an `okl connect --token` step, which wrote the bearer
|
|
39
|
+
# token into .okl/config.json on the runner — needless, since the client reads both
|
|
40
|
+
# variables directly, and one more place for a credential to end up.
|
|
41
|
+
# Unset secrets leave these empty, and okl falls back to the repo-local store.
|
|
42
|
+
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
43
|
+
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
22
44
|
steps:
|
|
23
|
-
|
|
45
|
+
# Actions are pinned to a commit SHA: a tag is mutable, so `@v5` is an unpinned
|
|
46
|
+
# dependency with access to your runner. If you copy this file into your own repo,
|
|
47
|
+
# add a .github/dependabot.yml with the `github-actions` ecosystem so these pins get
|
|
48
|
+
# security updates — a pin with no update path goes stale and that is its own risk.
|
|
49
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
24
50
|
with:
|
|
25
|
-
fetch-depth: 0 # drift needs history: it compares file
|
|
26
|
-
|
|
51
|
+
fetch-depth: 0 # drift needs history: it compares governed-file commits vs verified_at
|
|
52
|
+
persist-credentials: false # this job never pushes
|
|
53
|
+
|
|
54
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
27
55
|
with:
|
|
28
56
|
python-version: "3.13"
|
|
57
|
+
|
|
29
58
|
- name: Install okl
|
|
30
59
|
# Detect by the package source, not the distribution name: the name changed once
|
|
31
60
|
# (PyPI rejects "okl" as confusable) and a name-based check silently broke with it.
|
|
@@ -36,13 +65,10 @@ jobs:
|
|
|
36
65
|
pip install org-knowledge-layer
|
|
37
66
|
fi
|
|
38
67
|
|
|
39
|
-
- name:
|
|
40
|
-
env:
|
|
41
|
-
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
42
|
-
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
68
|
+
- name: Report which store the gate will run against
|
|
43
69
|
run: |
|
|
44
70
|
if [ -n "${OKL_SERVICE_URL:-}" ]; then
|
|
45
|
-
|
|
71
|
+
echo "verifying against the shared layer at $OKL_SERVICE_URL"
|
|
46
72
|
else
|
|
47
73
|
echo "no OKL_SERVICE_URL secret — verifying against the repo-local store"
|
|
48
74
|
fi
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Security — affects the CI workflow already in your repo
|
|
6
|
+
|
|
7
|
+
- **The shipped CI verifier no longer writes your bearer token to disk.** It ran
|
|
8
|
+
`okl connect --token`, which persisted `OKL_TOKEN` into `.okl/config.json` on the runner
|
|
9
|
+
for no reason: the client reads `OKL_SERVICE_URL` and `OKL_TOKEN` from the environment
|
|
10
|
+
directly, so setting them at job level does the same work with the credential never
|
|
11
|
+
touching the filesystem. Re-run `okl init` (or `okl scaffold`) to pick up the new file.
|
|
12
|
+
- **Both shipped workflows are hardened.** `okl-verify.yml` and `method-gates.yml` now
|
|
13
|
+
declare least-privilege `permissions`, a concurrency group, `pipefail`, and
|
|
14
|
+
`persist-credentials: false`, and pin their actions to commit SHAs rather than mutable
|
|
15
|
+
tags. They satisfied none of that before.
|
|
16
|
+
- `.github/dependabot.yml` ships with the kit, because pinning to a SHA without an update
|
|
17
|
+
path is how a repo ends up on a two-year-old action and calls it hardening.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **Opt-in architecture review in CI.** `ci/review-agent.sh` runs the reviewer over a PR
|
|
22
|
+
diff and fails on must-fix findings. **Off unless you set the `REVIEW_CMD` repository
|
|
23
|
+
variable** to a CLI that reads a prompt on stdin — `claude -p` (authenticates with an
|
|
24
|
+
existing Claude Code login, no separate API key), `ollama run <model>` (local, free), or
|
|
25
|
+
any other. Unset, it prints one line and passes. It is the only gate in the kit that
|
|
26
|
+
calls a model, which is why it is the only one that is opt-in. Documented in the README
|
|
27
|
+
and the kit manifest.
|
|
28
|
+
|
|
29
|
+
|
|
3
30
|
## 0.4.0
|
|
4
31
|
|
|
5
32
|
### Behaviour changes worth reading before upgrading
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: org-knowledge-layer
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Org Knowledge Layer — an installable sixth surface that carries encoded engineering lessons across repos.
|
|
5
5
|
Author: Joshua Dell
|
|
6
6
|
License: MIT
|
|
@@ -358,6 +358,32 @@ To remove okl from a repo entirely, delete `.okl/`, the two hook scripts and the
|
|
|
358
358
|
in `.claude/settings.json`, and `.github/workflows/okl-verify.yml`. Nothing else was
|
|
359
359
|
written, and nothing outside that repo was touched.
|
|
360
360
|
|
|
361
|
+
### Architecture review in CI (off by default)
|
|
362
|
+
|
|
363
|
+
The kit ships a reviewer that reads a PR diff against your encoded rules and fails the
|
|
364
|
+
build on a must-fix finding. It is **off unless you ask for it**, and it is not tied to any
|
|
365
|
+
vendor. Set the `REVIEW_CMD` repository variable to any CLI that reads a prompt on stdin:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
gh variable set REVIEW_CMD --body "claude -p --model sonnet" # your existing Claude Code login
|
|
369
|
+
gh variable set REVIEW_CMD --body "ollama run qwen2.5-coder" # local model, no API cost
|
|
370
|
+
gh variable set REVIEW_CMD --body "llm -m gpt-4o" # any other CLI
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Two things worth knowing:
|
|
374
|
+
|
|
375
|
+
- **`claude -p` needs no separate API key.** It authenticates with the Claude Code login you
|
|
376
|
+
already have, so if you use Claude Code there is nothing else to configure and no second
|
|
377
|
+
bill. Verified headless with `ANTHROPIC_API_KEY` unset.
|
|
378
|
+
- **Locally you do not need this at all.** The reviewer is a subagent
|
|
379
|
+
(`.claude/agents/architecture-reviewer.md`); ask your agent to run it on your changes and
|
|
380
|
+
it costs nothing beyond the session you are already in. The CI job exists for the case
|
|
381
|
+
where no human and no agent is in the loop — a PR nobody reviewed.
|
|
382
|
+
|
|
383
|
+
Unset, the step prints one line saying it is off and exits 0. Every other gate in the kit is
|
|
384
|
+
deterministic and free; this is the only one that calls a model, which is why it is the only
|
|
385
|
+
one that is opt-in.
|
|
386
|
+
|
|
361
387
|
## Wire a repo
|
|
362
388
|
|
|
363
389
|
```bash
|
|
@@ -324,6 +324,32 @@ To remove okl from a repo entirely, delete `.okl/`, the two hook scripts and the
|
|
|
324
324
|
in `.claude/settings.json`, and `.github/workflows/okl-verify.yml`. Nothing else was
|
|
325
325
|
written, and nothing outside that repo was touched.
|
|
326
326
|
|
|
327
|
+
### Architecture review in CI (off by default)
|
|
328
|
+
|
|
329
|
+
The kit ships a reviewer that reads a PR diff against your encoded rules and fails the
|
|
330
|
+
build on a must-fix finding. It is **off unless you ask for it**, and it is not tied to any
|
|
331
|
+
vendor. Set the `REVIEW_CMD` repository variable to any CLI that reads a prompt on stdin:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
gh variable set REVIEW_CMD --body "claude -p --model sonnet" # your existing Claude Code login
|
|
335
|
+
gh variable set REVIEW_CMD --body "ollama run qwen2.5-coder" # local model, no API cost
|
|
336
|
+
gh variable set REVIEW_CMD --body "llm -m gpt-4o" # any other CLI
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Two things worth knowing:
|
|
340
|
+
|
|
341
|
+
- **`claude -p` needs no separate API key.** It authenticates with the Claude Code login you
|
|
342
|
+
already have, so if you use Claude Code there is nothing else to configure and no second
|
|
343
|
+
bill. Verified headless with `ANTHROPIC_API_KEY` unset.
|
|
344
|
+
- **Locally you do not need this at all.** The reviewer is a subagent
|
|
345
|
+
(`.claude/agents/architecture-reviewer.md`); ask your agent to run it on your changes and
|
|
346
|
+
it costs nothing beyond the session you are already in. The CI job exists for the case
|
|
347
|
+
where no human and no agent is in the loop — a PR nobody reviewed.
|
|
348
|
+
|
|
349
|
+
Unset, the step prints one line saying it is off and exits 0. Every other gate in the kit is
|
|
350
|
+
deterministic and free; this is the only one that calls a model, which is why it is the only
|
|
351
|
+
one that is opt-in.
|
|
352
|
+
|
|
327
353
|
## Wire a repo
|
|
328
354
|
|
|
329
355
|
```bash
|
|
@@ -16,16 +16,45 @@ on:
|
|
|
16
16
|
push:
|
|
17
17
|
branches: [main]
|
|
18
18
|
|
|
19
|
+
# Least privilege: this workflow reads code and reports a status. It never writes.
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: okl-verify-${{ github.ref }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
defaults:
|
|
28
|
+
run:
|
|
29
|
+
# Without pipefail a run block continues past a failed segment of a pipeline, so a
|
|
30
|
+
# green step can hide a red command.
|
|
31
|
+
shell: bash -euo pipefail {0}
|
|
32
|
+
|
|
19
33
|
jobs:
|
|
20
34
|
okl-verify:
|
|
21
35
|
runs-on: ubuntu-latest
|
|
36
|
+
env:
|
|
37
|
+
# Set at job level so every okl command below resolves the shared layer from the
|
|
38
|
+
# environment. This replaces an `okl connect --token` step, which wrote the bearer
|
|
39
|
+
# token into .okl/config.json on the runner — needless, since the client reads both
|
|
40
|
+
# variables directly, and one more place for a credential to end up.
|
|
41
|
+
# Unset secrets leave these empty, and okl falls back to the repo-local store.
|
|
42
|
+
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
43
|
+
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
22
44
|
steps:
|
|
23
|
-
|
|
45
|
+
# Actions are pinned to a commit SHA: a tag is mutable, so `@v5` is an unpinned
|
|
46
|
+
# dependency with access to your runner. If you copy this file into your own repo,
|
|
47
|
+
# add a .github/dependabot.yml with the `github-actions` ecosystem so these pins get
|
|
48
|
+
# security updates — a pin with no update path goes stale and that is its own risk.
|
|
49
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
24
50
|
with:
|
|
25
|
-
fetch-depth: 0 # drift needs history: it compares file
|
|
26
|
-
|
|
51
|
+
fetch-depth: 0 # drift needs history: it compares governed-file commits vs verified_at
|
|
52
|
+
persist-credentials: false # this job never pushes
|
|
53
|
+
|
|
54
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
27
55
|
with:
|
|
28
56
|
python-version: "3.13"
|
|
57
|
+
|
|
29
58
|
- name: Install okl
|
|
30
59
|
# Detect by the package source, not the distribution name: the name changed once
|
|
31
60
|
# (PyPI rejects "okl" as confusable) and a name-based check silently broke with it.
|
|
@@ -36,13 +65,10 @@ jobs:
|
|
|
36
65
|
pip install org-knowledge-layer
|
|
37
66
|
fi
|
|
38
67
|
|
|
39
|
-
- name:
|
|
40
|
-
env:
|
|
41
|
-
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
42
|
-
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
68
|
+
- name: Report which store the gate will run against
|
|
43
69
|
run: |
|
|
44
70
|
if [ -n "${OKL_SERVICE_URL:-}" ]; then
|
|
45
|
-
|
|
71
|
+
echo "verifying against the shared layer at $OKL_SERVICE_URL"
|
|
46
72
|
else
|
|
47
73
|
echo "no OKL_SERVICE_URL secret — verifying against the repo-local store"
|
|
48
74
|
fi
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# review-agent.sh — run the architecture reviewer over a PR diff, headless.
|
|
3
|
+
#
|
|
4
|
+
# Closes the gap the store names as "an enforcement surface that only runs on-demand runs
|
|
5
|
+
# never": .claude/agents/architecture-reviewer.md is listed as a review surface but nothing
|
|
6
|
+
# triggers it, so in practice it runs when someone remembers, which is never.
|
|
7
|
+
#
|
|
8
|
+
# OFF BY DEFAULT, AND VENDOR-NEUTRAL. Set REVIEW_CMD to any CLI that reads a prompt on
|
|
9
|
+
# stdin and writes the model's reply to stdout:
|
|
10
|
+
#
|
|
11
|
+
# REVIEW_CMD="claude -p --model sonnet"
|
|
12
|
+
# REVIEW_CMD="llm -m gpt-4o"
|
|
13
|
+
# REVIEW_CMD="ollama run qwen2.5-coder" # local, no API cost at all
|
|
14
|
+
#
|
|
15
|
+
# Unset, the step soft-passes and says how to switch it on. okl is harness-agnostic —
|
|
16
|
+
# hard-coding one vendor's CLI here would contradict that, and would hand every consumer
|
|
17
|
+
# an API bill they never asked for. This mirrors GENERATOR_CMD/JUDGE_CMD in evals/.
|
|
18
|
+
#
|
|
19
|
+
# Self-owned on purpose: no third-party review SaaS holds a token for your source, and the
|
|
20
|
+
# reviewer reads YOUR encoded rules (it calls `okl check` itself) rather than generic advice.
|
|
21
|
+
set -uo pipefail
|
|
22
|
+
cd "$(dirname "$0")/.."
|
|
23
|
+
|
|
24
|
+
# Located, not assumed: `okl scaffold --claude-dir` lets a repo name that directory
|
|
25
|
+
# something other than .claude, and a hard-coded path silently skips the review in exactly
|
|
26
|
+
# those repos — a gate that quietly does nothing is the failure this whole file exists to
|
|
27
|
+
# fix. AGENT_FILE overrides for anything unusual.
|
|
28
|
+
AGENT="${AGENT_FILE:-}"
|
|
29
|
+
if [ -z "$AGENT" ]; then
|
|
30
|
+
AGENT="$(find . -maxdepth 3 -path ./.git -prune -o \
|
|
31
|
+
-name architecture-reviewer.md -print 2>/dev/null | head -1)"
|
|
32
|
+
fi
|
|
33
|
+
BASE="${REVIEW_BASE_REF:-origin/main}"
|
|
34
|
+
|
|
35
|
+
if [ -z "${REVIEW_CMD:-}" ]; then
|
|
36
|
+
echo "review-agent: REVIEW_CMD not set — skipping (soft pass)."
|
|
37
|
+
echo " Set it to any CLI that takes a prompt on stdin to turn this into a blocking gate,"
|
|
38
|
+
echo " e.g. REVIEW_CMD=\"claude -p --model sonnet\" or REVIEW_CMD=\"ollama run qwen2.5-coder\"."
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
if [ ! -f "$AGENT" ]; then
|
|
42
|
+
echo "review-agent: no $AGENT — skipping (the reviewer ships with \`okl scaffold\`)."
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
# shellcheck disable=SC2086 — REVIEW_CMD is a command line, so word splitting is intended
|
|
46
|
+
if ! command -v ${REVIEW_CMD%% *} >/dev/null 2>&1; then
|
|
47
|
+
echo "review-agent: '${REVIEW_CMD%% *}' from REVIEW_CMD is not on PATH — skipping (soft pass)." >&2
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
diff_text="$(git diff "$BASE"...HEAD 2>/dev/null)"
|
|
52
|
+
if [ -z "$diff_text" ]; then
|
|
53
|
+
echo "review-agent: no diff against $BASE — nothing to review."
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Truncate: a very large diff would blow the context budget and produce a worse review than
|
|
58
|
+
# a focused one. Reviewing the first N lines and saying so beats silently reviewing a
|
|
59
|
+
# truncated diff as though it were whole.
|
|
60
|
+
max_lines=4000
|
|
61
|
+
total_lines=$(printf '%s' "$diff_text" | wc -l | tr -d ' ')
|
|
62
|
+
if [ "$total_lines" -gt "$max_lines" ]; then
|
|
63
|
+
diff_text="$(printf '%s' "$diff_text" | head -n "$max_lines")"
|
|
64
|
+
echo "review-agent: diff is $total_lines lines; reviewing the first $max_lines."
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# The checklist lives in the agent file — one source of truth for the rules. Only the OUTPUT
|
|
68
|
+
# CONTRACT is supplied here, because the agent is written for interactive use and returns
|
|
69
|
+
# prose, which CI cannot act on.
|
|
70
|
+
prompt="$(cat <<EOF
|
|
71
|
+
You are the architecture reviewer defined below. Apply its checklist to the diff.
|
|
72
|
+
|
|
73
|
+
$(cat "$AGENT")
|
|
74
|
+
|
|
75
|
+
--- DIFF UNDER REVIEW ---
|
|
76
|
+
$diff_text
|
|
77
|
+
--- END DIFF ---
|
|
78
|
+
|
|
79
|
+
Reply with STRICT JSON and nothing else:
|
|
80
|
+
{"findings":[{"severity":"must-fix|consider","file":"path","line":0,"rule":"which checklist item","finding":"one sentence"}]}
|
|
81
|
+
|
|
82
|
+
Rules for your reply:
|
|
83
|
+
- "must-fix" is reserved for a violation of an encoded rule: a restated retraction, a
|
|
84
|
+
resurrected tombstoned identifier, a speculative abstraction, an assert-from-memory claim.
|
|
85
|
+
Style preferences and suggestions are "consider".
|
|
86
|
+
- Only report what this diff introduces. Pre-existing issues are out of scope.
|
|
87
|
+
- An empty findings list is a valid and common answer. Do not invent findings to seem useful.
|
|
88
|
+
EOF
|
|
89
|
+
)"
|
|
90
|
+
|
|
91
|
+
echo "review-agent: reviewing $(printf '%s' "$diff_text" | wc -l | tr -d ' ') lines of diff against $BASE"
|
|
92
|
+
# CLEAN ROOM. Run the reviewer from a temp directory, never the repo. If REVIEW_CMD is a
|
|
93
|
+
# coding agent, this repo's own hooks would otherwise fire on it: the UserPromptSubmit hook
|
|
94
|
+
# injects a briefing into the review, and the Stop hook answers instead of the reviewer.
|
|
95
|
+
# Reproduced while verifying this script — a smoke call in the repo cwd came back answering
|
|
96
|
+
# the Stop hook rather than the question, which is the same failure evals/ documents.
|
|
97
|
+
clean="$(mktemp -d)"
|
|
98
|
+
raw="$(cd "$clean" && printf '%s' "$prompt" | $REVIEW_CMD 2>/dev/null)"
|
|
99
|
+
rmdir "$clean" 2>/dev/null || true
|
|
100
|
+
|
|
101
|
+
# Strip any markdown fence the model adds around the JSON.
|
|
102
|
+
json="$(printf '%s' "$raw" | sed -e 's/^```json//' -e 's/^```//' -e '/^```$/d')"
|
|
103
|
+
|
|
104
|
+
if ! printf '%s' "$json" | python3 -c "import json,sys; json.load(sys.stdin)" 2>/dev/null; then
|
|
105
|
+
# Fail OPEN on an unparseable reply, loudly. A reviewer that cannot be understood has not
|
|
106
|
+
# found anything; blocking every merge on a malformed model response would train people to
|
|
107
|
+
# bypass the gate, which is worse than the gate not firing.
|
|
108
|
+
echo "review-agent: could not parse the reviewer's reply as JSON — not blocking." >&2
|
|
109
|
+
printf '%s\n' "$raw" | head -20 >&2
|
|
110
|
+
exit 0
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
printf '%s' "$json" | python3 -c '
|
|
114
|
+
import json, sys
|
|
115
|
+
|
|
116
|
+
# %-formatting rather than f-strings: this is embedded in a shell single-quoted string, so
|
|
117
|
+
# the keys need double quotes, and a backslash inside an f-string EXPRESSION is a SyntaxError
|
|
118
|
+
# before Python 3.12 — which this must survive, since it runs on whatever interpreter the
|
|
119
|
+
# consumer has. The first version hit exactly that and exited 1 on every run. A gate that
|
|
120
|
+
# always blocks looks identical to a gate that works until someone notices nothing has ever
|
|
121
|
+
# passed it.
|
|
122
|
+
findings = json.load(sys.stdin).get("findings", [])
|
|
123
|
+
must = [f for f in findings if f.get("severity") == "must-fix"]
|
|
124
|
+
for f in findings:
|
|
125
|
+
mark = "MUST-FIX" if f.get("severity") == "must-fix" else "consider"
|
|
126
|
+
print(" [%s] %s:%s %s" % (mark, f.get("file"), f.get("line"), f.get("rule")))
|
|
127
|
+
print(" %s" % f.get("finding"))
|
|
128
|
+
if not findings:
|
|
129
|
+
print(" no findings")
|
|
130
|
+
print()
|
|
131
|
+
print("review-agent: %d must-fix, %d to consider" % (len(must), len(findings) - len(must)))
|
|
132
|
+
sys.exit(1 if must else 0)
|
|
133
|
+
'
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
# Distribution name only. The CLI command, the import package, and the repo are all `okl`;
|
|
7
7
|
# PyPI rejects `okl` as too similar to the existing `oki` (l/i are treated as confusable).
|
|
8
8
|
name = "org-knowledge-layer"
|
|
9
|
-
version = "0.4.
|
|
9
|
+
version = "0.4.1"
|
|
10
10
|
description = "Org Knowledge Layer — an installable sixth surface that carries encoded engineering lessons across repos."
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.10"
|
|
@@ -57,3 +57,11 @@ okl scaffold --profile geospatial # rslearn/OlmoEarth pipeli
|
|
|
57
57
|
Each profile also writes a `_PROFILE_<name>.md` into `.claude/rules/` documenting what it installed.
|
|
58
58
|
Profile rules are the *static* half; the *cross-repo* half (defects, gates, retractions that move
|
|
59
59
|
between repos) lives in okl and surfaces via `okl check`.
|
|
60
|
+
|
|
61
|
+
## Architecture review (opt-in)
|
|
62
|
+
|
|
63
|
+
`ci/review-agent.sh` runs `.claude/agents/architecture-reviewer.md` over a PR diff and
|
|
64
|
+
fails on must-fix findings. **Off unless the `REVIEW_CMD` repository variable is set** to
|
|
65
|
+
a CLI that reads a prompt on stdin — `claude -p` (uses your existing Claude Code login,
|
|
66
|
+
no separate API key), `ollama run <model>` (local, free), or any other. Unset, it prints
|
|
67
|
+
one line and passes. It is the only gate in this kit that calls a model.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copy into .github/dependabot.yml
|
|
2
|
+
#
|
|
3
|
+
# This exists because the shipped workflows pin their actions to commit SHAs. Pinning
|
|
4
|
+
# closes the "a mutable tag moved under me" hole and opens a quieter one: the pin never
|
|
5
|
+
# updates, so a security fix in an action never arrives. Pinning with no update path is
|
|
6
|
+
# how a repo ends up on a two-year-old checkout action and calls it hardening.
|
|
7
|
+
# Dependabot rewrites the SHA and the trailing `# v5` comment together.
|
|
8
|
+
version: 2
|
|
9
|
+
|
|
10
|
+
updates:
|
|
11
|
+
- package-ecosystem: github-actions
|
|
12
|
+
directory: "/"
|
|
13
|
+
schedule:
|
|
14
|
+
interval: weekly
|
|
15
|
+
labels: ["dependencies", "ci"]
|
|
16
|
+
commit-message:
|
|
17
|
+
prefix: "ci"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Copy into .github/workflows/method-gates.yml
|
|
2
|
+
# Surface 5 in CI: the mechanical drift-gates + the eval tier. Fail-closed — a red gate blocks merge.
|
|
3
|
+
name: method-gates
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
pull_request:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
# Least privilege: these jobs read code and report a status. Neither writes.
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: method-gates-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
defaults:
|
|
19
|
+
run:
|
|
20
|
+
# Without pipefail a run block continues past a failed segment of a pipeline, so a
|
|
21
|
+
# green step can hide a red command — which defeats the point of a fail-closed gate.
|
|
22
|
+
shell: bash -euo pipefail {0}
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
gates:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
# Pinned to a commit SHA, not a tag: a tag is mutable, so `@v5` is an unpinned
|
|
29
|
+
# dependency with access to your runner. Add a .github/dependabot.yml with the
|
|
30
|
+
# `github-actions` ecosystem so these pins receive security updates — a pin with no
|
|
31
|
+
# update path goes stale, which is its own risk.
|
|
32
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
33
|
+
with:
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
- name: Run drift-gates (retractions / tombstones / doc-orphans / canon-size)
|
|
36
|
+
run: bash gates/run-gates.sh
|
|
37
|
+
|
|
38
|
+
evals:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
42
|
+
with:
|
|
43
|
+
persist-credentials: false
|
|
44
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.13"
|
|
47
|
+
- name: Run eval tier (leads with its own failure count; blocks if RESULTS NOT USABLE)
|
|
48
|
+
env:
|
|
49
|
+
GENERATOR_MODEL: ${{ vars.GENERATOR_MODEL }}
|
|
50
|
+
JUDGE_MODEL: ${{ vars.JUDGE_MODEL }} # must differ from GENERATOR_MODEL
|
|
51
|
+
run: python evals/run_evals.py --fail-rate 0.20
|
|
52
|
+
|
|
53
|
+
review:
|
|
54
|
+
# The architecture reviewer, run headless on the PR diff. OFF unless you set the
|
|
55
|
+
# REVIEW_CMD repository variable to a CLI that takes a prompt on stdin — any vendor,
|
|
56
|
+
# or a local model. Installing the kit costs you nothing and calls nobody's API.
|
|
57
|
+
if: github.event_name == 'pull_request'
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
61
|
+
with:
|
|
62
|
+
fetch-depth: 0 # the reviewer diffs against the base branch
|
|
63
|
+
persist-credentials: false
|
|
64
|
+
- name: Architecture review (off unless REVIEW_CMD is set)
|
|
65
|
+
env:
|
|
66
|
+
REVIEW_CMD: ${{ vars.REVIEW_CMD }}
|
|
67
|
+
# Whatever credential your REVIEW_CMD needs, named by you. Unset is fine.
|
|
68
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
69
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
70
|
+
REVIEW_BASE_REF: origin/${{ github.base_ref }}
|
|
71
|
+
run: bash ci/review-agent.sh
|
|
72
|
+
|
|
73
|
+
# Optional: emit VERIFIED_ON receipts to the org knowledge layer when gates pass.
|
|
74
|
+
# See okl README + ci/okl-verify.yml.
|
|
@@ -16,16 +16,45 @@ on:
|
|
|
16
16
|
push:
|
|
17
17
|
branches: [main]
|
|
18
18
|
|
|
19
|
+
# Least privilege: this workflow reads code and reports a status. It never writes.
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: okl-verify-${{ github.ref }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
defaults:
|
|
28
|
+
run:
|
|
29
|
+
# Without pipefail a run block continues past a failed segment of a pipeline, so a
|
|
30
|
+
# green step can hide a red command.
|
|
31
|
+
shell: bash -euo pipefail {0}
|
|
32
|
+
|
|
19
33
|
jobs:
|
|
20
34
|
okl-verify:
|
|
21
35
|
runs-on: ubuntu-latest
|
|
36
|
+
env:
|
|
37
|
+
# Set at job level so every okl command below resolves the shared layer from the
|
|
38
|
+
# environment. This replaces an `okl connect --token` step, which wrote the bearer
|
|
39
|
+
# token into .okl/config.json on the runner — needless, since the client reads both
|
|
40
|
+
# variables directly, and one more place for a credential to end up.
|
|
41
|
+
# Unset secrets leave these empty, and okl falls back to the repo-local store.
|
|
42
|
+
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
43
|
+
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
22
44
|
steps:
|
|
23
|
-
|
|
45
|
+
# Actions are pinned to a commit SHA: a tag is mutable, so `@v5` is an unpinned
|
|
46
|
+
# dependency with access to your runner. If you copy this file into your own repo,
|
|
47
|
+
# add a .github/dependabot.yml with the `github-actions` ecosystem so these pins get
|
|
48
|
+
# security updates — a pin with no update path goes stale and that is its own risk.
|
|
49
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
24
50
|
with:
|
|
25
|
-
fetch-depth: 0 # drift needs history: it compares file
|
|
26
|
-
|
|
51
|
+
fetch-depth: 0 # drift needs history: it compares governed-file commits vs verified_at
|
|
52
|
+
persist-credentials: false # this job never pushes
|
|
53
|
+
|
|
54
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
27
55
|
with:
|
|
28
56
|
python-version: "3.13"
|
|
57
|
+
|
|
29
58
|
- name: Install okl
|
|
30
59
|
# Detect by the package source, not the distribution name: the name changed once
|
|
31
60
|
# (PyPI rejects "okl" as confusable) and a name-based check silently broke with it.
|
|
@@ -36,13 +65,10 @@ jobs:
|
|
|
36
65
|
pip install org-knowledge-layer
|
|
37
66
|
fi
|
|
38
67
|
|
|
39
|
-
- name:
|
|
40
|
-
env:
|
|
41
|
-
OKL_SERVICE_URL: ${{ secrets.OKL_SERVICE_URL }}
|
|
42
|
-
OKL_TOKEN: ${{ secrets.OKL_TOKEN }}
|
|
68
|
+
- name: Report which store the gate will run against
|
|
43
69
|
run: |
|
|
44
70
|
if [ -n "${OKL_SERVICE_URL:-}" ]; then
|
|
45
|
-
|
|
71
|
+
echo "verifying against the shared layer at $OKL_SERVICE_URL"
|
|
46
72
|
else
|
|
47
73
|
echo "no OKL_SERVICE_URL secret — verifying against the repo-local store"
|
|
48
74
|
fi
|