Repository navigation
152 lines (148 loc) · 8.02 KB
/
Copy pathci.yml
File metadata and controls
152 lines (148 loc) · 8.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- name: Syntax check (compile all)
run: python -m compileall -q ingest hooks rerank ci
- name: Lint (real errors only -- undefined names, syntax)
run: |
pip install --quiet ruff
ruff check --select E9,F63,F7,F82 ingest hooks rerank ci
- name: GRAPH_SQL parity (hook copy vs Rust source of truth)
run: python ci/check_graph_sql_parity.py
- name: Hook I/O contract (hooks are fail-open, so a broken contract is silent)
run: python tests/test_hook_contract.py
- name: Incremental ingest (a silent fallback to full replace only costs embeddings)
run: python tests/test_incremental_ingest.py
- name: Ingest enumeration (an empty ingest deletes the corpus it should have refreshed)
run: python tests/test_ingest_enumeration.py
- name: Ingest redaction (a secret in a runbook becomes a chunk, a vector and a prompt)
run: python tests/test_ingest_redaction.py
- name: Query hygiene (a split hostname matches nothing, and nothing says so)
run: python tests/test_query_hygiene.py
- name: Glob parity (the hook must inject exactly what get_constraints returns)
run: python tests/test_glob_parity.py
- name: Doctor (the health check must not call a broken store healthy)
run: python tests/test_doctor.py
- name: hm ingest (a re-ingest must not silently drop every embedding)
run: python tests/test_hm_cli.py
- name: Chunker (nothing may exceed what the embedder can embed whole)
run: python tests/test_chunker.py
- name: Latency statistics (no store needed)
run: python ci/latency.py --selfcheck
- name: Settings knobs must name files that exist and variables the code reads
run: python tests/test_settings_knobs.py
- name: Shared settings file (prefix allowlist, mode check, env precedence)
run: python tests/test_env_file.py
# The consolidator rewrites memory in place: one bad grouping can retire hundreds of
# records in a single verdict, which is exactly what it did before this guard existed.
- name: Consolidator grouping (a chain must not become one group)
run: python tests/test_consolidate_groups.py
# Four modules ship an executable self-check and only one of them was run. For each of
# the three below, that self-check is the ONLY automated coverage its behaviour has:
# Tier-1 selection (longest-match order, 1-hop propagation, cross-repo isolation),
# secret redaction, and the novelty gate with its negation guard. A change that leaked
# another repo's constraints or broke a redaction pattern passed everything else green.
- name: Tier-1 selection (1-hop propagation and cross-repo isolation)
run: python hooks/_arch.py
- name: Secret redaction patterns
run: python ingest/_redact.py
- name: Novelty gate and its negation guard
run: python hooks/mem_extract.py --selfcheck
rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Build the MCP server
working-directory: mcp-server
run: cargo build --release --locked
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- name: Project status (source hashes, scope and real MCP transport)
run: python tests/test_project_status.py
- name: Rust unit tests (glob parity with the Python hook)
working-directory: mcp-server
run: cargo test --locked
# The console is a separate crate: its own build and its own tests. Kept in the same job
# because it shares the toolchain, and a console that does not compile is a console nobody
# notices is broken until they try to open it.
#
# On this runner that means the data layer and the four command-line tools with the default
# feature set: the tray's GUI dependencies are declared for macOS unconditionally, and for
# Linux only behind the `tray` feature (off by default), specifically so this step needs no
# GUI library at all. Everything the tests cover here is in the part that builds without it.
- name: Build the console (data layer + CLI tools; no GUI libraries needed)
working-directory: console
run: cargo build --release --locked
- name: Console unit tests
working-directory: console
run: cargo test --locked
# The Linux tray, behind its feature: exercises the `tray-icon` + GTK path this runner does
# not otherwise touch. Its own dependencies need real headers, hence the apt step -- and
# that step is confined to here so the two steps above stay proof that nothing else in this
# crate needs them.
- name: Build the Linux tray (GTK + appindicator)
working-directory: console
run: |
sudo apt-get update
# libxdo-dev is easy to miss: tray-icon's menu-accelerator handling links -lxdo, and the
# link fails without it even though nothing above mentions xdo by name.
sudo apt-get install -y libgtk-3-dev libayatana-appindicator3-dev libxdo-dev
cargo build --release --locked --features tray
- name: Linux tray unit tests
working-directory: console
run: cargo test --locked --features tray
schema:
runs-on: ubuntu-latest
services:
postgres:
image: pgvector/pgvector:0.8.5-pg16
env:
POSTGRES_USER: hm
POSTGRES_PASSWORD: hm
POSTGRES_DB: hypermnesia
ports: ["5432:5432"]
options: >-
--health-cmd "pg_isready -U hm -d hypermnesia"
--health-interval 5s --health-timeout 5s --health-retries 10
env:
PGPASSWORD: hm
steps:
- uses: actions/checkout@v4
- name: Load schemas
run: |
psql -h localhost -U hm -d hypermnesia -v ON_ERROR_STOP=1 -f sql/schema.sql
psql -h localhost -U hm -d hypermnesia -v ON_ERROR_STOP=1 -f sql/schema_mem.sql
- name: Load the example seed + assert Tier-1 resolves
run: |
psql -h localhost -U hm -d hypermnesia -v ON_ERROR_STOP=1 -f examples/seed_example.sql
psql -h localhost -U hm -d hypermnesia -tAc \
"SELECT count(*) FROM components WHERE repo='myapp'" | grep -qx 4
psql -h localhost -U hm -d hypermnesia -tAc \
"SELECT count(*) FROM constraints WHERE repo='myapp'" | grep -qx 2
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- name: Golden -- the hook's GRAPH_SQL is valid and returns the seed shape
run: |
# Run the exact query the PreToolUse hook uses; assert it loads the map (not just that
# the tables have rows). Catches an invalid/renamed column the string-parity check can't.
python ci/check_graph_sql_parity.py --print > /tmp/graph.sql
psql -h localhost -U hm -d hypermnesia -v ON_ERROR_STOP=1 -tAf /tmp/graph.sql > /tmp/graph.json
python -c "import json; g=json.load(open('/tmp/graph.json')); c={x['slug'] for x in g['components'] if x['repo']=='myapp'}; assert {'myapp-api','myapp-db','myapp-docs','myapp-root'}<=c, c; assert any(x['scope']=='global' and x['severity']=='must' for x in g['constraints']), 'seed global must missing'; print('GRAPH_SQL golden OK:', sorted(c))"
# Nothing in CI executed a single mem.* statement, so abstention and
# supersede-not-overwrite -- both headline claims -- were asserted only by a probe that
# needs a live embedder and therefore never ran. This needs no embedder: pgvector takes a
# literal vector, which isolates the SQL and the view from the model.
- name: Memory SQL contract (the view hides what it promises, the gate abstains)
env:
DATABASE_URL: postgresql://hm:hm@localhost:5432/hypermnesia
run: python tests/test_memory_sql.py