This repository was archived by the owner on Sep 5, 2026. It is now read-only.
harden: work through both code-review batches (provenance pinning, consolidation, guard, CI, docs) - #11
Merged
Merged
Conversation
Verification proved internal consistency, not authenticity: every verify path checked signatures against the key embedded in the artifact's own issuer field, so a vault-write attacker could forge a self-consistent chain under their own did:key and have it verify. Pin the agent DID on first use in $COGMEM_HOME/trust.json (outside vault/) and require issuer == pinned DID in verify_credential, verify_log, and verify_sth. Adds the forged-chain rejection test.
load_existing_knowledge concatenated every rule + pending into one prompt with no cap; as the vault grew the call would eventually exceed the context window, fail, and strand candidates unconsolidated forever. Cap the corpus to a char budget (curated files always included, newest rules fill the rest) and classify candidates in batches so one failed batch no longer strands the whole backlog.
acquire.py carried its own drifted copies of api_call (60s vs common's 90s) and parse_json_block; import them from common instead. Move every hardcoded model id (per-role LLMs + the embed/rerank models, incl. the two out-of-sync copies in daemon.py and index.py) into config with accessors, so upgrades and overrides no longer need code edits.
guard.py ran model-generated regexes via re.search on every Bash command, so a catastrophic-backtracking pattern (accidental or planted in a poisoned failure note) could hang the PreToolUse hook. Cap command and pattern length, fall back to literal search for oversized patterns, and bound total matching to 250ms via SIGALRM, failing open on timeout.
Both _recv_line and the recall client looped until a newline with no size bound, so a peer that never sends one could grow the buffer without limit. Add a 1 MiB ceiling.
The default eval reported at a hardcoded floor=0.62 while production runs the tuned config value, so the published number wasn't the operating point. Read thresholds from config (with --floor/--gap overrides) and document that auto-generated positives are paraphrases of the rules themselves, so the number is an upper bound, not absolute.
A silently-broken learning loop looked identical to a working one. doctor reports every link that can fail independently: daemon warm/cold (with a live ping), API key presence, trust-anchor status, last capture time, candidate/approval backlog, recall injections, feedback tallies, and the provenance-enforce flag.
CI installed only cryptography+cbor2 and ran two of three test files, so test_cogmem and the entire recall/daemon import graph were never checked. Install numpy too, add an import smoke over every engine module, run all three suites, and add a ruff lint job (pyproject config) gating real defects (F-class: undefined names, unused imports).
Newest-first truncation could evict the older same-scope rule a candidate actually duplicates, defeating the dedup it was meant to protect. Order the bounded corpus in-scope-first then by recency, so a candidate's likely duplicate is always present. Test proves the oldest in-scope rule survives eviction over 40 newer out-of-scope ones.
stat -f %m is BSD-only; on Linux it failed straight to 'echo 0', so the capture dedup saw mtime 0 (skipping real captures) and lock-age math misfired. Fall back to GNU 'stat -c %Y'. (A Linux daemon service is still tracked separately as issue #8.)
README claimed 'nothing is sent anywhere', but the learning pipeline (acquisition, consolidation, feedback, project/user-model) sends session transcripts to the Anthropic API; only recall is local. State the split honestly and soften the badge/ tagline. Update THREAT-MODEL T2 and §4.3 to reflect the new TOFU issuer pinning and its precise residual (whole-home write still collapses to T6; STH still unwitnessed).
This was referenced Jun 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Works through both review batches from the code review. 11 commits, each self-contained and verified; 73 tests pass (was 66),
ruffclean, every engine module import-smoked.Security / correctness (the high-value core)
d1d5cb9Issuer pinning. Verification proved internal consistency, not authenticity: every verify path checked signatures against the key embedded in the artifact's ownissuerfield, so a vault-write attacker could forge a self-consistent chain under their owndid:keyand have it verify. Pin the agent DID on first use in$COGMEM_HOME/trust.json(outsidevault/) and requireissuer == pinned DIDinverify_credential/verify_log/verify_sth. New forged-chain rejection test.f553b43+8184badConsolidation cliff.load_existing_knowledgeconcatenated every rule into one unbounded prompt → at scale the call exceeds the context window, fails, and strands candidates forever. Bound the corpus + batch candidates, then scope-prioritize it so the older same-scope rule a candidate may duplicate isn't evicted by newer out-of-scope ones. Test proves the oldest in-scope rule survives over 40 newer out-of-scope rules.236cd30Guard ReDoS. Model-generated tripwire regexes ran viare.searchon every Bash command. Cap inputs, fall back to literal for oversized patterns, bound total matching to 250ms via SIGALRM (fail-open). Regression test.f2f322aSocket bound. 1 MiB ceiling on daemon/recall reads.Quality / reach
927e8cbDedupe driftedapi_call/parse_json_block(acquire → common); centralize all model IDs (incl. two out-of-sync embed-model copies) into config.c332cc4cogmem doctor— end-to-end loop health (daemon ping, API key, trust anchor, capture freshness, backlog).435c450CI installs numpy, import-smokes every engine module, runs all three suites, adds a ruff job. (Previously only 2/3 suites, recall path never imported.)52becb8Portablemtimein hooks — capture dedup + approval rate-limit were silently broken on Linux (stat -fis BSD-only).411baecEval reports at live config thresholds (was hardcoded 0.62); circularity documented.015b35aDocs honesty: corrected "nothing is sent anywhere" (learning calls the Anthropic API; recall is local); documented the pinning trust model + residuals in THREAT-MODEL.Honest seams
$COGMEM_HOMEwrite still re-anchors (collapses to T6); OS-keychain is the next step, noted in THREAT-MODEL §4.3.