omind 10.3.4__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.
- omind-10.3.4/.githooks/commit-msg +9 -0
- omind-10.3.4/.github/codeql/codeql-config.yml +9 -0
- omind-10.3.4/.github/dependabot.yml +21 -0
- omind-10.3.4/.github/workflows/codeql.yml +35 -0
- omind-10.3.4/.github/workflows/publish.yml +80 -0
- omind-10.3.4/.github/workflows/test.yml +246 -0
- omind-10.3.4/.gitignore +22 -0
- omind-10.3.4/.gitleaks.toml +19 -0
- omind-10.3.4/.woodpecker.yml +14 -0
- omind-10.3.4/AGENTS.md +156 -0
- omind-10.3.4/BACKLOG.md +957 -0
- omind-10.3.4/CHANGELOG.md +4826 -0
- omind-10.3.4/CONTRIBUTING.md +171 -0
- omind-10.3.4/LICENSE +201 -0
- omind-10.3.4/LessonsLearned.md +308 -0
- omind-10.3.4/PKG-INFO +794 -0
- omind-10.3.4/README.md +742 -0
- omind-10.3.4/SECURITY.md +33 -0
- omind-10.3.4/conformance.toml +18 -0
- omind-10.3.4/docs/audit.md +120 -0
- omind-10.3.4/docs/conveyor-factory.md +120 -0
- omind-10.3.4/docs/design/2026-08-27-roadmap-consensus.md +84 -0
- omind-10.3.4/docs/graph-demo/README.md +33 -0
- omind-10.3.4/docs/graph-demo/make_demo_vault.py +45 -0
- omind-10.3.4/docs/graph-demo/render_graph.py +71 -0
- omind-10.3.4/docs/graph.png +0 -0
- omind-10.3.4/docs/install-verification.md +211 -0
- omind-10.3.4/docs/manual-setup.md +155 -0
- omind-10.3.4/docs/mesh-ops.md +111 -0
- omind-10.3.4/docs/mesh.md +288 -0
- omind-10.3.4/docs/needle.md +94 -0
- omind-10.3.4/docs/retrieval.md +349 -0
- omind-10.3.4/docs/reviews/2026-08-27-multi-agent-review.md +298 -0
- omind-10.3.4/docs/screenshot.png +0 -0
- omind-10.3.4/docs/self-update.md +92 -0
- omind-10.3.4/docs/serve.md +112 -0
- omind-10.3.4/docs/troubleshooting.md +316 -0
- omind-10.3.4/e2e/README.md +105 -0
- omind-10.3.4/e2e/__init__.py +3 -0
- omind-10.3.4/e2e/conftest.py +57 -0
- omind-10.3.4/e2e/nodes.py +164 -0
- omind-10.3.4/e2e/providers.py +275 -0
- omind-10.3.4/e2e/sweep.py +34 -0
- omind-10.3.4/e2e/test_bootstrap.py +28 -0
- omind-10.3.4/e2e/test_mesh_sync.py +78 -0
- omind-10.3.4/e2e/test_provider_smoke.py +15 -0
- omind-10.3.4/extras/README.md +35 -0
- omind-10.3.4/extras/omi_enforce.py +139 -0
- omind-10.3.4/extras/omi_write.py +106 -0
- omind-10.3.4/pyproject.toml +144 -0
- omind-10.3.4/scripts/bootstrap.sh +190 -0
- omind-10.3.4/scripts/check-attribution.sh +83 -0
- omind-10.3.4/scripts/stress_append_lock.py +69 -0
- omind-10.3.4/scripts/test.sh +22 -0
- omind-10.3.4/src/omind/__init__.py +5 -0
- omind-10.3.4/src/omind/__main__.py +8 -0
- omind-10.3.4/src/omind/_omi_enforce.py +139 -0
- omind-10.3.4/src/omind/access.py +226 -0
- omind-10.3.4/src/omind/adapters.py +364 -0
- omind-10.3.4/src/omind/agents.py +3895 -0
- omind-10.3.4/src/omind/ai_usage.py +790 -0
- omind-10.3.4/src/omind/audit.py +553 -0
- omind-10.3.4/src/omind/backup.py +576 -0
- omind-10.3.4/src/omind/bench.py +717 -0
- omind-10.3.4/src/omind/checkpoint.py +367 -0
- omind-10.3.4/src/omind/cli.py +2015 -0
- omind-10.3.4/src/omind/clock.py +64 -0
- omind-10.3.4/src/omind/compliance.py +393 -0
- omind-10.3.4/src/omind/consolidate.py +277 -0
- omind-10.3.4/src/omind/corpus.py +88 -0
- omind-10.3.4/src/omind/deadline.py +145 -0
- omind-10.3.4/src/omind/embed.py +209 -0
- omind-10.3.4/src/omind/entities.py +479 -0
- omind-10.3.4/src/omind/filelock.py +206 -0
- omind-10.3.4/src/omind/fleet-sudo.sh +37 -0
- omind-10.3.4/src/omind/git-fresh-base.sh +87 -0
- omind-10.3.4/src/omind/graph.py +391 -0
- omind-10.3.4/src/omind/guard.py +6098 -0
- omind-10.3.4/src/omind/harness.py +808 -0
- omind-10.3.4/src/omind/help_system.py +65 -0
- omind-10.3.4/src/omind/hooks.py +1037 -0
- omind-10.3.4/src/omind/journal.py +364 -0
- omind-10.3.4/src/omind/learn.py +166 -0
- omind-10.3.4/src/omind/lint.py +337 -0
- omind-10.3.4/src/omind/loopguard.py +244 -0
- omind-10.3.4/src/omind/maintain.py +192 -0
- omind-10.3.4/src/omind/merge.py +461 -0
- omind-10.3.4/src/omind/mesh.py +1209 -0
- omind-10.3.4/src/omind/model_http.py +89 -0
- omind-10.3.4/src/omind/namehints.py +729 -0
- omind-10.3.4/src/omind/needle.py +344 -0
- omind-10.3.4/src/omind/notes.py +80 -0
- omind-10.3.4/src/omind/okf.py +152 -0
- omind-10.3.4/src/omind/omi-gate-reset.sh +52 -0
- omind-10.3.4/src/omind/omi-guard-hermes.sh +98 -0
- omind-10.3.4/src/omind/omi-guard.dsh.js +390 -0
- omind-10.3.4/src/omind/omi-guard.opencode.js +56 -0
- omind-10.3.4/src/omind/omi-guard.sh +239 -0
- omind-10.3.4/src/omind/paths.py +137 -0
- omind-10.3.4/src/omind/policy.py +955 -0
- omind-10.3.4/src/omind/proc.py +88 -0
- omind-10.3.4/src/omind/provision.py +2764 -0
- omind-10.3.4/src/omind/quickstart.py +530 -0
- omind-10.3.4/src/omind/recall.py +166 -0
- omind-10.3.4/src/omind/retrieve.py +500 -0
- omind-10.3.4/src/omind/rules.py +1131 -0
- omind-10.3.4/src/omind/scope_guard.py +73 -0
- omind-10.3.4/src/omind/searchindex.py +2064 -0
- omind-10.3.4/src/omind/secret-output-guard.sh +138 -0
- omind-10.3.4/src/omind/seeds.py +405 -0
- omind-10.3.4/src/omind/server.py +743 -0
- omind-10.3.4/src/omind/skills/omind/SKILL.md +37 -0
- omind-10.3.4/src/omind/skills/omind/agents/openai.yaml +4 -0
- omind-10.3.4/src/omind/store.py +1835 -0
- omind-10.3.4/src/omind/timeline.py +323 -0
- omind-10.3.4/src/omind/transfer.py +347 -0
- omind-10.3.4/src/omind/txn.py +429 -0
- omind-10.3.4/src/omind/unwritten.py +129 -0
- omind-10.3.4/src/omind/update.py +728 -0
- omind-10.3.4/src/omind/verify.py +779 -0
- omind-10.3.4/src/omind/web/__init__.py +3 -0
- omind-10.3.4/src/omind/web/app.py +255 -0
- omind-10.3.4/src/omind/web/static/app.css +841 -0
- omind-10.3.4/src/omind/web/static/app.js +1062 -0
- omind-10.3.4/src/omind/web/static/graph.js +336 -0
- omind-10.3.4/src/omind/web/static/index.html +91 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/bricolagegrotesque-1c7e673e77.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/bricolagegrotesque-40c2cb34af.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/bricolagegrotesque-fdb6b064da.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-028edbf560.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-0a7197f9e2.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-acf87d8659.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-c8b23d7bdf.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-d2761cb6ca.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/jetbrainsmono-db1e206703.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-1c520e8540.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-2b5209ccd5.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-34eec9781a.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-72c495d39d.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-a6a2a4bf8d.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts/newsreader-f24c321523.woff2 +0 -0
- omind-10.3.4/src/omind/web/static/vendor/fonts.css +251 -0
- omind-10.3.4/src/omind/web/static/vendor/marked.min.js +69 -0
- omind-10.3.4/src/omind/web/static/vendor/purify.min.js +3 -0
- omind-10.3.4/src/omind/web/static/vendor/tailwind.css +2 -0
- omind-10.3.4/src/omind/web/tailwind/input.css +5 -0
- omind-10.3.4/src/omind/web/tailwind/tailwind.config.js +30 -0
- omind-10.3.4/src/omind/writecontext.py +463 -0
- omind-10.3.4/tests/conftest.py +259 -0
- omind-10.3.4/tests/test_access.py +106 -0
- omind-10.3.4/tests/test_adapters.py +803 -0
- omind-10.3.4/tests/test_agent_identity.py +75 -0
- omind-10.3.4/tests/test_agents.py +2203 -0
- omind-10.3.4/tests/test_ai_usage.py +368 -0
- omind-10.3.4/tests/test_audit.py +194 -0
- omind-10.3.4/tests/test_backup.py +453 -0
- omind-10.3.4/tests/test_bench.py +126 -0
- omind-10.3.4/tests/test_checkpoint.py +181 -0
- omind-10.3.4/tests/test_cli.py +317 -0
- omind-10.3.4/tests/test_cli_integration.py +323 -0
- omind-10.3.4/tests/test_clock.py +42 -0
- omind-10.3.4/tests/test_compliance.py +247 -0
- omind-10.3.4/tests/test_consolidate.py +113 -0
- omind-10.3.4/tests/test_corpus.py +65 -0
- omind-10.3.4/tests/test_embed.py +77 -0
- omind-10.3.4/tests/test_entities.py +397 -0
- omind-10.3.4/tests/test_filelock.py +214 -0
- omind-10.3.4/tests/test_graph.py +220 -0
- omind-10.3.4/tests/test_grok_client.py +336 -0
- omind-10.3.4/tests/test_guard.py +6251 -0
- omind-10.3.4/tests/test_harness.py +402 -0
- omind-10.3.4/tests/test_hook_shell_safety.py +149 -0
- omind-10.3.4/tests/test_hooks.py +992 -0
- omind-10.3.4/tests/test_journal.py +265 -0
- omind-10.3.4/tests/test_learn.py +94 -0
- omind-10.3.4/tests/test_lint.py +216 -0
- omind-10.3.4/tests/test_loopguard.py +140 -0
- omind-10.3.4/tests/test_maintain.py +127 -0
- omind-10.3.4/tests/test_merge.py +444 -0
- omind-10.3.4/tests/test_mesh.py +655 -0
- omind-10.3.4/tests/test_model_http.py +138 -0
- omind-10.3.4/tests/test_name_hints.py +495 -0
- omind-10.3.4/tests/test_name_timelines.py +729 -0
- omind-10.3.4/tests/test_needle.py +147 -0
- omind-10.3.4/tests/test_okf.py +188 -0
- omind-10.3.4/tests/test_policy.py +269 -0
- omind-10.3.4/tests/test_proc.py +78 -0
- omind-10.3.4/tests/test_provision.py +3005 -0
- omind-10.3.4/tests/test_quickstart.py +219 -0
- omind-10.3.4/tests/test_rare_term_preflight.py +138 -0
- omind-10.3.4/tests/test_retrieve.py +292 -0
- omind-10.3.4/tests/test_rules.py +1851 -0
- omind-10.3.4/tests/test_scope.py +78 -0
- omind-10.3.4/tests/test_scope_guard.py +49 -0
- omind-10.3.4/tests/test_searchindex.py +637 -0
- omind-10.3.4/tests/test_secret_output_guard.py +183 -0
- omind-10.3.4/tests/test_server.py +704 -0
- omind-10.3.4/tests/test_store.py +1117 -0
- omind-10.3.4/tests/test_transfer.py +258 -0
- omind-10.3.4/tests/test_txn.py +347 -0
- omind-10.3.4/tests/test_unwritten.py +76 -0
- omind-10.3.4/tests/test_update.py +520 -0
- omind-10.3.4/tests/test_verify.py +1184 -0
- omind-10.3.4/tests/test_web.py +306 -0
- omind-10.3.4/tests/test_windows_hook_shells.py +397 -0
- omind-10.3.4/tests/test_write_context.py +302 -0
- omind-10.3.4/uv.lock +4479 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
# Copyright 2026 Aaron K. Clark
|
|
4
|
+
#
|
|
5
|
+
# Reject a commit that declares no authorship. Enable with:
|
|
6
|
+
# git config core.hooksPath .githooks
|
|
7
|
+
set -eu
|
|
8
|
+
root=$(git rev-parse --show-toplevel)
|
|
9
|
+
exec "$root/scripts/check-attribution.sh" --message-file "$1"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python dependencies (pyproject.toml). omind's CI installs with pip.
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
open-pull-requests-limit: 5
|
|
9
|
+
groups:
|
|
10
|
+
python-deps:
|
|
11
|
+
patterns: ["*"]
|
|
12
|
+
|
|
13
|
+
# Keep the SHA-pinned GitHub Actions current.
|
|
14
|
+
- package-ecosystem: "github-actions"
|
|
15
|
+
directory: "/"
|
|
16
|
+
schedule:
|
|
17
|
+
interval: "weekly"
|
|
18
|
+
open-pull-requests-limit: 5
|
|
19
|
+
groups:
|
|
20
|
+
github-actions:
|
|
21
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
# Semantic static analysis (SAST) for the Python source. Runs on pushes/PRs to
|
|
4
|
+
# main and weekly, so new code paths and newly-disclosed query packs are caught.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: [main]
|
|
10
|
+
schedule:
|
|
11
|
+
- cron: "0 6 * * 1" # Mondays 06:00 UTC
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
analyze:
|
|
19
|
+
name: Analyze (python)
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
security-events: write
|
|
23
|
+
contents: read
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
- name: Initialize CodeQL
|
|
27
|
+
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
28
|
+
with:
|
|
29
|
+
languages: python
|
|
30
|
+
queries: security-and-quality
|
|
31
|
+
config-file: ./.github/codeql/codeql-config.yml
|
|
32
|
+
- name: Perform CodeQL analysis
|
|
33
|
+
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
|
|
34
|
+
with:
|
|
35
|
+
category: "/language:python"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
# Uploads omind to PyPI on every published GitHub release (#267).
|
|
3
|
+
#
|
|
4
|
+
# Auth: a PyPI API token stored as the `PYPI_API_TOKEN` secret of the `pypi`
|
|
5
|
+
# environment (Settings -> Environments -> pypi). Only the publish job runs in
|
|
6
|
+
# that environment, so only it can read the token. Rotate the token on pypi.org
|
|
7
|
+
# and re-set the secret; nothing else references it.
|
|
8
|
+
on:
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
dry_run:
|
|
14
|
+
description: Build and verify only; do not upload
|
|
15
|
+
type: boolean
|
|
16
|
+
default: true
|
|
17
|
+
|
|
18
|
+
# Least privilege: read-only everywhere; the token is scoped to the `pypi`
|
|
19
|
+
# environment, which only the publish job enters.
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: publish-${{ github.ref }}
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
build:
|
|
29
|
+
name: Build sdist + wheel
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
33
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
34
|
+
with:
|
|
35
|
+
python-version: '3.12'
|
|
36
|
+
- uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
|
|
37
|
+
- name: A release tag must match the packaged version
|
|
38
|
+
if: github.event_name == 'release'
|
|
39
|
+
env:
|
|
40
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
41
|
+
run: |
|
|
42
|
+
version="$(python - <<'PY'
|
|
43
|
+
import tomllib
|
|
44
|
+
print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])
|
|
45
|
+
PY
|
|
46
|
+
)"
|
|
47
|
+
if [ "v$version" != "$TAG" ]; then
|
|
48
|
+
echo "::error::release tag $TAG does not match pyproject version $version"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
# uv build: the same command test.yml's wheel job runs on every PR, so
|
|
52
|
+
# the build path that publishes is the one CI exercises.
|
|
53
|
+
- run: uv build
|
|
54
|
+
- name: Metadata renders on PyPI
|
|
55
|
+
run: uvx twine check --strict dist/*
|
|
56
|
+
- name: Hand the artifacts to the publish job
|
|
57
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
58
|
+
with:
|
|
59
|
+
name: dist
|
|
60
|
+
path: dist/
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
|
|
63
|
+
publish:
|
|
64
|
+
name: Upload to PyPI
|
|
65
|
+
needs: build
|
|
66
|
+
if: github.event_name == 'release' || inputs.dry_run == false
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
environment:
|
|
69
|
+
name: pypi
|
|
70
|
+
url: https://pypi.org/project/omind/
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: dist/
|
|
76
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
|
|
77
|
+
with:
|
|
78
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
79
|
+
# Attestations need trusted publishing (OIDC); token uploads skip them.
|
|
80
|
+
attestations: false
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
# Least privilege: jobs only read the repo.
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
# Cancel superseded runs on the same ref.
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
os: [ubuntu-latest]
|
|
23
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
24
|
+
# Windows and macOS are supported deploy platforms (filelock shim /
|
|
25
|
+
# .cmd-shim resolution on Windows; BSD userland, case-insensitive FS and
|
|
26
|
+
# the ~/.local/bin PATH behavior on macOS). Exercise the oldest and
|
|
27
|
+
# newest Python on each so platform-specific breakage can't ship green.
|
|
28
|
+
include:
|
|
29
|
+
- os: windows-latest
|
|
30
|
+
python-version: "3.10"
|
|
31
|
+
- os: windows-latest
|
|
32
|
+
python-version: "3.14"
|
|
33
|
+
- os: macos-latest
|
|
34
|
+
python-version: "3.10"
|
|
35
|
+
- os: macos-latest
|
|
36
|
+
python-version: "3.14"
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
39
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{ matrix.python-version }}
|
|
42
|
+
# setuptools too: the windows-latest Python 3.10 toolcache bundles a
|
|
43
|
+
# vulnerable 65.5.0 that pip-audit (rightly) flags.
|
|
44
|
+
- run: python -m pip install -U pip setuptools
|
|
45
|
+
- run: pip install -e .[dev]
|
|
46
|
+
- run: ruff check .
|
|
47
|
+
- run: mypy src
|
|
48
|
+
# filelock is not an omind dependency — pip-audit pulls it for its own
|
|
49
|
+
# cachecontrol filecache. Its fix (4.2.1) requires Python >=3.11, so the
|
|
50
|
+
# 3.10 matrix legs can never install a fixed version; ignore the six
|
|
51
|
+
# CVEs rather than pretend the 3.10 legs can be green. pip-audit 2.10
|
|
52
|
+
# has no package-level skip, hence the explicit IDs.
|
|
53
|
+
- run: >-
|
|
54
|
+
pip-audit
|
|
55
|
+
--ignore-vuln CVE-2026-112906 --ignore-vuln CVE-2026-112907
|
|
56
|
+
--ignore-vuln CVE-2026-112913 --ignore-vuln CVE-2026-112914
|
|
57
|
+
--ignore-vuln CVE-2026-112937 --ignore-vuln CVE-2026-112940
|
|
58
|
+
- run: pytest -v --cov=omind --cov-report=term-missing
|
|
59
|
+
|
|
60
|
+
wheel:
|
|
61
|
+
# CI otherwise only installs editable (`pip install -e`), so hatchling's
|
|
62
|
+
# wheel file-selection is never exercised — a change that drops the hook
|
|
63
|
+
# .sh/.js scripts or the web/static assets from the package would ship green
|
|
64
|
+
# and crash `importlib.resources` on installed nodes. Build the real wheel,
|
|
65
|
+
# install it non-editable, and assert the packaged data files are present.
|
|
66
|
+
name: Wheel build + install smoke test
|
|
67
|
+
runs-on: ${{ matrix.os }}
|
|
68
|
+
strategy:
|
|
69
|
+
fail-fast: false
|
|
70
|
+
matrix:
|
|
71
|
+
os: [ubuntu-latest, macos-latest]
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
74
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.12'
|
|
77
|
+
# Same build path as publish.yml, so every PR exercises what gets uploaded.
|
|
78
|
+
- uses: astral-sh/setup-uv@07a047e608db84b3d8c06cd9a7c7dcc9c355c18e # v10.3.2
|
|
79
|
+
- name: Build the wheel
|
|
80
|
+
run: uv build --wheel
|
|
81
|
+
- name: Install the built wheel (not editable)
|
|
82
|
+
run: pip install dist/*.whl
|
|
83
|
+
- name: Smoke test the CLI and the packaged data files
|
|
84
|
+
run: |
|
|
85
|
+
omind --version
|
|
86
|
+
python - <<'PY'
|
|
87
|
+
from importlib.resources import files
|
|
88
|
+
|
|
89
|
+
root = files("omind")
|
|
90
|
+
|
|
91
|
+
def res(*parts):
|
|
92
|
+
p = root
|
|
93
|
+
for part in parts:
|
|
94
|
+
p = p / part
|
|
95
|
+
return p
|
|
96
|
+
|
|
97
|
+
required = [
|
|
98
|
+
("omi-guard.sh",),
|
|
99
|
+
("omi-guard-hermes.sh",),
|
|
100
|
+
("omi-gate-reset.sh",),
|
|
101
|
+
("secret-output-guard.sh",),
|
|
102
|
+
("git-fresh-base.sh",),
|
|
103
|
+
("fleet-sudo.sh",),
|
|
104
|
+
("omi-guard.opencode.js",),
|
|
105
|
+
("_omi_enforce.py",),
|
|
106
|
+
("web", "static", "app.js"),
|
|
107
|
+
("web", "static", "graph.js"),
|
|
108
|
+
]
|
|
109
|
+
missing = ["/".join(parts) for parts in required if not res(*parts).is_file()]
|
|
110
|
+
fonts = [f for f in res("web", "static", "vendor", "fonts").iterdir()]
|
|
111
|
+
assert not missing, f"wheel is missing packaged data files: {missing}"
|
|
112
|
+
assert fonts, "wheel is missing web/static/vendor/fonts"
|
|
113
|
+
print(f"OK: {len(required)} data files + {len(fonts)} fonts present in the wheel")
|
|
114
|
+
PY
|
|
115
|
+
|
|
116
|
+
upgrade:
|
|
117
|
+
# Every PR proves that people can still UPGRADE, against a real uv on a real
|
|
118
|
+
# filesystem, on every OS omind is installed on. The unit tests mock uv, and
|
|
119
|
+
# the failure this guards (#375) does not exist in a mock: `uv tool install
|
|
120
|
+
# --force` deletes the environment before it builds the new one, and on
|
|
121
|
+
# Windows cannot delete the python.exe that `omind self-update` runs from —
|
|
122
|
+
# 9.4.0 -> 9.7.5 left a machine with no omind at all.
|
|
123
|
+
#
|
|
124
|
+
# Path walked: install an OLD release the way a user did -> upgrade it to this
|
|
125
|
+
# checkout -> run this checkout's `omind self-update` -> re-run the installer
|
|
126
|
+
# over the result. The invariant after EVERY step: omind still starts.
|
|
127
|
+
name: Upgrade from ${{ matrix.from }} (${{ matrix.os }})
|
|
128
|
+
runs-on: ${{ matrix.os }}
|
|
129
|
+
strategy:
|
|
130
|
+
fail-fast: false
|
|
131
|
+
matrix:
|
|
132
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
133
|
+
# A pinned old release (the one #375 started from) and whatever is the
|
|
134
|
+
# newest tag today, so the baseline moves forward with every release.
|
|
135
|
+
from: [v9.4.0, latest]
|
|
136
|
+
defaults:
|
|
137
|
+
run:
|
|
138
|
+
shell: bash
|
|
139
|
+
env:
|
|
140
|
+
# The heal re-provisions ~/.claude and needs the claude CLI; not under test.
|
|
141
|
+
OMIND_NO_AUTOHEAL: '1'
|
|
142
|
+
steps:
|
|
143
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
144
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
145
|
+
with:
|
|
146
|
+
python-version: '3.12'
|
|
147
|
+
- run: python -m pip install -U pip uv
|
|
148
|
+
- name: Install the old release with bootstrap.sh, on a clean machine
|
|
149
|
+
run: |
|
|
150
|
+
bin="$(uv tool dir --bin)"
|
|
151
|
+
echo "$bin" >> "$GITHUB_PATH"
|
|
152
|
+
# Git Bash splits PATH on ':', so C:\... must become /c/... for this step.
|
|
153
|
+
if command -v cygpath >/dev/null 2>&1; then bin="$(cygpath -u "$bin")"; fi
|
|
154
|
+
export PATH="$bin:$PATH"
|
|
155
|
+
ref=()
|
|
156
|
+
[ "${{ matrix.from }}" = "latest" ] || ref=(--ref "${{ matrix.from }}")
|
|
157
|
+
# Exits 1 only because the runner has no `claude` CLI to set up.
|
|
158
|
+
scripts/bootstrap.sh --no-setup "${ref[@]}" || true
|
|
159
|
+
omind --version
|
|
160
|
+
- name: Upgrade it to this checkout
|
|
161
|
+
run: |
|
|
162
|
+
uv tool install --force --from . omind
|
|
163
|
+
want="$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)"
|
|
164
|
+
omind --version | tee version.txt
|
|
165
|
+
grep -qF "$want" version.txt
|
|
166
|
+
- name: omind self-update, for real
|
|
167
|
+
run: |
|
|
168
|
+
set +e
|
|
169
|
+
omind self-update --force 2>&1 | tee update.log
|
|
170
|
+
code=${PIPESTATUS[0]}
|
|
171
|
+
set -e
|
|
172
|
+
if grep -q "could not reach GitHub" update.log; then
|
|
173
|
+
echo "::warning::GitHub API unreachable/rate-limited from this runner; self-update not exercised"
|
|
174
|
+
elif [ "$RUNNER_OS" = "Windows" ]; then
|
|
175
|
+
# In-place replacement cannot work on Windows: it must refuse, not try.
|
|
176
|
+
[ "$code" -eq 1 ] && grep -q "refusing to update" update.log
|
|
177
|
+
else
|
|
178
|
+
[ "$code" -eq 0 ] && grep -q "updated to" update.log
|
|
179
|
+
fi
|
|
180
|
+
- name: Whatever self-update decided, omind still starts
|
|
181
|
+
run: omind --version
|
|
182
|
+
- name: bootstrap.sh over an existing install leaves a working omind
|
|
183
|
+
run: |
|
|
184
|
+
scripts/bootstrap.sh --no-setup || true
|
|
185
|
+
omind --version
|
|
186
|
+
|
|
187
|
+
secrets:
|
|
188
|
+
name: Secret scan (gitleaks, full history)
|
|
189
|
+
runs-on: ubuntu-latest
|
|
190
|
+
steps:
|
|
191
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
192
|
+
with:
|
|
193
|
+
fetch-depth: 0 # gitleaks scans history
|
|
194
|
+
- name: gitleaks
|
|
195
|
+
run: |
|
|
196
|
+
docker run --rm -v "${{ github.workspace }}:/repo" \
|
|
197
|
+
--entrypoint sh ghcr.io/gitleaks/gitleaks:v8.30.1 \
|
|
198
|
+
-c "git config --global --add safe.directory /repo && \
|
|
199
|
+
gitleaks git --redact --verbose /repo"
|
|
200
|
+
|
|
201
|
+
attribution:
|
|
202
|
+
name: Commit attribution
|
|
203
|
+
runs-on: ubuntu-latest
|
|
204
|
+
if: github.event_name == 'pull_request'
|
|
205
|
+
steps:
|
|
206
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
207
|
+
with:
|
|
208
|
+
fetch-depth: 0 # needs the base branch to diff against
|
|
209
|
+
- name: Every commit declares its authorship
|
|
210
|
+
run: ./scripts/check-attribution.sh --range "origin/${{ github.base_ref }}..HEAD"
|
|
211
|
+
|
|
212
|
+
conformance:
|
|
213
|
+
name: MCP conformance (live stdio)
|
|
214
|
+
runs-on: ubuntu-latest
|
|
215
|
+
steps:
|
|
216
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
217
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
218
|
+
with:
|
|
219
|
+
python-version: '3.12'
|
|
220
|
+
- name: Conformance suite
|
|
221
|
+
# mcp-conformance is a private repo, so this job is a graceful no-op until
|
|
222
|
+
# MCP_CONFORMANCE_TOKEN (a PAT with read access to it) is set in the repo's
|
|
223
|
+
# Actions secrets. Then it boots `omind node` over stdio against a throwaway
|
|
224
|
+
# vault and asserts the baseline contracts (see conformance.toml).
|
|
225
|
+
env:
|
|
226
|
+
MCP_CONFORMANCE_TOKEN: ${{ secrets.MCP_CONFORMANCE_TOKEN }}
|
|
227
|
+
run: |
|
|
228
|
+
if [ -z "$MCP_CONFORMANCE_TOKEN" ]; then
|
|
229
|
+
echo "MCP_CONFORMANCE_TOKEN not set — skipping conformance suite."
|
|
230
|
+
exit 0
|
|
231
|
+
fi
|
|
232
|
+
python -m venv .venv
|
|
233
|
+
.venv/bin/pip install -U pip
|
|
234
|
+
.venv/bin/pip install -e .
|
|
235
|
+
# The token is set but may be expired or lack access to the private
|
|
236
|
+
# repo. Treat a failed clone/install as a skip, not a hard CI failure —
|
|
237
|
+
# this job is a graceful no-op until a working token is wired up, and
|
|
238
|
+
# an expired PAT shouldn't turn the whole build red.
|
|
239
|
+
if ! .venv/bin/pip install "git+https://x-access-token:${MCP_CONFORMANCE_TOKEN}@github.com/CryptoJones/mcp-conformance.git"; then
|
|
240
|
+
echo "::warning::Could not install mcp-conformance (token expired or no access?) — skipping conformance suite."
|
|
241
|
+
exit 0
|
|
242
|
+
fi
|
|
243
|
+
mkdir -p ./.conformance-vault/OMI
|
|
244
|
+
.venv/bin/mcp-conformance run -- -q
|
|
245
|
+
|
|
246
|
+
# Actions pinned by commit SHA; kept current by Dependabot (.github/dependabot.yml).
|
omind-10.3.4/.gitignore
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
*.egg
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.eggs/
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
env/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.coverage
|
|
15
|
+
htmlcov/
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
*.swp
|
|
19
|
+
.DS_Store
|
|
20
|
+
Thumbs.db
|
|
21
|
+
.claude/
|
|
22
|
+
.aider*
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# gitleaks config. Uses the default rule set; allowlists obvious test fixtures
|
|
2
|
+
# and the generated mesh node-id/backup-password placeholders so CI stays signal,
|
|
3
|
+
# not noise. omind has no committed credentials: backup passwords and node IDs
|
|
4
|
+
# are generated at runtime with `secrets.token_*` and written outside the repo.
|
|
5
|
+
title = "omind gitleaks"
|
|
6
|
+
|
|
7
|
+
[extend]
|
|
8
|
+
useDefault = true
|
|
9
|
+
|
|
10
|
+
[allowlist]
|
|
11
|
+
description = "Test/e2e fixtures and docs use obvious fake tokens/paths."
|
|
12
|
+
paths = [
|
|
13
|
+
'''tests/.*''',
|
|
14
|
+
'''docs/.*''',
|
|
15
|
+
# The e2e harness reads provider keys from the environment at runtime; it
|
|
16
|
+
# commits no secrets. gitleaks' generic-api-key rule false-positives on the
|
|
17
|
+
# high-entropy env-var NAME in runpod_api_key()'s docstring (e2e/providers.py).
|
|
18
|
+
'''e2e/.*''',
|
|
19
|
+
]
|
omind-10.3.4/AGENTS.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# AGENTS.md — orientation for AI agents working on omind
|
|
2
|
+
|
|
3
|
+
Read this before changing code. It covers what a contributor doc can't: the
|
|
4
|
+
invariants that break *silently*, the current state of in-flight work, and the
|
|
5
|
+
dead ends someone already walked down.
|
|
6
|
+
|
|
7
|
+
For dev setup, the four quality gates, the module map, SemVer rules, and PR
|
|
8
|
+
conventions, see **[CONTRIBUTING.md](CONTRIBUTING.md)** — this file does not
|
|
9
|
+
repeat them.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## The one-paragraph version
|
|
14
|
+
|
|
15
|
+
omind gives AI agents durable memory as **plain Markdown notes** in an Obsidian
|
|
16
|
+
vault, replicated peer-to-peer over git, exposed to agents through a local MCP
|
|
17
|
+
server (`omind node`) and enforced by a hook-based guard. Roughly a third of the
|
|
18
|
+
repo is memory; the rest is agent enforcement (`guard.py`, `policy.py`,
|
|
19
|
+
`verify.py`), fleet provisioning (`provision.py`, `agents.py`), and mesh
|
|
20
|
+
replication (`mesh.py`, `merge.py`). Know which subsystem you are in.
|
|
21
|
+
|
|
22
|
+
## Invariants — violate these and something breaks quietly
|
|
23
|
+
|
|
24
|
+
1. **The Markdown files are the source of truth.** Indexes, caches, and vectors
|
|
25
|
+
are derived and disposable. Anything derived lives in the state dir
|
|
26
|
+
(`paths.state_dir()`), never in the vault: vault contents are committed and
|
|
27
|
+
mesh-synced, so a derived file there would replicate machine-specific junk
|
|
28
|
+
fleet-wide.
|
|
29
|
+
2. **Retrieval fails open.** Every layer of search returns `None` on any problem
|
|
30
|
+
and the caller falls back to the older, dumber path. A missing model, a
|
|
31
|
+
corrupt index, a locked database, a missing FTS5 build — all degrade search;
|
|
32
|
+
none may break it. Test the failure branch, not just the happy one.
|
|
33
|
+
3. **Multi-note writes go through `omind.txn`.** One note at a time is already
|
|
34
|
+
atomic (same-dir temp + `os.replace`). Two or more is not, and a crash
|
|
35
|
+
between them used to leave partial state with no way back. Any new operation
|
|
36
|
+
that writes several notes must journal its pre-images through
|
|
37
|
+
`txn.Transaction` under `store.write_lock()`, or it reintroduces the gap
|
|
38
|
+
`omind recover` exists to close. Recovery refuses to overwrite a note edited
|
|
39
|
+
after the crash — that edit is newer than the pre-image.
|
|
40
|
+
4. **All note writes go through `OmiStore`** (`notes.upsert_note` for external
|
|
41
|
+
writers) — flock, atomic rename, Lamport `Rev:` stamping, soft delete.
|
|
42
|
+
Deletes archive (`Disabled: true`); only `omind mesh purge` truly removes.
|
|
43
|
+
5. **`OmiStore.safe_name` guards every read and write.** Path traversal must stay
|
|
44
|
+
impossible; there are tests enforcing this. Don't route around them.
|
|
45
|
+
6. **`store.py` stays framework-free.** No FastAPI, no MCP. The CLI and the web
|
|
46
|
+
app both build on it.
|
|
47
|
+
7. **Credential notes are de-prioritised** in search and in the gate's
|
|
48
|
+
suggestions unless the query is itself about credentials
|
|
49
|
+
(`retrieve._CREDENTIAL_PENALTY`). The gate must never steer an agent into the
|
|
50
|
+
secrets notes. This is load-bearing, not decoration.
|
|
51
|
+
8. **No MCP tool may return unbounded output.** Every list-shaped tool pages
|
|
52
|
+
(`limit`, `offset`, `total`, `has_more`) via `server._page`. `list-notes` once
|
|
53
|
+
returned ~90,800 tokens in a single result; `tests/test_server.py::
|
|
54
|
+
test_every_list_tool_is_bounded` exists so a new tool cannot regress that.
|
|
55
|
+
9. **Reserved files are not memories.** `index.md` and `Memory Template.md` are
|
|
56
|
+
scaffolding; reading one does *not* clear the consult gate
|
|
57
|
+
(`paths.NON_CONSULT_FILENAMES` — an anti-dodge measure, issue #109).
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Handoff: the 2026-10-02 backlog sweep (shipped)
|
|
62
|
+
|
|
63
|
+
The 2026-08-27 handoff below is history too. Current state: **v10.2.11 on `main`**.
|
|
64
|
+
Trust **BACKLOG.md + CHANGELOG.md** (10.1.1–10.2.11) for detail.
|
|
65
|
+
|
|
66
|
+
The sweep closed #393 #392 #391 #394 #414 #402 #403 #406 #416 #377 #380 #417 #419
|
|
67
|
+
#420 #423 #425 via PRs #405, #407–#413, #415, #418, #421, #422, #424 and #426.
|
|
68
|
+
Every item from that sweep is closed.
|
|
69
|
+
|
|
70
|
+
Lessons for the next agent:
|
|
71
|
+
|
|
72
|
+
- `windows-latest` CI runners are real Windows. Tests must be platform-correct: use
|
|
73
|
+
`tmp_path` absolute paths, `.as_posix()` in command text, and pin `provision._windows`.
|
|
74
|
+
- PowerShell `-Command` turns a native exit 2 into 1 unless the command ends with
|
|
75
|
+
the null-guarded `exit $LASTEXITCODE`.
|
|
76
|
+
- Recall names must be stored filenames, never titles.
|
|
77
|
+
- Enforcement classifiers must bind markers to their own stage; repo-scoped rules
|
|
78
|
+
match only real command sites.
|
|
79
|
+
- Fail-open must never drop the seed hard rules.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Handoff: the 2026-08-27 multi-agent review (shipped — history)
|
|
84
|
+
|
|
85
|
+
The 2026-07-24 retrieval handoff below is history: `feat/hybrid-retrieval-token-budgets`
|
|
86
|
+
landed long ago, and #167–#178 all shipped (see BACKLOG.md). Current state at this
|
|
87
|
+
writing: **v8.8.0 on `main`**, 1,000+ tests + ruff + mypy strict green. Trust
|
|
88
|
+
**BACKLOG.md + CHANGELOG.md** for what's open — not older handoffs.
|
|
89
|
+
|
|
90
|
+
### What changed and why
|
|
91
|
+
|
|
92
|
+
A nine-slice multi-agent review (report:
|
|
93
|
+
[docs/reviews/2026-08-27-multi-agent-review.md](docs/reviews/2026-08-27-multi-agent-review.md))
|
|
94
|
+
found 35 issues; all are fixed in the working tree. The classes worth remembering:
|
|
95
|
+
|
|
96
|
+
- **Locking is total now, and the pattern is uniform.** Any read-modify-write of a
|
|
97
|
+
small state file (gate sentinels, re-close/off-topic counters, `loop_guard.json`,
|
|
98
|
+
`node.json`, `backup.json`, harness settings.json) goes through
|
|
99
|
+
`filelock.exclusive()` on a SIBLING `.lock` path — never on the data file itself,
|
|
100
|
+
because the data file is replaced atomically and a flock on a replaced inode
|
|
101
|
+
protects nothing. Apply this to any new state file.
|
|
102
|
+
- **Optimistic concurrency is the coordination story.** `upsert_note` captures the
|
|
103
|
+
version BEFORE reading existing fields; checkpoint/okf/consolidate pin versions;
|
|
104
|
+
`edit-note` without a token answers `concurrency: "unverified"` instead of
|
|
105
|
+
silently last-write-wins.
|
|
106
|
+
- **Deletion yields to newer edits.** Purge tombstones carry the purge-time Rev;
|
|
107
|
+
`_apply_tombstones` keeps and reports a note whose live Rev dominates it.
|
|
108
|
+
- **Merge LWW losses are visible in the vault** (`merge-lww` tag), not just daemon
|
|
109
|
+
stderr. If you touch `merge.py`, keep scalar losses tagged.
|
|
110
|
+
- **The index stores the encoder IDENTITY** (`embed.model_identity`: name +
|
|
111
|
+
embedding-space digest), not the model name — same name/different snapshot used
|
|
112
|
+
to mix vector spaces silently. Refresh also BACKFILLS chunks missing vectors.
|
|
113
|
+
- **Self-update pins the resolved commit SHA**, never the mutable tag, and records
|
|
114
|
+
the previous version for `omind self-update --rollback`.
|
|
115
|
+
- **Enforcement hardening:** `guard reset` is compliance-logged (`gate-reset`);
|
|
116
|
+
freshness recorded at PreToolUse is RETRACTED on PostToolUse failure; the
|
|
117
|
+
verifier prompt fences untrusted material and parses verdicts by token; Layer E
|
|
118
|
+
uses the strict `policy.opt_in_satisfied` matcher.
|
|
119
|
+
|
|
120
|
+
### Things that will bite you (still true)
|
|
121
|
+
|
|
122
|
+
- Retrieval/enforcement fail OPEN — every new path must degrade, never raise into
|
|
123
|
+
the agent. `SearchIndex.search` now blanket-catches; keep it that way.
|
|
124
|
+
- Recency only re-ranks matches (`test_recency_only_reorders_matches...`).
|
|
125
|
+
- The index doesn't strip fences from `[[wikilinks]]`; lint.py does.
|
|
126
|
+
- `link_targets()` preserves case.
|
|
127
|
+
- Never mutate a cached `NoteSummary`; use `dataclasses.replace`.
|
|
128
|
+
- `mesh purge` requires `--yes` (or a TTY confirm) — keep it gated.
|
|
129
|
+
- `read-note` caps bodies (20k default / 65k hard) — keep it bounded (invariant 8).
|
|
130
|
+
|
|
131
|
+
### Where to pick up
|
|
132
|
+
|
|
133
|
+
The feature roadmap (agent identity/attribution, a usefulness feedback loop,
|
|
134
|
+
sleep-time consolidation, write-time dedup, scoped writes) is Part 2 of the review
|
|
135
|
+
report — none of it is started.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Working agreements
|
|
140
|
+
|
|
141
|
+
- **BACKLOG.md and the GitHub Issues tab are two views of one list.** File an
|
|
142
|
+
issue for every backlog line and link it both ways; check the box when it
|
|
143
|
+
ships. Both had drifted badly before 2026-07-24 (every "Open" item was already
|
|
144
|
+
closed upstream) — don't let that happen again.
|
|
145
|
+
- **GitHub is the only remote** (Codeberg is end-of-life).
|
|
146
|
+
- **Commit/push only when asked.** Branch off `main` (`feat/`, `fix/`, `docs/`,
|
|
147
|
+
`chore/`, `refactor/`), conventional-commit subjects.
|
|
148
|
+
- **Docs carry the footer** (`*Proudly Made in Nebraska. Go Big Red! 🌽
|
|
149
|
+
<https://xkcd.com/2347/>*`); the README carries the centred banner version.
|
|
150
|
+
- **Report honestly.** If a gate fails, say so with the output. If you skipped
|
|
151
|
+
part of the scope, say which part and why — see how #174 and #177 were left
|
|
152
|
+
open rather than half-done.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
*Proudly Made in Nebraska. Go Big Red! 🌽 <https://xkcd.com/2347/>*
|