kea-brain 1.0.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.
- kea_brain-1.0.1/.claude-plugin/marketplace.json +19 -0
- kea_brain-1.0.1/.claude-plugin/plugin.json +14 -0
- kea_brain-1.0.1/.editorconfig +34 -0
- kea_brain-1.0.1/.github/ISSUE_TEMPLATE/bug_report.yml +25 -0
- kea_brain-1.0.1/.github/ISSUE_TEMPLATE/config.yml +6 -0
- kea_brain-1.0.1/.github/ISSUE_TEMPLATE/feature_request.yml +16 -0
- kea_brain-1.0.1/.github/dependabot.yml +11 -0
- kea_brain-1.0.1/.github/pull_request_template.md +20 -0
- kea_brain-1.0.1/.github/workflows/dev.yml +70 -0
- kea_brain-1.0.1/.github/workflows/python-checks.yml +107 -0
- kea_brain-1.0.1/.github/workflows/python-tests.yml +52 -0
- kea_brain-1.0.1/.github/workflows/release.yml +67 -0
- kea_brain-1.0.1/.gitignore +19 -0
- kea_brain-1.0.1/.mcp.json +15 -0
- kea_brain-1.0.1/AGENTS.md +58 -0
- kea_brain-1.0.1/CHANGELOG.md +52 -0
- kea_brain-1.0.1/CODE_OF_CONDUCT.md +6 -0
- kea_brain-1.0.1/CONTRIBUTING.md +34 -0
- kea_brain-1.0.1/Dockerfile +20 -0
- kea_brain-1.0.1/LICENSE +21 -0
- kea_brain-1.0.1/Makefile +137 -0
- kea_brain-1.0.1/PKG-INFO +307 -0
- kea_brain-1.0.1/README.md +265 -0
- kea_brain-1.0.1/SECURITY.md +36 -0
- kea_brain-1.0.1/docs/MANUAL.md +366 -0
- kea_brain-1.0.1/docs/brand/mark.svg +11 -0
- kea_brain-1.0.1/docs/images/banner-dark.png +0 -0
- kea_brain-1.0.1/docs/images/banner-light.png +0 -0
- kea_brain-1.0.1/docs/images/social-preview.png +0 -0
- kea_brain-1.0.1/llms.txt +20 -0
- kea_brain-1.0.1/pyproject.toml +130 -0
- kea_brain-1.0.1/scripts/bench.py +67 -0
- kea_brain-1.0.1/scripts/build_man.py +153 -0
- kea_brain-1.0.1/setup.cfg +20 -0
- kea_brain-1.0.1/skills/kea/SKILL.md +75 -0
- kea_brain-1.0.1/skills/kea-council/SKILL.md +47 -0
- kea_brain-1.0.1/skills/kea-frameworks/SKILL.md +32 -0
- kea_brain-1.0.1/src/kea/__init__.py +8 -0
- kea_brain-1.0.1/src/kea/__main__.py +3 -0
- kea_brain-1.0.1/src/kea/_version.py +1 -0
- kea_brain-1.0.1/src/kea/brain.py +506 -0
- kea_brain-1.0.1/src/kea/cli.py +1251 -0
- kea_brain-1.0.1/src/kea/council.py +630 -0
- kea_brain-1.0.1/src/kea/data/MANUAL.md +366 -0
- kea_brain-1.0.1/src/kea/data/example/DECISIONS.md +36 -0
- kea_brain-1.0.1/src/kea/data/example/IDEAS.md +16 -0
- kea_brain-1.0.1/src/kea/data/example/METRICS.md +13 -0
- kea_brain-1.0.1/src/kea/data/example/PREDICTIONS.md +68 -0
- kea_brain-1.0.1/src/kea/data/example/ROADMAP.md +27 -0
- kea_brain-1.0.1/src/kea/data/example/STATE.md +42 -0
- kea_brain-1.0.1/src/kea/data/example/frameworks/INDEX.md +7 -0
- kea_brain-1.0.1/src/kea/data/example/frameworks/constraints.md +94 -0
- kea_brain-1.0.1/src/kea/data/example/journal/wholesale-samples.md +11 -0
- kea_brain-1.0.1/src/kea/data/example/plans/second-cafe/00-proposal.md +64 -0
- kea_brain-1.0.1/src/kea/data/example/plans/second-cafe/01-review-questions.md +9 -0
- kea_brain-1.0.1/src/kea/data/example/plans/second-cafe/reviews/example_chair_your-agent.md +25 -0
- kea_brain-1.0.1/src/kea/data/example/plans/second-cafe/reviews/example_contrarian_gpt-oss-120b.md +26 -0
- kea_brain-1.0.1/src/kea/data/example/plans/second-cafe/reviews/example_operator_mistral-small-latest.md +26 -0
- kea_brain-1.0.1/src/kea/data/kea.1 +421 -0
- kea_brain-1.0.1/src/kea/data/skills/kea/SKILL.md +75 -0
- kea_brain-1.0.1/src/kea/data/skills/kea-council/SKILL.md +47 -0
- kea_brain-1.0.1/src/kea/data/skills/kea-frameworks/SKILL.md +32 -0
- kea_brain-1.0.1/src/kea/data/templates/AGENTS.md +63 -0
- kea_brain-1.0.1/src/kea/data/templates/CLAUDE.md +1 -0
- kea_brain-1.0.1/src/kea/data/templates/DECISIONS.md +9 -0
- kea_brain-1.0.1/src/kea/data/templates/IDEAS.md +8 -0
- kea_brain-1.0.1/src/kea/data/templates/LEARNING.md +17 -0
- kea_brain-1.0.1/src/kea/data/templates/METRICS.md +8 -0
- kea_brain-1.0.1/src/kea/data/templates/PREDICTIONS.md +11 -0
- kea_brain-1.0.1/src/kea/data/templates/README.md +21 -0
- kea_brain-1.0.1/src/kea/data/templates/ROADMAP.md +28 -0
- kea_brain-1.0.1/src/kea/data/templates/SOURCES.md +22 -0
- kea_brain-1.0.1/src/kea/data/templates/STATE.md +23 -0
- kea_brain-1.0.1/src/kea/data/templates/VOICE.md +16 -0
- kea_brain-1.0.1/src/kea/data/templates/council/PROTOCOL.md +69 -0
- kea_brain-1.0.1/src/kea/data/templates/council/roster.toml +80 -0
- kea_brain-1.0.1/src/kea/data/templates/frameworks/INDEX.md +16 -0
- kea_brain-1.0.1/src/kea/data/templates/frameworks/_TEMPLATE.md +80 -0
- kea_brain-1.0.1/src/kea/data/templates/gitignore +6 -0
- kea_brain-1.0.1/src/kea/data/templates/journal/README.md +4 -0
- kea_brain-1.0.1/src/kea/data/templates/kea.toml +27 -0
- kea_brain-1.0.1/src/kea/data/templates/plans/_template/00-proposal.md +79 -0
- kea_brain-1.0.1/src/kea/data/templates/plans/_template/01-review-questions.md +36 -0
- kea_brain-1.0.1/src/kea/data/templates/plans/_template/20-production-plan.md +44 -0
- kea_brain-1.0.1/src/kea/data/templates/plans/_template/30-execution-log.md +23 -0
- kea_brain-1.0.1/src/kea/digest.py +210 -0
- kea_brain-1.0.1/src/kea/ingest.py +1014 -0
- kea_brain-1.0.1/src/kea/ledger.py +913 -0
- kea_brain-1.0.1/src/kea/markdown.py +431 -0
- kea_brain-1.0.1/src/kea/mcp.py +756 -0
- kea_brain-1.0.1/src/kea/providers.py +333 -0
- kea_brain-1.0.1/src/kea/py.typed +0 -0
- kea_brain-1.0.1/src/kea/redact.py +517 -0
- kea_brain-1.0.1/src/kea/skills.py +92 -0
- kea_brain-1.0.1/src/kea/store.py +499 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/PKG-INFO +307 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/SOURCES.txt +115 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/dependency_links.txt +1 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/entry_points.txt +2 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/requires.txt +14 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/scm_file_list.json +110 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/scm_version.json +8 -0
- kea_brain-1.0.1/src/kea_brain.egg-info/top_level.txt +1 -0
- kea_brain-1.0.1/tests/conftest.py +66 -0
- kea_brain-1.0.1/tests/kea/test_brain.py +109 -0
- kea_brain-1.0.1/tests/kea/test_cli.py +172 -0
- kea_brain-1.0.1/tests/kea/test_council.py +230 -0
- kea_brain-1.0.1/tests/kea/test_digest.py +67 -0
- kea_brain-1.0.1/tests/kea/test_hardening.py +1399 -0
- kea_brain-1.0.1/tests/kea/test_ingest.py +363 -0
- kea_brain-1.0.1/tests/kea/test_ledger.py +183 -0
- kea_brain-1.0.1/tests/kea/test_markdown.py +108 -0
- kea_brain-1.0.1/tests/kea/test_mcp.py +116 -0
- kea_brain-1.0.1/tests/kea/test_redact.py +53 -0
- kea_brain-1.0.1/tests/kea/test_redact_corpus.py +296 -0
- kea_brain-1.0.1/tests/kea/test_skills.py +44 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
|
|
3
|
+
"name": "kea",
|
|
4
|
+
"description": "kea: a second brain that checks its facts, for you and your agents.",
|
|
5
|
+
"owner": {
|
|
6
|
+
"name": "James Phillip Sanders",
|
|
7
|
+
"email": "hello@jamesphillipsanders.com"
|
|
8
|
+
},
|
|
9
|
+
"plugins": [
|
|
10
|
+
{
|
|
11
|
+
"name": "kea",
|
|
12
|
+
"description": "Sourced facts, decisions with revisit dates, scored predictions, a council of rival models and local search over your AI sessions: three skills and an MCP server.",
|
|
13
|
+
"version": "1.0.1",
|
|
14
|
+
"source": "./",
|
|
15
|
+
"category": "productivity",
|
|
16
|
+
"homepage": "https://github.com/jpsanders/kea"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kea",
|
|
3
|
+
"description": "A second brain that checks its facts: sourced facts, decisions with revisit dates, scored predictions, a council of rival AI models, and local search over your AI sessions. Three skills and an MCP server.",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "James Phillip Sanders",
|
|
7
|
+
"email": "hello@jamesphillipsanders.com",
|
|
8
|
+
"url": "https://jamesphillipsanders.com"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/jpsanders/kea",
|
|
11
|
+
"repository": "https://github.com/jpsanders/kea",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": ["second-brain", "memory", "decisions", "predictions", "calibration", "council", "mcp", "search", "pkm"]
|
|
14
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*.{sh,py}]
|
|
4
|
+
indent_style = space
|
|
5
|
+
indent_size = 4
|
|
6
|
+
tab_width = 4
|
|
7
|
+
end_of_line = lf
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
max_line_length = 120
|
|
11
|
+
|
|
12
|
+
[*.{yaml,yml,toml}]
|
|
13
|
+
indent_style = space
|
|
14
|
+
indent_size = 2
|
|
15
|
+
tab_width = 2
|
|
16
|
+
end_of_line = lf
|
|
17
|
+
trim_trailing_whitespace = true
|
|
18
|
+
insert_final_newline = true
|
|
19
|
+
max_line_length = 120
|
|
20
|
+
|
|
21
|
+
[*.md]
|
|
22
|
+
trim_trailing_whitespace = true
|
|
23
|
+
max_line_length = 120
|
|
24
|
+
insert_final_newline = true
|
|
25
|
+
|
|
26
|
+
[*.json]
|
|
27
|
+
indent_style = space
|
|
28
|
+
indent_size = 2
|
|
29
|
+
end_of_line = lf
|
|
30
|
+
insert_final_newline = true
|
|
31
|
+
|
|
32
|
+
# Badge rows, the skill front matter and generated roff carry long lines by design
|
|
33
|
+
[{SKILL.md,*.1,README.md}]
|
|
34
|
+
max_line_length = off
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
description: A command that did not do what the manual says
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: what
|
|
8
|
+
attributes:
|
|
9
|
+
label: What happened
|
|
10
|
+
description: The command you ran, what it did, and what you expected instead.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: output
|
|
15
|
+
attributes:
|
|
16
|
+
label: Output
|
|
17
|
+
description: The output, ideally with --json. Remove anything private from your brain first.
|
|
18
|
+
render: text
|
|
19
|
+
- type: input
|
|
20
|
+
id: version
|
|
21
|
+
attributes:
|
|
22
|
+
label: kea, Python and operating system
|
|
23
|
+
placeholder: kea 1.0.1, Python 3.15.2 on Ubuntu 26.04
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
description: A source to ingest, a provider, a check, or a command kea should have
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: problem
|
|
8
|
+
attributes:
|
|
9
|
+
label: The problem
|
|
10
|
+
description: What you do by hand today, or what your agent gets wrong without it.
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: idea
|
|
15
|
+
attributes:
|
|
16
|
+
label: What would help
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
### Description
|
|
2
|
+
<!--- Provide a brief description of the changes introduced by this pull request -->
|
|
3
|
+
|
|
4
|
+
### Reference
|
|
5
|
+
<!--- Provide the related ticket(s) or issue id(s) this PR addresses -->
|
|
6
|
+
**Ticket:**
|
|
7
|
+
|
|
8
|
+
### Additional Notes
|
|
9
|
+
<!--- Add any additional notes or comments for the reviewers (test instructions, examples, screenshots etc) -->
|
|
10
|
+
|
|
11
|
+
### Checklist
|
|
12
|
+
<!--- Use this checklist to make sure you haven't missed anything -->
|
|
13
|
+
|
|
14
|
+
- [ ] Related tests have been added or updated, (if applicable)
|
|
15
|
+
- [ ] Updated documentation (if applicable)
|
|
16
|
+
- [ ] All checks and tests passed locally (`make checks`)
|
|
17
|
+
- [ ] All checks and tests passed in CI
|
|
18
|
+
- [ ] The branch is current with the base branch
|
|
19
|
+
- [ ] PR has a clean commit history
|
|
20
|
+
- [ ] Examples/additional configuration notes added to PR description (if applicable)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- 'main'
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- '*'
|
|
11
|
+
# Run CI manually
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
lint:
|
|
19
|
+
uses: "./.github/workflows/python-checks.yml"
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.15"
|
|
22
|
+
|
|
23
|
+
test:
|
|
24
|
+
needs: lint
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
os: ["ubuntu-latest", "macos-latest"]
|
|
29
|
+
uses: "./.github/workflows/python-tests.yml"
|
|
30
|
+
with:
|
|
31
|
+
os: ${{ matrix.os }}
|
|
32
|
+
python-version: "3.15"
|
|
33
|
+
|
|
34
|
+
# Proves the built wheel installs on its own and works, with no source tree around it.
|
|
35
|
+
package:
|
|
36
|
+
needs: test
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- name: "Checkout code"
|
|
40
|
+
uses: actions/checkout@v7
|
|
41
|
+
with:
|
|
42
|
+
fetch-depth: 0
|
|
43
|
+
|
|
44
|
+
- name: "Set up Python"
|
|
45
|
+
uses: actions/setup-python@v7
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.15"
|
|
48
|
+
|
|
49
|
+
- name: "Build the wheel and the sdist"
|
|
50
|
+
run: |
|
|
51
|
+
python -m pip install build
|
|
52
|
+
python -m build -o dist
|
|
53
|
+
|
|
54
|
+
- name: "Install the wheel in a clean environment and use it"
|
|
55
|
+
run: |
|
|
56
|
+
python -m venv /tmp/clean
|
|
57
|
+
/tmp/clean/bin/pip install dist/*.whl
|
|
58
|
+
cd /tmp
|
|
59
|
+
export XDG_CONFIG_HOME=/tmp/config
|
|
60
|
+
/tmp/clean/bin/kea --version
|
|
61
|
+
/tmp/clean/bin/kea init /tmp/demo --example --no-git
|
|
62
|
+
cd /tmp/demo
|
|
63
|
+
/tmp/clean/bin/kea status
|
|
64
|
+
/tmp/clean/bin/kea calibration --json
|
|
65
|
+
/tmp/clean/bin/kea synth second-cafe
|
|
66
|
+
/tmp/clean/bin/kea search wholesale --limit 1
|
|
67
|
+
/tmp/clean/bin/kea check
|
|
68
|
+
/tmp/clean/bin/kea guide | head -3
|
|
69
|
+
/tmp/clean/bin/kea man --raw | head -1
|
|
70
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | /tmp/clean/bin/kea mcp | head -c 200
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python-checks
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
python-version:
|
|
8
|
+
type: string
|
|
9
|
+
default: "3.15"
|
|
10
|
+
|
|
11
|
+
cache-dependency-path:
|
|
12
|
+
type: string
|
|
13
|
+
default: "pyproject.toml"
|
|
14
|
+
|
|
15
|
+
enable-ec:
|
|
16
|
+
type: boolean
|
|
17
|
+
default: true
|
|
18
|
+
|
|
19
|
+
enable-black:
|
|
20
|
+
type: boolean
|
|
21
|
+
default: true
|
|
22
|
+
|
|
23
|
+
enable-isort:
|
|
24
|
+
type: boolean
|
|
25
|
+
default: true
|
|
26
|
+
|
|
27
|
+
enable-lint:
|
|
28
|
+
type: boolean
|
|
29
|
+
default: true
|
|
30
|
+
|
|
31
|
+
enable-docstyle:
|
|
32
|
+
type: boolean
|
|
33
|
+
default: true
|
|
34
|
+
|
|
35
|
+
enable-mypy:
|
|
36
|
+
type: boolean
|
|
37
|
+
default: true
|
|
38
|
+
|
|
39
|
+
enable-bandit:
|
|
40
|
+
type: boolean
|
|
41
|
+
default: true
|
|
42
|
+
|
|
43
|
+
checkout-fetch-depth:
|
|
44
|
+
type: number
|
|
45
|
+
default: 1
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
checks:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- name: "Checkout code"
|
|
54
|
+
uses: actions/checkout@v7
|
|
55
|
+
with:
|
|
56
|
+
fetch-depth: ${{ inputs.checkout-fetch-depth }}
|
|
57
|
+
|
|
58
|
+
- name: "Set up Python"
|
|
59
|
+
uses: actions/setup-python@v7
|
|
60
|
+
with:
|
|
61
|
+
python-version: ${{ inputs.python-version }}
|
|
62
|
+
cache: 'pip'
|
|
63
|
+
cache-dependency-path: ${{ inputs.cache-dependency-path }}
|
|
64
|
+
|
|
65
|
+
- name: "Install dependencies"
|
|
66
|
+
run: |
|
|
67
|
+
make init-dev
|
|
68
|
+
|
|
69
|
+
- name: "Run editorconfig-checker style checks"
|
|
70
|
+
if: ${{ inputs.enable-ec && (success() || failure()) }}
|
|
71
|
+
run: |
|
|
72
|
+
make ec
|
|
73
|
+
|
|
74
|
+
- name: "Run black style checks"
|
|
75
|
+
if: ${{ inputs.enable-black && (success() || failure()) }}
|
|
76
|
+
run: |
|
|
77
|
+
make black-check
|
|
78
|
+
|
|
79
|
+
- name: "Run isort import checks"
|
|
80
|
+
if: ${{ inputs.enable-isort && (success() || failure()) }}
|
|
81
|
+
run: |
|
|
82
|
+
make isort-check
|
|
83
|
+
|
|
84
|
+
- name: "Run bandit security checks"
|
|
85
|
+
if: ${{ inputs.enable-bandit && (success() || failure()) }}
|
|
86
|
+
run: |
|
|
87
|
+
make bandit
|
|
88
|
+
|
|
89
|
+
- name: "Run flake8 lint checks"
|
|
90
|
+
if: ${{ inputs.enable-lint && (success() || failure()) }}
|
|
91
|
+
run: |
|
|
92
|
+
make lint
|
|
93
|
+
|
|
94
|
+
- name: "Run docstring checks"
|
|
95
|
+
if: ${{ inputs.enable-docstyle && (success() || failure()) }}
|
|
96
|
+
run: |
|
|
97
|
+
make docstyle
|
|
98
|
+
|
|
99
|
+
- name: "Run mypy static type checks"
|
|
100
|
+
if: ${{ inputs.enable-mypy && (success() || failure()) }}
|
|
101
|
+
run: |
|
|
102
|
+
make mypy
|
|
103
|
+
|
|
104
|
+
- name: "Check the man page, the packaged manual and the packaged skills are up to date"
|
|
105
|
+
if: ${{ success() || failure() }}
|
|
106
|
+
run: |
|
|
107
|
+
make man-check
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python-tests
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
python-version:
|
|
8
|
+
type: string
|
|
9
|
+
default: "3.15"
|
|
10
|
+
|
|
11
|
+
os:
|
|
12
|
+
type: string
|
|
13
|
+
default: "ubuntu-latest"
|
|
14
|
+
|
|
15
|
+
cache-dependency-path:
|
|
16
|
+
type: string
|
|
17
|
+
default: "pyproject.toml"
|
|
18
|
+
|
|
19
|
+
enable-lfs:
|
|
20
|
+
type: boolean
|
|
21
|
+
default: false
|
|
22
|
+
|
|
23
|
+
checkout-fetch-depth:
|
|
24
|
+
type: number
|
|
25
|
+
default: 1
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
test:
|
|
30
|
+
runs-on: ${{ inputs.os }}
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: "Checkout code"
|
|
34
|
+
uses: actions/checkout@v7
|
|
35
|
+
with:
|
|
36
|
+
lfs: ${{ inputs.enable-lfs }}
|
|
37
|
+
fetch-depth: ${{ inputs.checkout-fetch-depth }}
|
|
38
|
+
|
|
39
|
+
- name: "Set up Python"
|
|
40
|
+
uses: actions/setup-python@v7
|
|
41
|
+
with:
|
|
42
|
+
python-version: ${{ inputs.python-version }}
|
|
43
|
+
cache: 'pip'
|
|
44
|
+
cache-dependency-path: ${{ inputs.cache-dependency-path }}
|
|
45
|
+
|
|
46
|
+
- name: "Install dependencies"
|
|
47
|
+
run: |
|
|
48
|
+
make init-dev
|
|
49
|
+
|
|
50
|
+
- name: "Run tests"
|
|
51
|
+
run: |
|
|
52
|
+
make pytest
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
release:
|
|
6
|
+
types: [published]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
assets:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: "Checkout the tag"
|
|
16
|
+
uses: actions/checkout@v7
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- name: "Set up Python"
|
|
21
|
+
uses: actions/setup-python@v7
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.15"
|
|
24
|
+
|
|
25
|
+
- name: "Check the README badge, the plugin, the MCP config and the changelog all name this version"
|
|
26
|
+
env:
|
|
27
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
28
|
+
run: |
|
|
29
|
+
grep -q "badge/release-${TAG}-" README.md
|
|
30
|
+
grep -q "\"version\": \"${TAG}\"" .claude-plugin/plugin.json
|
|
31
|
+
grep -q "\"version\": \"${TAG}\"" .claude-plugin/marketplace.json
|
|
32
|
+
grep -q "kea-brain==${TAG}\"" .mcp.json
|
|
33
|
+
grep -q "^## ${TAG} " CHANGELOG.md
|
|
34
|
+
|
|
35
|
+
- name: "Build the wheel and the sdist"
|
|
36
|
+
run: |
|
|
37
|
+
python -m pip install build
|
|
38
|
+
python -m build -o dist
|
|
39
|
+
test -f "dist/kea_brain-${{ github.event.release.tag_name }}-py3-none-any.whl"
|
|
40
|
+
|
|
41
|
+
- name: "Attach them to the release"
|
|
42
|
+
env:
|
|
43
|
+
GH_TOKEN: ${{ github.token }}
|
|
44
|
+
run: gh release upload "${{ github.event.release.tag_name }}" dist/* --clobber
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# Publishes kea-brain to PyPI through trusted publishing: PyPI trusts this workflow in this repository, so no token
|
|
48
|
+
# is stored anywhere. Off until the repository variable PUBLISH_TO_PYPI is "true".
|
|
49
|
+
pypi:
|
|
50
|
+
needs: assets
|
|
51
|
+
if: ${{ vars.PUBLISH_TO_PYPI == 'true' }}
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment:
|
|
54
|
+
name: pypi
|
|
55
|
+
url: https://pypi.org/project/kea-brain/
|
|
56
|
+
permissions:
|
|
57
|
+
contents: read
|
|
58
|
+
id-token: write
|
|
59
|
+
steps:
|
|
60
|
+
- name: "Download the wheel and the sdist the release now carries"
|
|
61
|
+
env:
|
|
62
|
+
GH_TOKEN: ${{ github.token }}
|
|
63
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
64
|
+
run: gh release download "$TAG" -R "${{ github.repository }}" -D dist -p "kea_brain-*"
|
|
65
|
+
|
|
66
|
+
- name: "Publish to PyPI"
|
|
67
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Make text search tools know that these "hidden" directories contain code
|
|
2
|
+
!/.github/
|
|
3
|
+
|
|
4
|
+
# Caches and build artifacts
|
|
5
|
+
__pycache__
|
|
6
|
+
/build
|
|
7
|
+
.terraform
|
|
8
|
+
.terraform.lock.hcl
|
|
9
|
+
|
|
10
|
+
# Per-user config such as the following should generally be stored in ~/.gitignore rather than here
|
|
11
|
+
#.python-version
|
|
12
|
+
#.envrc
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Local virtual environment and editor state
|
|
16
|
+
/.venv
|
|
17
|
+
/.idea
|
|
18
|
+
/src/*.egg-info
|
|
19
|
+
/src/kea/_version.py
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Instructions for AI coding agents working on kea itself. People will find them useful too. (To work inside a kea
|
|
4
|
+
brain, read that brain's own AGENTS.md, or the skill in `skills/kea/SKILL.md`.)
|
|
5
|
+
|
|
6
|
+
## Commands
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
make init-dev # install kea and the development tools into the active environment (Python 3.15)
|
|
10
|
+
make format # apply black and isort
|
|
11
|
+
make checks # every check CI runs, in CI's order; run it before you say a change is done
|
|
12
|
+
make man # rebuild the man page, the packaged manual and the packaged skills
|
|
13
|
+
make bench # start up and command times
|
|
14
|
+
make demo # the example brain in /tmp/kea-demo
|
|
15
|
+
make build # wheel and sdist into build/dist
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Layout
|
|
19
|
+
|
|
20
|
+
```text
|
|
21
|
+
src/kea/cli.py the command line: one cmd_* function per command, lazy imports
|
|
22
|
+
src/kea/brain.py finding a brain, kea.toml, the clock, kea init
|
|
23
|
+
src/kea/markdown.py reading and writing ledger entries without touching other lines
|
|
24
|
+
src/kea/ledger.py facts, log, decisions, predictions, calibration, ideas, roadmap, check, status
|
|
25
|
+
src/kea/store.py the SQLite and FTS5 evidence index
|
|
26
|
+
src/kea/ingest.py the adapters: claude-code, codex, opencode, chatgpt, claude, git, docs, the brain
|
|
27
|
+
src/kea/redact.py the credential path denylist and secret redaction
|
|
28
|
+
src/kea/council.py plans, packets, the parallel council run, the synthesis scaffold
|
|
29
|
+
src/kea/providers.py OpenAI compatible, Gemini and Anthropic clients on urllib
|
|
30
|
+
src/kea/mcp.py the MCP server: tools, resources, prompts
|
|
31
|
+
src/kea/digest.py Claude Code transcripts as readable files
|
|
32
|
+
src/kea/skills.py installing the skills into agent folders
|
|
33
|
+
src/kea/data/ templates and example brains, plus generated files: MANUAL.md, kea.1, skills/
|
|
34
|
+
docs/MANUAL.md the one source for kea guide and the man page
|
|
35
|
+
skills/ the agent skills; make man copies them into the package
|
|
36
|
+
tests/kea/ pytest, one file per module
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Rules the checks enforce
|
|
40
|
+
|
|
41
|
+
- mypy runs in strict mode, on the tests too: every function has full type hints.
|
|
42
|
+
- Docstrings use the Sphinx style and darglint checks them. Private helpers (`_name`) need none.
|
|
43
|
+
- Imports are absolute. Lines are at most 120 characters in every file type, Markdown included.
|
|
44
|
+
- bandit fails on shell injection and string built SQL; a justified exception carries `# nosec <code>: <reason>`.
|
|
45
|
+
- `make checks` fails when `src/kea/data/MANUAL.md`, `kea.1` or the packaged skills are stale.
|
|
46
|
+
|
|
47
|
+
## Conventions the checks cannot see
|
|
48
|
+
|
|
49
|
+
- No runtime dependencies. The standard library only; that is a feature.
|
|
50
|
+
- Every command that prints data takes `--json` with stable fields. Exit 0 on success, 1 on failure, 2 on bad
|
|
51
|
+
arguments. Commands load their modules lazily so start up stays near 30 ms.
|
|
52
|
+
- kea never writes outside the brain, the per user config and the folders a command names. Ingest is read only.
|
|
53
|
+
- Nothing leaves the machine except `kea council`, which asks first.
|
|
54
|
+
- When a command or option changes, update `docs/MANUAL.md` and the skills in the same commit, then `make man`.
|
|
55
|
+
- Add an entry to `CHANGELOG.md` for anything a user would notice.
|
|
56
|
+
- Tags carry the bare version, `1.2.0`, never `v1.2.0`. The release workflow checks that the README badge, the
|
|
57
|
+
plugin files, `.mcp.json` and the changelog all name the tag.
|
|
58
|
+
- Never commit secrets, a real brain, `.env` files or anything from `build/`.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions follow [semantic versioning](https://semver.org). Tags carry the bare version, such as `1.0.0`.
|
|
4
|
+
|
|
5
|
+
## 1.0.1 (2026-11-14)
|
|
6
|
+
|
|
7
|
+
- kea is on PyPI as `kea-brain`: `uv tool install --python 3.15 kea-brain`, `pipx install kea-brain` or
|
|
8
|
+
`pip install kea-brain`. The command is still `kea`.
|
|
9
|
+
- The Claude Code plugin starts its MCP server from the PyPI wheel (`uvx --from kea-brain==1.0.1`), which is faster
|
|
10
|
+
than building from git.
|
|
11
|
+
- The release workflow publishes the wheel and the sdist that the GitHub release carries, through trusted publishing,
|
|
12
|
+
so no token is stored anywhere.
|
|
13
|
+
- A council seat whose server drops the connection while sending an error ends as a seat error with the HTTP status,
|
|
14
|
+
instead of an unhandled connection error; kea reads at most 4 KB of an error message.
|
|
15
|
+
|
|
16
|
+
## 1.0.0 (2026-11-14)
|
|
17
|
+
|
|
18
|
+
The first release.
|
|
19
|
+
|
|
20
|
+
- **The ledger**, in plain Markdown that people and agents edit side by side: facts with a source and a verified date
|
|
21
|
+
(`kea fact`), a dated log (`kea log`), decisions with a revisit date or trigger (`kea decide`, `kea revisit`),
|
|
22
|
+
predictions with a date and a confidence (`kea predict`, `kea score`), parked ideas and a roadmap with a section for
|
|
23
|
+
what waits for the owner.
|
|
24
|
+
- **Calibration**: `kea calibration` gives the Brier score, skill over a coin, and ten buckets of stated against
|
|
25
|
+
observed confidence.
|
|
26
|
+
- **Health**: `kea status` shows the whole brain and six health checks; `kea check` lints unsourced facts, facts past
|
|
27
|
+
their recheck date, malformed entries and overdue decisions and predictions, and exits 1 on errors.
|
|
28
|
+
- **The council**: `kea plan new`, `kea brief` (one hashed packet for every seat), `kea council` (every ready seat in
|
|
29
|
+
parallel, with per provider pacing, after asking before anything leaves the machine) and `kea synth` (verdicts,
|
|
30
|
+
convergence, splits and solo insights). Twelve providers preset, any OpenAI compatible server, Ollama and LM Studio
|
|
31
|
+
for local seats.
|
|
32
|
+
- **Evidence search**: `kea ingest` indexes Claude Code, Codex and OpenCode sessions, ChatGPT and Claude exports, git
|
|
33
|
+
history and folders of notes into SQLite with FTS5, incrementally, read only, with credential paths refused and
|
|
34
|
+
secrets redacted. `kea search`, `kea show` with provenance and context, `kea effort` for where attention went,
|
|
35
|
+
`kea forget`.
|
|
36
|
+
- **Agents**: an MCP server with 25 tools, five resources and three prompts; three skills installed into Claude Code,
|
|
37
|
+
Codex, OpenCode and `~/.agents` by `kea skill install`; a Claude Code plugin; `AGENTS.md` and `CLAUDE.md` in every
|
|
38
|
+
brain.
|
|
39
|
+
- **Safety**: nothing shaped like a key or token is stored in the index or sent in a packet (provider keys,
|
|
40
|
+
`NAME_API_KEY=` lines, passwords in URLs, private keys), and unmistakable key shapes never reach the ledger;
|
|
41
|
+
credential paths such as `.ssh`, `.env.local`, shell histories and `.pem` files are refused, symbolic links
|
|
42
|
+
included; the index is private to you; requests follow no redirects; agents on MCP can neither add sources nor send
|
|
43
|
+
a packet off the machine unless `kea.toml` allows it.
|
|
44
|
+
Before release, three independent review agents found 56 issues. Six further rounds, by two more agents each,
|
|
45
|
+
checked the fixes and found more problems in them. Every leak, crash and loss of data they confirmed is fixed, and
|
|
46
|
+
each code fix is pinned by a test.
|
|
47
|
+
- `kea digest` turns a Claude Code transcript into private readable files in the brain's `digests/` folder.
|
|
48
|
+
- `kea init --example` makes a complete example brain to explore. `kea init` on an existing brain puts back missing
|
|
49
|
+
files and changes nothing else; `--add` makes a brain beside files you already have, and `--force` keeps a backup
|
|
50
|
+
of every file it overwrites.
|
|
51
|
+
- A manual for people and agents: `kea guide`, `kea man`, `man kea` after `kea man --install`.
|
|
52
|
+
- Python 3.15, no dependencies, lazy imports: about 30 ms to start.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Code of conduct
|
|
2
|
+
|
|
3
|
+
This project follows the
|
|
4
|
+
[Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
5
|
+
Be kind, assume good faith, and keep discussion about the work. Report unacceptable behaviour to
|
|
6
|
+
hello@jamesphillipsanders.com; reports are handled in confidence.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Issues and pull requests are welcome.
|
|
4
|
+
|
|
5
|
+
## Set up
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
git clone https://github.com/jpsanders/kea && cd kea
|
|
9
|
+
python3.15 -m venv .venv && . .venv/bin/activate
|
|
10
|
+
make init-dev
|
|
11
|
+
make demo
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Before a pull request
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
make format # black and isort
|
|
18
|
+
make checks # every check CI runs, in the same order
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`make checks` runs isort, black, editorconfig-checker, darglint, flake8, mypy in strict mode, bandit, the manual and
|
|
22
|
+
skills freshness check and pytest with coverage. CI runs the same, then the tests on Linux and macOS, then installs
|
|
23
|
+
the built wheel in a clean environment and runs it against the example brain.
|
|
24
|
+
|
|
25
|
+
## Changing things
|
|
26
|
+
|
|
27
|
+
- **No dependencies.** kea runs on the standard library alone. A change that needs a package needs a very good reason.
|
|
28
|
+
- **The manual** is `docs/MANUAL.md` and **the skills** are `skills/*/SKILL.md`. `make man` copies them into the
|
|
29
|
+
package and builds the man page; `make checks` fails while any copy is stale.
|
|
30
|
+
- **Templates** for new brains live in `src/kea/data/templates`, the example brain in `src/kea/data/example`. Keep
|
|
31
|
+
every line at 120 characters or fewer.
|
|
32
|
+
- **A new ingest source** is an adapter in `src/kea/ingest.py` that reads, never writes, passes every text through
|
|
33
|
+
`redact`, and comes with a test built on a small fake export.
|
|
34
|
+
- **Commits** are signed. Tags carry the bare version, `1.2.0`, never `v1.2.0`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
FROM python:3.15-slim
|
|
2
|
+
|
|
3
|
+
ARG USER=kea
|
|
4
|
+
|
|
5
|
+
# git lets kea ingest repositories; nothing else is needed at run time
|
|
6
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/* \
|
|
7
|
+
&& useradd -rms /bin/bash $USER
|
|
8
|
+
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
COPY --chown=$USER:$USER src src
|
|
11
|
+
COPY --chown=$USER:$USER pyproject.toml README.md LICENSE ./
|
|
12
|
+
RUN --mount=source=.git,target=.git,type=bind \
|
|
13
|
+
python3 -m pip install --no-cache-dir .
|
|
14
|
+
|
|
15
|
+
USER $USER
|
|
16
|
+
WORKDIR /brain
|
|
17
|
+
ENV KEA_BRAIN=/brain
|
|
18
|
+
# docker run --rm -it -v ~/brain:/brain kea status
|
|
19
|
+
ENTRYPOINT ["kea"]
|
|
20
|
+
CMD ["status"]
|