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.
Files changed (135) hide show
  1. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.coverage +0 -0
  2. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/workflows/ci.yml +12 -0
  3. {org_knowledge_layer-0.4.0/ci → org_knowledge_layer-0.4.1/.github/workflows}/okl-verify.yml +34 -8
  4. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CHANGELOG.md +27 -0
  5. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/PKG-INFO +27 -1
  6. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/README.md +26 -0
  7. {org_knowledge_layer-0.4.0/src/okl/scaffold → org_knowledge_layer-0.4.1}/ci/okl-verify.yml +34 -8
  8. org_knowledge_layer-0.4.1/ci/review-agent.sh +133 -0
  9. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/pyproject.toml +1 -1
  10. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/MANIFEST.md +8 -0
  11. org_knowledge_layer-0.4.1/src/okl/scaffold/ci/dependabot.yml +17 -0
  12. org_knowledge_layer-0.4.1/src/okl/scaffold/ci/method-gates.yml +74 -0
  13. {org_knowledge_layer-0.4.0/.github/workflows → org_knowledge_layer-0.4.1/src/okl/scaffold/ci}/okl-verify.yml +34 -8
  14. org_knowledge_layer-0.4.1/src/okl/scaffold/ci/review-agent.sh +133 -0
  15. org_knowledge_layer-0.4.1/src/okl/scaffold/claude/agents/architecture-reviewer.md +41 -0
  16. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold_cmd.py +5 -0
  17. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/tests/test_okl.py +44 -0
  18. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/tests/test_scaffold.py +89 -0
  19. org_knowledge_layer-0.4.0/src/okl/scaffold/ci/method-gates.yml +0 -32
  20. {org_knowledge_layer-0.4.0/src/okl/scaffold/claude → org_knowledge_layer-0.4.1/.claude}/agents/architecture-reviewer.md +0 -0
  21. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/hooks/stop-okl-encode.sh +0 -0
  22. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/hooks/userpromptsubmit-okl-check.sh +0 -0
  23. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.claude/settings.json +0 -0
  24. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  25. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  26. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/dependabot.yml +0 -0
  27. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/pull_request_template.md +0 -0
  28. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.github/workflows/publish.yml +0 -0
  29. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/.gitignore +0 -0
  30. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/AGENTS.md +0 -0
  31. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CLAUDE.md +0 -0
  32. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/CONTRIBUTING.md +0 -0
  33. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/LICENSE +0 -0
  34. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/SECURITY.md +0 -0
  35. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/ci/check-diagram-figures.sh +0 -0
  36. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/DEPLOY.md +0 -0
  37. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/ab-results-chart.png +0 -0
  38. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/ab-results-chart.svg +0 -0
  39. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/decisions/2026-07-17-flat-retrieval-until-scale.md +0 -0
  40. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/decisions/2026-07-21-subject-tags-controlled-vocabulary.md +0 -0
  41. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-how-it-works.excalidraw +0 -0
  42. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-how-it-works.svg +0 -0
  43. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-sixth-surface.excalidraw +0 -0
  44. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/okl-sixth-surface.svg +0 -0
  45. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/01-memory-that-outlives-the-run.md +0 -0
  46. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/02-dont-let-a-step-grade-itself.md +0 -0
  47. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/docs/posts/03-enforcement-or-good-intentions.md +0 -0
  48. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/README.md +0 -0
  49. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/REPORT.md +0 -0
  50. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/ab_harness.py +0 -0
  51. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260829-2300.json +0 -0
  52. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260829-2315.json +0 -0
  53. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260830-0003.json +0 -0
  54. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260830-0148.json +0 -0
  55. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260901-0133.json +0 -0
  56. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/ab-20260901-1238.json +0 -0
  57. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/README.md +0 -0
  58. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/briefed-userpromptsubmit-lint.yml +0 -0
  59. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/control-lint.yml +0 -0
  60. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/hook.log +0 -0
  61. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/service-record-500.log +0 -0
  62. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-briefed-pretooluse.txt +0 -0
  63. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-briefed-userpromptsubmit.txt +0 -0
  64. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/results/e2e-20260830/session-control.txt +0 -0
  65. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/evals/tasks.jsonl +0 -0
  66. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-canon-size.sh +0 -0
  67. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-diagram-pairs.sh +0 -0
  68. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-doc-orphans.sh +0 -0
  69. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-links.sh +0 -0
  70. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-retractions.sh +0 -0
  71. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/check-tombstones.sh +0 -0
  72. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/gates/run-gates.sh +0 -0
  73. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/hooks/stop-okl-encode.sh +0 -0
  74. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/hooks/userpromptsubmit-okl-check.sh +0 -0
  75. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-canon.json +0 -0
  76. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-decisions.json +0 -0
  77. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-defects.json +0 -0
  78. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/dotnet-review-surfaces.json +0 -0
  79. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/frontend-canon.json +0 -0
  80. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-deeptime-defects.json +0 -0
  81. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-defects.json +0 -0
  82. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-enforcement-defects.json +0 -0
  83. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/geospatial-eval-defects.json +0 -0
  84. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/rag-defects.json +0 -0
  85. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/seed/react-defects.json +0 -0
  86. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/__init__.py +0 -0
  87. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/__main__.py +0 -0
  88. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/bootstrap.py +0 -0
  89. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/cli.py +0 -0
  90. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/client.py +0 -0
  91. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/core.py +0 -0
  92. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/drift.py +0 -0
  93. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/mcp_server.py +0 -0
  94. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/check-rules.md +0 -0
  95. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/feature-spec.md +0 -0
  96. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/seed-from-codebase.md +0 -0
  97. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/commands/seed-from-docs.md +0 -0
  98. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/rules/example-area.md +0 -0
  99. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/RECOMMENDED-COMPANIONS.md +0 -0
  100. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/encoding-loop/SKILL.md +0 -0
  101. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/claude/skills/verify-before-claiming/SKILL.md +0 -0
  102. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/README.md +0 -0
  103. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/cases.jsonl +0 -0
  104. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/evals/run_evals.py +0 -0
  105. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-canon-size.sh +0 -0
  106. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-diagram-pairs.sh +0 -0
  107. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-doc-orphans.sh +0 -0
  108. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-links.sh +0 -0
  109. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-retractions.sh +0 -0
  110. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/check-tombstones.sh +0 -0
  111. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/gates/run-gates.sh +0 -0
  112. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/hooks.json +0 -0
  113. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/stop-okl-encode.sh +0 -0
  114. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/hooks/userpromptsubmit-okl-check.sh +0 -0
  115. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/plugin/plugin.json +0 -0
  116. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/README.md +0 -0
  117. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/architecture.md +0 -0
  118. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/messaging.md +0 -0
  119. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/performance-and-data.md +0 -0
  120. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/dotnet/rules/security.md +0 -0
  121. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/geospatial/README.md +0 -0
  122. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/geospatial/rules/geospatial-ml.md +0 -0
  123. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/README.md +0 -0
  124. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/fastapi-backend.md +0 -0
  125. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/project-structure.md +0 -0
  126. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/python-rag/rules/rag-pipeline.md +0 -0
  127. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/react/README.md +0 -0
  128. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/profiles/react/rules/frontend.md +0 -0
  129. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/registries/RETRACTIONS.md +0 -0
  130. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/registries/tombstones.txt +0 -0
  131. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/root/CLAUDE.md +0 -0
  132. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/scaffold/root/METHOD.md +0 -0
  133. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/seed.py +0 -0
  134. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/service.py +0 -0
  135. {org_knowledge_layer-0.4.0 → org_knowledge_layer-0.4.1}/src/okl/store.py +0 -0
@@ -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
- - uses: actions/checkout@v4
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 mtimes/commits vs verified_at
26
- - uses: actions/setup-python@v5
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: Connect to the shared layer (optional — skipped when secrets are unset)
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
- okl connect "$OKL_SERVICE_URL" --token "$OKL_TOKEN"
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.0
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
- - uses: actions/checkout@v4
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 mtimes/commits vs verified_at
26
- - uses: actions/setup-python@v5
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: Connect to the shared layer (optional — skipped when secrets are unset)
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
- okl connect "$OKL_SERVICE_URL" --token "$OKL_TOKEN"
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.0"
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
- - uses: actions/checkout@v4
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 mtimes/commits vs verified_at
26
- - uses: actions/setup-python@v5
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: Connect to the shared layer (optional — skipped when secrets are unset)
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
- okl connect "$OKL_SERVICE_URL" --token "$OKL_TOKEN"
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