org-knowledge-layer 0.1.0__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.1.0/.claude/hooks/stop-okl-encode.sh +78 -0
- org_knowledge_layer-0.1.0/.claude/hooks/userpromptsubmit-okl-check.sh +68 -0
- org_knowledge_layer-0.1.0/.claude/settings.json +24 -0
- org_knowledge_layer-0.1.0/.claude/settings.local.json +79 -0
- org_knowledge_layer-0.1.0/.github/workflows/ci.yml +22 -0
- org_knowledge_layer-0.1.0/.github/workflows/okl-verify.yml +59 -0
- org_knowledge_layer-0.1.0/.gitignore +21 -0
- org_knowledge_layer-0.1.0/AGENTS.md +62 -0
- org_knowledge_layer-0.1.0/CLAUDE.md +62 -0
- org_knowledge_layer-0.1.0/LICENSE +21 -0
- org_knowledge_layer-0.1.0/PKG-INFO +475 -0
- org_knowledge_layer-0.1.0/README.md +443 -0
- org_knowledge_layer-0.1.0/ci/okl-verify.yml +59 -0
- org_knowledge_layer-0.1.0/docs/decisions/2026-07-17-flat-retrieval-until-scale.md +55 -0
- org_knowledge_layer-0.1.0/docs/decisions/2026-07-21-subject-tags-controlled-vocabulary.md +52 -0
- org_knowledge_layer-0.1.0/docs/okl-sixth-surface.excalidraw +3819 -0
- org_knowledge_layer-0.1.0/docs/okl-sixth-surface.svg +2 -0
- org_knowledge_layer-0.1.0/docs/posts/01-memory-that-outlives-the-run.md +43 -0
- org_knowledge_layer-0.1.0/docs/posts/02-dont-let-a-step-grade-itself.md +37 -0
- org_knowledge_layer-0.1.0/docs/posts/03-enforcement-or-good-intentions.md +33 -0
- org_knowledge_layer-0.1.0/evals/README.md +49 -0
- org_knowledge_layer-0.1.0/evals/REPORT.md +265 -0
- org_knowledge_layer-0.1.0/evals/ab_harness.py +196 -0
- org_knowledge_layer-0.1.0/evals/results/ab-20260829-2300.json +41 -0
- org_knowledge_layer-0.1.0/evals/results/ab-20260829-2315.json +137 -0
- org_knowledge_layer-0.1.0/evals/results/ab-20260830-0003.json +441 -0
- org_knowledge_layer-0.1.0/evals/results/ab-20260830-0148.json +441 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/README.md +23 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/briefed-userpromptsubmit-lint.yml +27 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/control-lint.yml +22 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/hook.log +3 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/service-record-500.log +47 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/session-briefed-pretooluse.txt +3 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/session-briefed-userpromptsubmit.txt +7 -0
- org_knowledge_layer-0.1.0/evals/results/e2e-20260830/session-control.txt +3 -0
- org_knowledge_layer-0.1.0/evals/tasks.jsonl +8 -0
- org_knowledge_layer-0.1.0/hooks/stop-okl-encode.sh +78 -0
- org_knowledge_layer-0.1.0/hooks/userpromptsubmit-okl-check.sh +68 -0
- org_knowledge_layer-0.1.0/pyproject.toml +49 -0
- org_knowledge_layer-0.1.0/seed/dotnet-canon.json +489 -0
- org_knowledge_layer-0.1.0/seed/dotnet-decisions.json +328 -0
- org_knowledge_layer-0.1.0/seed/dotnet-defects.json +133 -0
- org_knowledge_layer-0.1.0/seed/dotnet-review-surfaces.json +147 -0
- org_knowledge_layer-0.1.0/seed/frontend-canon.json +116 -0
- org_knowledge_layer-0.1.0/seed/geospatial-deeptime-defects.json +59 -0
- org_knowledge_layer-0.1.0/seed/geospatial-defects.json +154 -0
- org_knowledge_layer-0.1.0/seed/geospatial-enforcement-defects.json +121 -0
- org_knowledge_layer-0.1.0/seed/geospatial-eval-defects.json +25 -0
- org_knowledge_layer-0.1.0/seed/rag-defects.json +120 -0
- org_knowledge_layer-0.1.0/seed/react-defects.json +45 -0
- org_knowledge_layer-0.1.0/src/okl/__init__.py +12 -0
- org_knowledge_layer-0.1.0/src/okl/__main__.py +8 -0
- org_knowledge_layer-0.1.0/src/okl/bootstrap.py +83 -0
- org_knowledge_layer-0.1.0/src/okl/cli.py +484 -0
- org_knowledge_layer-0.1.0/src/okl/client.py +160 -0
- org_knowledge_layer-0.1.0/src/okl/core.py +223 -0
- org_knowledge_layer-0.1.0/src/okl/drift.py +119 -0
- org_knowledge_layer-0.1.0/src/okl/mcp_server.py +75 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/MANIFEST.md +59 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/ci/method-gates.yml +32 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/ci/okl-verify.yml +59 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/agents/architecture-reviewer.md +41 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/commands/check-rules.md +24 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/commands/feature-spec.md +37 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/rules/example-area.md +22 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/skills/RECOMMENDED-COMPANIONS.md +40 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/skills/encoding-loop/SKILL.md +48 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/claude/skills/verify-before-claiming/SKILL.md +56 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/evals/README.md +32 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/evals/cases.jsonl +1 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/evals/run_evals.py +109 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/gates/check-canon-size.sh +11 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/gates/check-doc-orphans.sh +19 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/gates/check-retractions.sh +22 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/gates/check-tombstones.sh +22 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/gates/run-gates.sh +31 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/hooks/hooks.json +16 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/hooks/stop-okl-encode.sh +78 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/hooks/userpromptsubmit-okl-check.sh +68 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/plugin/plugin.json +10 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/dotnet/README.md +12 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/dotnet/rules/architecture.md +55 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/dotnet/rules/messaging.md +31 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/dotnet/rules/performance-and-data.md +36 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/dotnet/rules/security.md +42 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/geospatial/README.md +6 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/geospatial/rules/geospatial-ml.md +38 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/python-rag/README.md +13 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/python-rag/rules/fastapi-backend.md +37 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/python-rag/rules/project-structure.md +28 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/python-rag/rules/rag-pipeline.md +73 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/react/README.md +18 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/profiles/react/rules/frontend.md +57 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/registries/RETRACTIONS.md +19 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/registries/tombstones.txt +7 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/root/CLAUDE.md +55 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold/root/METHOD.md +64 -0
- org_knowledge_layer-0.1.0/src/okl/scaffold_cmd.py +110 -0
- org_knowledge_layer-0.1.0/src/okl/seed.py +55 -0
- org_knowledge_layer-0.1.0/src/okl/service.py +137 -0
- org_knowledge_layer-0.1.0/src/okl/store.py +432 -0
- org_knowledge_layer-0.1.0/tests/test_okl.py +343 -0
- org_knowledge_layer-0.1.0/tests/test_scaffold.py +168 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop hook — the write-side mechanical catch for the encoding loop.
|
|
3
|
+
#
|
|
4
|
+
# The read side (okl check) is enforced by the PreToolUse hook; nothing enforced the WRITE
|
|
5
|
+
# side, so a session could end without recording what it learned ("a merged fix without the
|
|
6
|
+
# rule is a half-finished job"). This hook asks the question at the ship moment, once:
|
|
7
|
+
# if the session changed the working tree, block the first stop (exit 2) with a prompt to
|
|
8
|
+
# either `okl record` the lesson or state that there is none. It never fires twice in one
|
|
9
|
+
# session (marker file) and never loops (stop_hook_active guard).
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
|
|
12
|
+
# Same resolver as pretooluse-okl-check.sh (env → pinned config → PATH → python3 -m okl);
|
|
13
|
+
# the reminder is best-effort, so an unresolvable okl silently disables it rather than blocking.
|
|
14
|
+
resolve_okl() {
|
|
15
|
+
if [ -n "${OKL_BIN:-}" ]; then printf '%s' "$OKL_BIN"; return 0; fi
|
|
16
|
+
local d="$PWD"
|
|
17
|
+
while [ "$d" != "/" ]; do
|
|
18
|
+
if [ -f "$d/.okl/config.json" ]; then
|
|
19
|
+
local bin
|
|
20
|
+
bin=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("okl_bin") or "")' \
|
|
21
|
+
"$d/.okl/config.json" 2>/dev/null || true)
|
|
22
|
+
if [ -n "$bin" ]; then printf '%s' "$bin"; return 0; fi
|
|
23
|
+
break
|
|
24
|
+
fi
|
|
25
|
+
d=$(dirname "$d")
|
|
26
|
+
done
|
|
27
|
+
if command -v okl >/dev/null 2>&1; then printf '%s' "okl"; return 0; fi
|
|
28
|
+
if python3 -c "import okl" >/dev/null 2>&1; then printf '%s' "python3 -m okl"; return 0; fi
|
|
29
|
+
return 1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
OKL=$(resolve_okl) || exit 0
|
|
33
|
+
|
|
34
|
+
payload=$(cat 2>/dev/null || true)
|
|
35
|
+
parsed=$(printf '%s' "$payload" | python3 -c '
|
|
36
|
+
import json, sys
|
|
37
|
+
try:
|
|
38
|
+
d = json.load(sys.stdin)
|
|
39
|
+
except Exception:
|
|
40
|
+
d = {}
|
|
41
|
+
print(d.get("session_id", ""))
|
|
42
|
+
print("true" if d.get("stop_hook_active") else "false")
|
|
43
|
+
' 2>/dev/null) || parsed=""
|
|
44
|
+
session_id=$(printf '%s\n' "$parsed" | sed -n 1p)
|
|
45
|
+
stop_hook_active=$(printf '%s\n' "$parsed" | sed -n 2p)
|
|
46
|
+
[ -n "$stop_hook_active" ] || stop_hook_active="false"
|
|
47
|
+
|
|
48
|
+
# Never loop: if we already blocked once and Claude is stopping again, let it stop.
|
|
49
|
+
[ "${stop_hook_active}" = "true" ] && exit 0
|
|
50
|
+
|
|
51
|
+
# Only fire when the session plausibly did work: uncommitted changes, or a commit in the
|
|
52
|
+
# last hour (covers commit-then-stop sessions).
|
|
53
|
+
changed=0
|
|
54
|
+
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
|
|
55
|
+
changed=1
|
|
56
|
+
elif last=$(git log -1 --format=%ct 2>/dev/null); then
|
|
57
|
+
now=$(date +%s)
|
|
58
|
+
[ $((now - last)) -lt 3600 ] && changed=1
|
|
59
|
+
fi
|
|
60
|
+
[ "$changed" = "1" ] || exit 0
|
|
61
|
+
|
|
62
|
+
# Once per session (fall back to a repo-scoped marker when no session id is provided).
|
|
63
|
+
marker="${TMPDIR:-/tmp}/okl-encode-reminder-${session_id:-$(pwd | cksum | cut -d' ' -f1)}"
|
|
64
|
+
[ -e "$marker" ] && exit 0
|
|
65
|
+
touch "$marker" 2>/dev/null || true
|
|
66
|
+
|
|
67
|
+
cat >&2 <<'MSG'
|
|
68
|
+
ENCODING LOOP — before this session ends: did it surface a lesson worth keeping?
|
|
69
|
+
A non-obvious failure mode, a rule discovered the hard way, a decision that shouldn't be
|
|
70
|
+
silently reversed? If yes, record it now (choose the scope deliberately — 'org' spreads
|
|
71
|
+
to every repo, 'repo' stays local — and tag the subject):
|
|
72
|
+
|
|
73
|
+
okl record --type Defect|Rule|Decision --scope org|repo --tags "<subjects>" \
|
|
74
|
+
--title "..." --symptom "..." --body "cause: ..." --fix "..."
|
|
75
|
+
|
|
76
|
+
If the session genuinely learned nothing durable, state that explicitly and finish.
|
|
77
|
+
MSG
|
|
78
|
+
exit 2
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# UserPromptSubmit hook — inject the org's relevant lessons into the model's context
|
|
3
|
+
# BEFORE it starts the task. This event is the only correct one for delivery: its stdout
|
|
4
|
+
# (exit 0) is added to Claude's context, and its stdin carries the actual prompt text, so
|
|
5
|
+
# the briefing is retrieved for the task the user really asked for.
|
|
6
|
+
#
|
|
7
|
+
# (The earlier PreToolUse version fired on every edit and printed the briefing to a channel
|
|
8
|
+
# the model never sees — PreToolUse exit-0 stdout goes to the transcript only. Discovered by
|
|
9
|
+
# an end-to-end test: hook fired, briefing correct, defect reproduced anyway.)
|
|
10
|
+
#
|
|
11
|
+
# FAILS CLOSED via exit 2: if the knowledge layer is unreachable, the prompt is blocked
|
|
12
|
+
# rather than letting the agent proceed blind. A check that reports "clean" while broken is
|
|
13
|
+
# worse than no check.
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
|
|
16
|
+
# Resolve how to invoke okl (env → pinned config → PATH → python3 -m okl); hooks run in
|
|
17
|
+
# whatever environment the harness spawns, which often lacks the venv/pipx bin dir.
|
|
18
|
+
resolve_okl() {
|
|
19
|
+
if [ -n "${OKL_BIN:-}" ]; then printf '%s' "$OKL_BIN"; return 0; fi
|
|
20
|
+
local d="$PWD"
|
|
21
|
+
while [ "$d" != "/" ]; do
|
|
22
|
+
if [ -f "$d/.okl/config.json" ]; then
|
|
23
|
+
local bin
|
|
24
|
+
bin=$(python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("okl_bin") or "")' \
|
|
25
|
+
"$d/.okl/config.json" 2>/dev/null || true)
|
|
26
|
+
if [ -n "$bin" ]; then printf '%s' "$bin"; return 0; fi
|
|
27
|
+
break
|
|
28
|
+
fi
|
|
29
|
+
d=$(dirname "$d")
|
|
30
|
+
done
|
|
31
|
+
if command -v okl >/dev/null 2>&1; then printf '%s' "okl"; return 0; fi
|
|
32
|
+
if python3 -c "import okl" >/dev/null 2>&1; then printf '%s' "python3 -m okl"; return 0; fi
|
|
33
|
+
return 1
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ! OKL=$(resolve_okl); then
|
|
37
|
+
[ "${OKL_OFFLINE:-0}" = "1" ] && exit 0
|
|
38
|
+
echo "okl NOT FOUND — blocking (a check that can't run must not pass as clean)." >&2
|
|
39
|
+
echo "Install it (pip install okl), set OKL_BIN, or re-run 'okl init' from a shell where it" >&2
|
|
40
|
+
echo "works (pins okl_bin into .okl/config.json). OKL_OFFLINE=1 proceeds without the layer." >&2
|
|
41
|
+
exit 2
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# The task is the prompt itself (stdin JSON: {"prompt": "..."}); OKL_TASK overrides;
|
|
45
|
+
# last-commit-message is only the fallback of last resort.
|
|
46
|
+
payload=$(cat 2>/dev/null || true)
|
|
47
|
+
prompt=$(printf '%s' "$payload" | python3 -c '
|
|
48
|
+
import json, sys
|
|
49
|
+
try:
|
|
50
|
+
print((json.load(sys.stdin).get("prompt") or "").strip()[:2000])
|
|
51
|
+
except Exception:
|
|
52
|
+
print("")
|
|
53
|
+
' 2>/dev/null || true)
|
|
54
|
+
TASK="${OKL_TASK:-${prompt:-$(git log -1 --pretty=%s 2>/dev/null || echo 'general work')}}"
|
|
55
|
+
|
|
56
|
+
# $OKL unquoted on purpose: it may be a command + args ("python3 -m okl").
|
|
57
|
+
if out=$($OKL check --task "$TASK" --format agent 2>/dev/null); then
|
|
58
|
+
printf '%s\n' "$out" # stdout → the model's context
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if [ "${OKL_OFFLINE:-0}" = "1" ]; then
|
|
63
|
+
echo "OKL offline (OKL_OFFLINE=1 acknowledged) — proceeding without the layer." >&2
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
echo "OKL UNREACHABLE — blocking this prompt. A check that reports 'clean' while broken is worse than no check." >&2
|
|
67
|
+
echo "Fix connectivity, or set OKL_OFFLINE=1 to explicitly proceed without the org knowledge layer." >&2
|
|
68
|
+
exit 2
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"Stop": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/stop-okl-encode.sh"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"UserPromptSubmit": [
|
|
14
|
+
{
|
|
15
|
+
"hooks": [
|
|
16
|
+
{
|
|
17
|
+
"type": "command",
|
|
18
|
+
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/userpromptsubmit-okl-check.sh"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(chmod +x /Users/joshuadell/Dev/okl/src/okl/scaffold/hooks/stop-okl-encode.sh)",
|
|
5
|
+
"Bash(python3 -m pytest tests/test_scaffold.py::test_encode_hook_loop_guard_and_fires_once -q)",
|
|
6
|
+
"Bash(python3 -c ' *)",
|
|
7
|
+
"Bash(python3 -m okl --help)",
|
|
8
|
+
"Bash(python3 -c \"import psycopg; print\\('psycopg', psycopg.__version__\\)\")",
|
|
9
|
+
"Bash(sqlite3 -column /Users/joshuadell/Dev/okl/.okl/okl.db \"SELECT COUNT\\(*\\) as nodes FROM node; SELECT COUNT\\(*\\) as edges FROM edge;\")",
|
|
10
|
+
"Bash(sqlite3 -column /Users/joshuadell/Dev/okl/.okl/okl.db \"SELECT substr\\(id,1,40\\) as id, type, substr\\(title,1,50\\) as title FROM node WHERE id NOT LIKE 'seed:novacraft-defects%' AND id NOT LIKE 'seed:quartzose%' AND id NOT LIKE 'seed:san-juan%' AND id NOT LIKE 'seed:react%' ORDER BY created_at;\")",
|
|
11
|
+
"Bash(sqlite3 -column /Users/joshuadell/Dev/okl/.okl/okl.db \"SELECT substr\\(id,1,50\\) as id, substr\\(title,1,45\\) as title FROM node WHERE id LIKE 'seed:novacraft-defects%' OR id LIKE 'seed:quartzose%' OR id LIKE 'seed:san-juan%' OR id LIKE 'seed:react%' ORDER BY id;\")",
|
|
12
|
+
"Bash(sqlite3 /Users/joshuadell/Dev/okl/.okl/okl.db \"SELECT COUNT\\(*\\) FROM node WHERE id LIKE 'seed:%';\")",
|
|
13
|
+
"Bash(sqlite3 /Users/joshuadell/Dev/okl/.okl/okl.db \"SELECT datetime\\(created_at/1000,'unixepoch','localtime'\\) as t, COUNT\\(*\\) FROM node WHERE id LIKE 'seed:san-juan-en%' OR id LIKE 'seed:san-juan-ev%' GROUP BY t;\")",
|
|
14
|
+
"Bash(git init *)",
|
|
15
|
+
"Bash(timeout 60 claude -p --model haiku)",
|
|
16
|
+
"Bash(claude -p --model haiku)",
|
|
17
|
+
"Bash(python3 evals/ab_harness.py --dry-run)",
|
|
18
|
+
"Bash(GENERATOR_CMD=\"claude -p --model sonnet\" JUDGE_CMD=\"claude -p --model sonnet\" python3 evals/ab_harness.py --dry-run)",
|
|
19
|
+
"Bash(python3 evals/ab_harness.py --limit 2)",
|
|
20
|
+
"Bash(python3 evals/ab_harness.py)",
|
|
21
|
+
"Bash(python3 evals/ab_harness.py --dry-run --samples 3)",
|
|
22
|
+
"Bash(python3 evals/ab_harness.py --samples 3)",
|
|
23
|
+
"Bash(git add *)",
|
|
24
|
+
"Bash(git -c core.hooksPath=/dev/null commit -m 'okl v0: the sixth surface — cross-repo knowledge layer with enforced loop *)",
|
|
25
|
+
"Bash(okl drift *)",
|
|
26
|
+
"Bash(okl verify *)",
|
|
27
|
+
"Bash(echo \"drift exit=$?\")",
|
|
28
|
+
"Bash(git -c core.hooksPath=/dev/null commit -m 'A/B receipt: 3-sample run \\(48 runs, 0 failures\\) — baseline 33% defect reproduction, briefed 4% *)",
|
|
29
|
+
"Bash(GENERATOR_CMD=\"claude -p --model haiku\" JUDGE_CMD=\"claude -p --model sonnet\" python3 evals/ab_harness.py --samples 3)",
|
|
30
|
+
"Bash(git -c core.hooksPath=/dev/null commit -m 'A/B receipt: haiku generator \\(sonnet judge\\) — briefed haiku 12% vs unbriefed sonnet 33% *)",
|
|
31
|
+
"Bash(git -c core.hooksPath=/dev/null commit -m 'Evaluation report: full method, all four runs, findings, threats to validity *)",
|
|
32
|
+
"Bash(git -c core.hooksPath=/dev/null commit -m 'Report: add '\\\\''How to read these numbers'\\\\'' — plain-language meaning, verbatim judge verdicts *)",
|
|
33
|
+
"Bash(python3 -c \"import fastapi, uvicorn; print\\('fastapi', fastapi.__version__, '| uvicorn', uvicorn.__version__\\)\")",
|
|
34
|
+
"Bash(OKL_DATABASE_URL=\"sqlite:////Users/joshuadell/Dev/okl/.okl/okl.db\" okl serve --port 8765)",
|
|
35
|
+
"Bash(curl -sf http://localhost:8765/health)",
|
|
36
|
+
"Bash(curl -s http://localhost:8765/health)",
|
|
37
|
+
"Bash(okl connect *)",
|
|
38
|
+
"Bash(OKL_TASK=\"Add a GitHub Actions job step that lints the project with ruff and fails the build on findings\" claude -p \"Add a GitHub Actions workflow at .github/workflows/lint.yml with a job step that lints this Python project with ruff and fails the build on findings. Write the file, then stop.\" --permission-mode acceptEdits --allowedTools \"Write,Edit,Read\")",
|
|
39
|
+
"Bash(claude -p \"Add a GitHub Actions workflow at .github/workflows/lint.yml with a job step that lints this Python project with ruff and fails the build on findings. Write the file, then stop.\" --permission-mode acceptEdits --allowedTools \"Write,Edit,Read\")",
|
|
40
|
+
"Bash(okl record --type Rule --scope org --tags \"method\" \\\\ *)",
|
|
41
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'E2E finding: briefing delivery moved to UserPromptSubmit — PreToolUse stdout never reaches the model *)",
|
|
42
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'README: full honesty on the crowded space — not novel, why built anyway, compose with mem0/Zep *)",
|
|
43
|
+
"Bash(curl -s -o /dev/null -w \"%{http_code}\" https://pypi.org/pypi/okl/json)",
|
|
44
|
+
"Bash(sqlite3 .okl/okl.db \"SELECT COUNT\\(*\\) FROM node;\")",
|
|
45
|
+
"Bash(timeout_ok=1 uv run python render_excalidraw.py /Users/joshuadell/Dev/okl/docs/okl-sixth-surface.excalidraw --svg -o /Users/joshuadell/Dev/okl/docs/okl-sixth-surface.svg)",
|
|
46
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'P0 canon + mirror enforcement + store sync \\(handoff work-down\\) *)",
|
|
47
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'Re-export sixth-surface SVG — render now matches the .excalidraw source *)",
|
|
48
|
+
"Bash(ls -la \"/Users/joshuadell/Dev/emeraldleaf-dev/src/assets/\" 2>/dev/null | grep -i \"okl\\\\|surface\"; cp docs/okl-sixth-surface.svg \"/Users/joshuadell/Dev/emeraldleaf-dev/src/assets/okl-sixth-surface.svg\" 2>/dev/null && echo \"site asset synced\")",
|
|
49
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'Genericize project identities across the public surface *)",
|
|
50
|
+
"Bash(git branch *)",
|
|
51
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'okl v0.1 — the Org Knowledge Layer *)",
|
|
52
|
+
"Bash(git -c core.hooksPath=/dev/null commit -qm 'Close the migration leftovers: AGENTS.md, dead-hook purge, stale diagram *)",
|
|
53
|
+
"Bash(python3 -m pip install -q build twine)",
|
|
54
|
+
"Bash(python3 -m build)",
|
|
55
|
+
"Bash(python3 -m twine check dist/*)",
|
|
56
|
+
"Bash(unzip -l dist/*.whl)",
|
|
57
|
+
"Bash(git -C /Users/joshuadell/Dev/okl add docs/posts)",
|
|
58
|
+
"Bash(git -C /Users/joshuadell/Dev/okl -c core.hooksPath=/dev/null commit -qm 'Post 3: correct the read-hook mechanics; add the dead-channel lesson *)",
|
|
59
|
+
"Bash(git -C /Users/joshuadell/Dev/okl push -q origin main)",
|
|
60
|
+
"Bash(git -C /Users/joshuadell/Dev/okl log --oneline)",
|
|
61
|
+
"Bash(python3 -m twine --version)",
|
|
62
|
+
"Bash(python3 -c \"import setuptools; print\\('setuptools', setuptools.__version__\\)\")",
|
|
63
|
+
"Bash(python3 -c \"import hatchling; print\\('hatchling', hatchling.__version__ if hasattr\\(hatchling,'__version__'\\) else 'n/a'\\)\")",
|
|
64
|
+
"Bash(python3 -m pip list)",
|
|
65
|
+
"Bash(rm -rf oklbuild)",
|
|
66
|
+
"Bash(python3 -m venv oklbuild)",
|
|
67
|
+
"Bash(./oklbuild/bin/pip install *)",
|
|
68
|
+
"Bash(./oklbuild/bin/pip show *)",
|
|
69
|
+
"Bash(/tmp/oklbuild/bin/python -m build --no-isolation)",
|
|
70
|
+
"Bash(unzip -p dist/*.whl \"*/entry_points.txt\")"
|
|
71
|
+
],
|
|
72
|
+
"additionalDirectories": [
|
|
73
|
+
"/Users/joshuadell/Dev/okl/e2e/scratch-briefed/.okl",
|
|
74
|
+
"/Users/joshuadell/Dev/emeraldleaf-dev/src/pages",
|
|
75
|
+
"/Users/joshuadell/Dev/emeraldleaf-dev/src/assets",
|
|
76
|
+
"/Users/joshuadell/Dev/emeraldleaf-dev/src"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Repo CI — lints and tests okl itself. (okl-verify.yml is different: it demonstrates
|
|
2
|
+
# the product's own drift/method gates, the workflow consumers copy into their repos.)
|
|
3
|
+
name: ci
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [ "main" ]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ "main" ]
|
|
9
|
+
jobs:
|
|
10
|
+
lint-and-test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v5
|
|
14
|
+
- uses: actions/setup-python@v6
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- name: Install (dev extras)
|
|
18
|
+
run: pip install -e ".[dev]"
|
|
19
|
+
- name: Lint — ruff (config in pyproject.toml)
|
|
20
|
+
run: ruff check .
|
|
21
|
+
- name: Tests
|
|
22
|
+
run: pytest -q
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Installed by `okl init` into .github/workflows/okl-verify.yml (also stamped by `okl scaffold`).
|
|
2
|
+
#
|
|
3
|
+
# The knowledge layer's CI verifier — real checks, not placeholders:
|
|
4
|
+
# 1. `okl drift --gate` — fails the build when a rule's governed files changed after the
|
|
5
|
+
# rule was last verified (a stale rule is a rule nobody re-checked).
|
|
6
|
+
# 2. `gates/run-gates.sh` — the repo's mechanical method gates, when the scaffold is present.
|
|
7
|
+
#
|
|
8
|
+
# Shared-layer connection is optional: without OKL_SERVICE_URL the drift gate runs against
|
|
9
|
+
# the repo's local .okl store. Configure the secrets to verify against the org layer and to
|
|
10
|
+
# let gate scripts emit receipts (`okl link <gate_id> VERIFIED_ON <defect_id>`) — emit those
|
|
11
|
+
# from inside the gate that proved itself against real drift, where the ids are known.
|
|
12
|
+
name: okl-verify
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
pull_request:
|
|
16
|
+
push:
|
|
17
|
+
branches: [main]
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
okl-verify:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0 # drift needs history: it compares file mtimes/commits vs verified_at
|
|
26
|
+
- uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.13"
|
|
29
|
+
- name: Install okl
|
|
30
|
+
# Consumer repos install the released package; in okl's own repo this
|
|
31
|
+
# workflow dogfoods the working tree (pip install okl would 404 — not on PyPI yet).
|
|
32
|
+
run: |
|
|
33
|
+
if grep -q '^name = "okl"' pyproject.toml 2>/dev/null; then
|
|
34
|
+
pip install -e .
|
|
35
|
+
else
|
|
36
|
+
pip install okl
|
|
37
|
+
fi
|
|
38
|
+
|
|
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 }}
|
|
43
|
+
run: |
|
|
44
|
+
if [ -n "${OKL_SERVICE_URL:-}" ]; then
|
|
45
|
+
okl connect "$OKL_SERVICE_URL" --token "$OKL_TOKEN"
|
|
46
|
+
else
|
|
47
|
+
echo "no OKL_SERVICE_URL secret — verifying against the repo-local store"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
- name: Drift gate — rules whose governed code changed after last verification
|
|
51
|
+
run: okl drift --gate
|
|
52
|
+
|
|
53
|
+
- name: Method gates (when the scaffold kit is present)
|
|
54
|
+
run: |
|
|
55
|
+
if [ -x gates/run-gates.sh ]; then
|
|
56
|
+
bash gates/run-gates.sh
|
|
57
|
+
else
|
|
58
|
+
echo "no gates/run-gates.sh — method-kit gates not installed (okl scaffold adds them)"
|
|
59
|
+
fi
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.DS_Store
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.okl/
|
|
6
|
+
okl.db
|
|
7
|
+
*.db
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.venv/
|
|
12
|
+
okl-starter-kit.tar.gz
|
|
13
|
+
okl-bootstrap.json
|
|
14
|
+
# scratch test repos created by smoke tests
|
|
15
|
+
*_test/
|
|
16
|
+
method-demo/
|
|
17
|
+
e2e/
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#Ignore vscode AI rules
|
|
21
|
+
.github/instructions/codacy.instructions.md
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# okl — repo instructions
|
|
2
|
+
|
|
3
|
+
Read [evals/REPORT.md](evals/REPORT.md) before touching anything measurement-adjacent —
|
|
4
|
+
it is the most load-bearing document in the repo (method, results, threats to validity).
|
|
5
|
+
|
|
6
|
+
## The loop is LIVE in this repo
|
|
7
|
+
|
|
8
|
+
The hooks fire on your own session: `UserPromptSubmit` injects the store's briefing into
|
|
9
|
+
your context before you start; `Stop` blocks your first stop to ask what was learned.
|
|
10
|
+
Answer it honestly — record with a deliberate scope (`org` spreads to every repo,
|
|
11
|
+
`repo` stays local) and tags from the closed vocabulary in `store.KNOWN_TAGS`. Growing
|
|
12
|
+
that vocabulary is an edit to the set plus a note in the tags ADR, never an ad-hoc tag.
|
|
13
|
+
|
|
14
|
+
- **Verification is evidence-based**: `okl verify <id> --run "<check>" --expect "<signal>"`.
|
|
15
|
+
Never re-record with `--verified` to clear drift — run the check.
|
|
16
|
+
- **After changing files a rule governs, `okl drift` goes red on purpose.** Re-verify
|
|
17
|
+
the affected nodes (their tests are usually the right `--run`) before finishing.
|
|
18
|
+
- The local store (`.okl/okl.db`, gitignored) should hold all 11 seed files plus
|
|
19
|
+
recorded nodes; `okl seed seed/` loads the `*-defects.json` set, while
|
|
20
|
+
`dotnet-{canon,decisions,review-surfaces}.json` and `frontend-canon.json` load explicitly.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pytest -q # full suite; must be green before any commit
|
|
26
|
+
ruff check . # lint (config in pyproject.toml)
|
|
27
|
+
python3 evals/ab_harness.py --dry-run # eval harness; see evals/README.md before running live
|
|
28
|
+
okl drift # rules whose governed source changed after verification
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Rules that are enforced (and why)
|
|
32
|
+
|
|
33
|
+
- **Mirror files are byte-identical, test-enforced**: `ci/okl-verify.yml` ==
|
|
34
|
+
`.github/workflows/okl-verify.yml` == `src/okl/scaffold/ci/okl-verify.yml`, and
|
|
35
|
+
`hooks/*.sh` == `src/okl/scaffold/hooks/*.sh`. The scaffold copies are what consumers
|
|
36
|
+
receive; the repo copies are the dogfood. Edit ONE, copy to the others in the same
|
|
37
|
+
change — `tests/test_scaffold.py::test_mirror_files_identical` fails otherwise.
|
|
38
|
+
- **ruff `E702` is ignored deliberately** (semicolon one-liners): the tests use a
|
|
39
|
+
compact setup style throughout; re-enabling it is a repo-wide style decision, not a
|
|
40
|
+
cleanup.
|
|
41
|
+
- **Audits read the repo, not the working tree**: any gate/check that scans content
|
|
42
|
+
must scan `git ls-files` output (committed reality), never the dirty working tree —
|
|
43
|
+
scanning the tree makes an uncommitted edit pass or fail an audit that main would
|
|
44
|
+
answer differently. (Bit the .NET platform twice.)
|
|
45
|
+
- **Eval integrity**: the harness refuses judge==generator; never quote a number from a
|
|
46
|
+
run marked RESULTS NOT USABLE; every cited figure needs a committed receipt in
|
|
47
|
+
`evals/results/`.
|
|
48
|
+
- **The diagram and README move with the system**: they are drift-enrolled
|
|
49
|
+
(`n_b550ba9c5c8a`). `docs/okl-sixth-surface.svg` is a *render* of the `.excalidraw`
|
|
50
|
+
— if you edit the source, re-render or say loudly in the commit that the render is
|
|
51
|
+
stale.
|
|
52
|
+
|
|
53
|
+
## Layout truth
|
|
54
|
+
|
|
55
|
+
`src/okl/` is the package (store/core/client/cli/service/mcp + scaffold templates);
|
|
56
|
+
`seed/` is the curated 161-node corpus (real lessons, real project names — deliberate);
|
|
57
|
+
`evals/` is the A/B harness and receipts; `docs/posts/` is the 3-part write-up;
|
|
58
|
+
`e2e/` (gitignored) holds scratch repos for end-to-end loop tests.
|
|
59
|
+
|
|
60
|
+
This file stays lean — always-on rules only. Everything conditionally relevant belongs
|
|
61
|
+
in the store, where the briefing selects it per task. If you're about to add a section
|
|
62
|
+
here, ask whether it should be an `okl record` instead. It usually should.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# okl — repo instructions
|
|
2
|
+
|
|
3
|
+
Read [evals/REPORT.md](evals/REPORT.md) before touching anything measurement-adjacent —
|
|
4
|
+
it is the most load-bearing document in the repo (method, results, threats to validity).
|
|
5
|
+
|
|
6
|
+
## The loop is LIVE in this repo
|
|
7
|
+
|
|
8
|
+
The hooks fire on your own session: `UserPromptSubmit` injects the store's briefing into
|
|
9
|
+
your context before you start; `Stop` blocks your first stop to ask what was learned.
|
|
10
|
+
Answer it honestly — record with a deliberate scope (`org` spreads to every repo,
|
|
11
|
+
`repo` stays local) and tags from the closed vocabulary in `store.KNOWN_TAGS`. Growing
|
|
12
|
+
that vocabulary is an edit to the set plus a note in the tags ADR, never an ad-hoc tag.
|
|
13
|
+
|
|
14
|
+
- **Verification is evidence-based**: `okl verify <id> --run "<check>" --expect "<signal>"`.
|
|
15
|
+
Never re-record with `--verified` to clear drift — run the check.
|
|
16
|
+
- **After changing files a rule governs, `okl drift` goes red on purpose.** Re-verify
|
|
17
|
+
the affected nodes (their tests are usually the right `--run`) before finishing.
|
|
18
|
+
- The local store (`.okl/okl.db`, gitignored) should hold all 11 seed files plus
|
|
19
|
+
recorded nodes; `okl seed seed/` loads the `*-defects.json` set, while
|
|
20
|
+
`dotnet-{canon,decisions,review-surfaces}.json` and `frontend-canon.json` load explicitly.
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pytest -q # full suite; must be green before any commit
|
|
26
|
+
ruff check . # lint (config in pyproject.toml)
|
|
27
|
+
python3 evals/ab_harness.py --dry-run # eval harness; see evals/README.md before running live
|
|
28
|
+
okl drift # rules whose governed source changed after verification
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Rules that are enforced (and why)
|
|
32
|
+
|
|
33
|
+
- **Mirror files are byte-identical, test-enforced**: `ci/okl-verify.yml` ==
|
|
34
|
+
`.github/workflows/okl-verify.yml` == `src/okl/scaffold/ci/okl-verify.yml`, and
|
|
35
|
+
`hooks/*.sh` == `src/okl/scaffold/hooks/*.sh`. The scaffold copies are what consumers
|
|
36
|
+
receive; the repo copies are the dogfood. Edit ONE, copy to the others in the same
|
|
37
|
+
change — `tests/test_scaffold.py::test_mirror_files_identical` fails otherwise.
|
|
38
|
+
- **ruff `E702` is ignored deliberately** (semicolon one-liners): the tests use a
|
|
39
|
+
compact setup style throughout; re-enabling it is a repo-wide style decision, not a
|
|
40
|
+
cleanup.
|
|
41
|
+
- **Audits read the repo, not the working tree**: any gate/check that scans content
|
|
42
|
+
must scan `git ls-files` output (committed reality), never the dirty working tree —
|
|
43
|
+
scanning the tree makes an uncommitted edit pass or fail an audit that main would
|
|
44
|
+
answer differently. (Bit the .NET platform twice.)
|
|
45
|
+
- **Eval integrity**: the harness refuses judge==generator; never quote a number from a
|
|
46
|
+
run marked RESULTS NOT USABLE; every cited figure needs a committed receipt in
|
|
47
|
+
`evals/results/`.
|
|
48
|
+
- **The diagram and README move with the system**: they are drift-enrolled
|
|
49
|
+
(`n_b550ba9c5c8a`). `docs/okl-sixth-surface.svg` is a *render* of the `.excalidraw`
|
|
50
|
+
— if you edit the source, re-render or say loudly in the commit that the render is
|
|
51
|
+
stale.
|
|
52
|
+
|
|
53
|
+
## Layout truth
|
|
54
|
+
|
|
55
|
+
`src/okl/` is the package (store/core/client/cli/service/mcp + scaffold templates);
|
|
56
|
+
`seed/` is the curated 161-node corpus (real lessons, real project names — deliberate);
|
|
57
|
+
`evals/` is the A/B harness and receipts; `docs/posts/` is the 3-part write-up;
|
|
58
|
+
`e2e/` (gitignored) holds scratch repos for end-to-end loop tests.
|
|
59
|
+
|
|
60
|
+
This file stays lean — always-on rules only. Everything conditionally relevant belongs
|
|
61
|
+
in the store, where the briefing selects it per task. If you're about to add a section
|
|
62
|
+
here, ask whether it should be an `okl record` instead. It usually should.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joshua Dell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|