32 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 1d958b3587 |
fix(security): patent-leak + classical-safety audit fixes
Some checks are pending
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / preflight (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / vps-smoke (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:frustration-matrix,kei-frustration-loop,kei-skill-importer,kei-projects-index,kei-projects-watcher,kei-gdrive-import,kei-leak-matrix,kei-skills,kei-gateway,kei-cron-scheduler,kei-export-trajectories,kei-backend-daytona,kei-d… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-compute-baremetal,kei-compute-vultr,kei-compute-linode,kei-compute-digitalocean,kei-svc-systemd,kei-llm-bridge-mlx name:hosted-sleep-compute]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-diff,kei-scheduler,kei-watch,kei-prune,kei-discover,kei-brain-view,kei-hibernate,kei-ledger-sign,kei-fork name:wave13-15]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-git-gitea,kei-git-forgejo,kei-git-gitlab,kei-git-bitbucket,kei-memory-sled,kei-memory-redis,kei-memory-postgres,kei-memory-sqlite,kei-auth-google,kei-auth-apple,kei-auth-magiclink,kei-auth-webauthn,kei-notify-slack,kei-n… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-ledger,kei-migrate,kei-changelog,kei-memory,kei-store,kei-conflict-scan,kei-refactor-engine,kei-graph-check,kei-shared,kei-dna-index,kei-pet name:core]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-machine-probe,kei-llm-ollama,kei-llm-llamacpp,kei-llm-mlx,kei-llm-router,kei-model name:llm-stack]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-router,kei-sage,kei-task,kei-chat-store,kei-crossdomain,kei-search-core,kei-content-store,kei-social-store,kei-curator,kei-auth,kei-artifact name:mcp-lbm]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:keisei,kei-forge,kei-runtime,kei-runtime-core,kei-atom-discovery,kei-agent-runtime,kei-capability,kei-provision,kei-entity-store,kei-pipe,kei-cache,kei-spawn,kei-replay name:atom-substrate]) (push) Blocked by required conditions
PATENT-LEAK (HIGH):
- hooks/no-python-without-approval.sh: genesis-verify пример → my-project
- docs/encyclopedia/rust-crates-H-N.md: убран термин «Genesis IP, ITAR»
PATENT-LEAK (MEDIUM):
- CHANGELOG: project-vortex → reduced scope
- _blocks/registries (submodule bump): убраны имена приватных
project-specialists из комментария agent-profiles.toml
- docs/encyclopedia/skills-and-agents.md: ML/RL/CfC → ML/RL
CLASSICAL-SAFETY (MEDIUM):
- install/lib-preflight.sh: eval "$version_cmd" → bash -c "..."
(защита от инъекции если providers.toml расширят)
- _primitives/provision-{vultr,hetzner}.sh: /tmp/$$ → mktemp
(устраняет symlink TOCTOU race)
- web-install.sh: chmod 600 + umask 077 на ~/.keisei-install.log
(Forgejo admin creds + токены в логе)
- scripts/regen-counts.sh: eval "$1" → bash -c
NOT FIXED (требуют действий юзера):
- HIGH: @keisei scope не зарегистрирован на npmjs.org — typosquat
возможен пока не задан NPM_TOKEN и не сделан publish
- HIGH: install.keisei.app DNS не настроен — DNS-hijack возможен
- LOW: parfionovich@keilab.io в SECURITY.md, plugin.json, ~40 Cargo
файлах — intentional contact, оставлен
Локальный git author установлен на parfionovich@keilab.io вместо
parfionovichd@icloud.com (только для будущих коммитов в этом репо).
|
|||
|
|
40a5c2e55f |
fix(audit-r2): HIGH+MEDIUM closures from second round audit
HIGH-1: submodule URL ssh → https + shallow (DNS spoofing surface, both repos)
HIGH-3: docs/DNA-MIGRATION.md — two-format coexistence policy (4-seg legacy
task-class vs 5-seg agent-shell marketplace)
HIGH-5: agent_shell_dna doc — explicit consumer = marketplace, planned ledger
integration; module-doc clarification
MEDIUM: Haiku model id pinned to claude-haiku-4-5-20251001 across
pricing.rs::from_slug + ::name + escalate.rs tests + select_posterior
fixture + kei-registries submodule (pushed c39e528→7aaa6a7)
|
||
|
|
7281e7ecea |
fix(registries+router): MEDIUM/LOW audit batch
closes MEDIUM/LOW from feat/agent-dna-three-layer audit: - models.toml: cache_write_1h_per_mtok_micro added to all 11 entries (Anthropic: 200M/600M/1000M micro = $2/$6/$10 per MTok per pricing page; other providers: 0 placeholder) - main.rs (kei-model-router): WAL pragma + busy_timeout errors now logged to stderr instead of silently dropped (previously .ok() swallowed both) - models.toml: Haiku id pin TODO documented (router still hardcodes alias) |
||
|
|
7cd74071a1 |
feat(kei-model-router): agent_shell_dna parser for 5-segment marketplace DNA
Adds `agent_shell_dna` cube parsing the new agent-shell::<p>:<m>:<c>::<scope>::<body>-<nonce> format emitted by keisei-marketplace/src/lib/cryptoid.ts::agentDna. Companion to legacy 4-segment `dna_class` (untouched per RULE Don't-Rewrite). Accepts both 8-hex (legacy) and 16-hex (current) lengths for forward-compat. - new file: src/agent_shell_dna.rs (235 LOC, 13 tests all pass) - lib.rs: pub mod agent_shell_dna + module doc Closes HIGH-2 (dna-three-layer audit). |
||
|
|
766504d345 |
fix(kei-model-router): close 2 HIGH regressions from re-audit
Re-audit (codex + critic-bug) on commit
|
||
|
|
187661714f |
fix(kei-model-router): close 10 audit-blocker findings
Codex CRITICAL + 4 HIGH + 5 MEDIUM/LOW from RULE 0.23 dual-review and
RULE 0.25 multi-critic swarm — all closed.
CRITICAL fix
- Model::slug() ledger compatibility: posterior.rs + select_kernel.rs
query `WHERE model = ?2 OR model = ?3`, binding canonical + legacy
slug pair via new `Model::legacy_slug()`. Production ledger rows
written under "haiku"/"sonnet"/"opus" remain visible to posterior
aggregation. Regression test ledger_legacy_slug_counted.
HIGH fixes
- cmd_select(): no longer early-returns on profile match. Profile's
default_model_ref now becomes DecisionInput.fallback; select() always
runs, posterior/kernel evidence wins if present. RULE 0.20 cost
optimisation restored for all 18 registered agents.
- Registry pricing SSoT: DecisionInput now carries Option<Arc<Registry>>.
estimated_cost() tries registry first; hardcoded match is documented
fallback only. select_posterior.rs no longer duplicates models.toml
constants.
- registry.rs portability: include_str!() embeds the three TOMLs at
compile time. load_embedded() new; disk path tried first via
KEI_REGISTRIES_DIR, embedded as fallback. `cargo install`d binaries
now find registries unconditionally. embedded_registry_matches_disk
test ensures embedded ≡ disk source.
- next_model() ambiguity: replaced Option<&Model> with EscalationResult
enum (Next(&Model) / AtTop / NotFound). Callers can distinguish typo
from ceiling. 5 new tests.
MEDIUM fixes
- posterior.rs u32 overflow: `(n_plus + n_minus) as u32` →
`u32::try_from(n_plus.saturating_add(n_minus)).unwrap_or(u32::MAX)`.
overflow_guard_on_huge_n test with i64::MAX.
- pick() unknown-model: now returns None when default_model_ref's model
is absent from registry. Inverted the deprecation guard.
- HOME unset: disk_registries_dir() returns None on empty HOME and
falls through to embedded registries. open_ledger() logs warning
and returns None instead of opening at malformed path.
- SQLite WAL + busy_timeout: applied to ledger connection in
open_ledger() — concurrent CLI invocations no longer SQLITE_BUSY.
LOW fixes
- impl Model consolidation: next_tier() moved to pricing.rs.
escalate.rs uses current.next_tier() instead of duplicating logic.
- complexity.rs: removed duplicate "ml-implementer" in HEAVY_ROLES.
- dna_class.rs: role("") now returns None instead of Some("").
Verification (orchestrator-side, RULE 0.13 §Verify-before-commit):
- cargo check → clean
- cargo test --release → 63 passed / 0 failed (was 58 → +5 new tests
cover legacy-slug, EscalationResult, overflow, unknown-model, embedded)
- Constructor Pattern → all files ≤ 200 LOC (max registry.rs 196)
- Largest fn from_ledger 28 LOC / limit 30
DNA-INDEX.md regenerated by kei-registry hook (cosmetic).
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
behaviour-verified: yes
follow-up-required:
- (none from this commit; next audit pass before merge to main)
|
||
|
|
4d79049eff |
feat(kei-model-router): registry-driven, three-layer DNA
Removes hardcoded Claude-only Model enum. Pricing constants now read
from _blocks/registries/models.toml at startup; provider/model lookup
goes through a typed Registry returned by registry.rs.
New API surface:
- Registry::load(dir) → (providers, models, profiles)
- pick(profile_id, &Registry) → Result<(provider_id, model_id)>
- cost_micro_cents(model_id, in, out, &Registry) → Option<u64>
- next_model(model_id, &Registry) → Option<&Model> (ascending cost,
same provider, skip deprecated)
Files:
- registry_types.rs new 107 LOC (Provider/Model/Profile structs)
- registry.rs new 152 LOC (TOML load + lookups)
- pricing.rs rew 127 LOC (registry-backed, no constants)
- escalate.rs rew 181 LOC (registry-backed ladder + skip deprecated)
- select.rs rew 131 LOC
- select_kernel.rs new 74 LOC (Constructor-Pattern split)
- select_posterior.rs new 178 LOC (Constructor-Pattern split)
- posterior.rs rew 197 LOC
- calibrate.rs rew 175 LOC
- lib.rs rew 53 LOC
- main.rs rew 163 LOC (CLI updated to new API)
- Cargo.toml dep added toml 0.8
Verification (orchestrator-side, RULE 0.13 §Verify-before-commit):
- cargo check → clean
- cargo test --release → 58 passed / 0 failed / 0 ignored
- LOC limit (Constructor) → max 197 / limit 200
- largest fn cmd_select → ~27 LOC / limit 30
DNA-INDEX.md regenerated by kei-registry hook (primitive count
144 → 150 reflects the 6 new/split modules).
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
behaviour-verified: yes
follow-up-required:
- select.rs `estimated_cost` still embeds inline cost constants
mirroring models.toml; if non-Anthropic providers need dynamic
pricing in select-time estimation, thread Registry through.
- External callers of old `cost_micro_cents(Model, ...)` signature
will break — intentional, no external callers in this workspace.
|
||
|
|
b103a9aa64 |
fix(kei-cortex/test): replace hand-rolled mock with wiremock — closes macOS CI flake
Previous `tests/common/mod.rs` spawned a mock Anthropic upstream via hand-rolled axum + std:🧵:spawn + own current-thread tokio runtime bound to 127.0.0.1:0. Stable on Linux runner; flaked on macOS GitHub Actions runners: thread 'streaming_responses_runs_real_loop_not_stub' panicked at kei-cortex/tests/openai_loop_wiring.rs:277:5: no responses delta event in stream: event: response.error data: {"error":"model: anthropic request: error sending request for url (http://127.0.0.1:49312/v1/messages)"} Root cause traced to macOS-runner loopback / fd-limit pressure on the dedicated-thread current-thread runtime. wiremock crate runs a production-quality hyper-based mock server, manages its own listener lifecycle, and survives the macOS runner constraints. ## Change - `Cargo.toml`: add wiremock = workspace dev-dep (already 0.6 in workspace) - `tests/common/mod.rs::MockAnthropicServer` rebuilt over wiremock::MockServer - `build_mock(text)` mounts `POST /v1/messages → 200 + canned body` on a wiremock instance - `mock_anthropic_responding_with()` spins one per call on a parked helper thread (preserves `MockAnthropicServer: 'static` lifetime for `shared_mock_anthropic` `OnceLock` singleton) - `shared_mock_anthropic()` API unchanged; existing test sites in `tests/openai_loop_wiring.rs` + `tests/openai_compat.rs` continue to work without modification ## Verification `cargo test -p kei-cortex --test openai_loop_wiring`: 7/7 pass locally `cargo test -p kei-cortex`: full suite green (428 lib + integration) Also includes DNA-INDEX regenerate (auto-encyclopedia hook artefact; 0 vortex matches preserved). |
||
|
|
302ca661ec |
chore(docs): regenerate DNA-INDEX without project-vortex
Removes the two banned-project references (project-vortex::vortex and project-vortex::vortex-constraints at lines 703/707 of DNA-INDEX.md pre-regenerate) that surfaced in the public-readiness audit (P0 finding from sub-agent a2c1199a). Source: ~/.claude/registry.sqlite row 391 + ~/.claude/registry-fragments/project-vortex__vortex-constraints.md. Both removed locally so kei-registry encyclopedia regen no longer emits the lines. auto-encyclopedia-refresh.sh PostToolUse:Edit|Write hook will not re-add them on next run since the source row is gone. If the Vortex agent project (cyber-banned per ~/.claude/rules/security.md) needs that rule again, it should be registered into a SEPARATE local-only registry (e.g. ~/.claude/registry-private.sqlite) so it never leaks into the public encyclopedia path. After regen: 0 vortex/neuralcloak/keidog/keinet matches in entire KeiSeiKit-public tree (git grep). Public-readiness P0 = 0. |
||
|
|
8a885a7d76 |
fix(release+slices): v0.14.4 publish auth fallback + 4 fix-implementer slices
After v0.14.3 npm-publish failed again with 401 Unauthorized despite
path-scoped _authToken. Direct curl probe to keigit confirmed BOTH Bearer
and Basic auth schemes work — so the issue is npm 10 not sending the
auth header in CI. Likely cause: deprecated `always-auth=true` interfered
with token resolution.
== Publish auth fix ==
- Drop `always-auth=true` (deprecated in npm 10+; warns in logs)
- Keep path-scoped `_authToken` (npm 10 canonical)
- Add legacy Basic-auth fallback rows (username/_password/email) — Forgejo
accepts both schemes per direct probe; if one resolution path fails,
npm tries the other
- chmod 600 on $HOME/.npmrc and project .npmrc (defense-in-depth)
- Bump 0.14.3 → 0.14.4
== Slice A — TS server hardening (Sonnet code-implementer-typescript) ==
File: _ts_packages/packages/mcp-server/src/server.ts (+3/-1)
File: _ts_packages/packages/mcp-server/src/index.ts (+14/-4)
- safeEqual constant-time path on length mismatch (timing oracle close)
- HTTP server defaults to 127.0.0.1 bind; --bind <addr> opt-in for 0.0.0.0
- Body cap 1 MiB with 413 response (DoS prevention)
- VERIFIED: tsc -b --noEmit exit 0
== Slice B — Outcome-only profile hardening (Sonnet code-implementer) ==
Files: install.sh, install/lib-args.sh, install/lib-profile-outcome-only.sh
- Confirm-screen gate before destructive install (skips on --dry-run / --yes)
- _outcome_install_ledger return value tracked → summary reflects reality
(was: false-success "ledger: ..." when init failed)
- --dry-run silent-ignored on non-outcome profiles → now warns
- VERIFIED: end-to-end smoke against fake $HOME with `<<< "y"` — all 5
files installed, schema v9 + 2 triggers, summary correct
== Slice D — jq-merge dedup tuple (Sonnet code-implementer) ==
File: install/lib-hooks.sh
- Replaced `unique_by(.command)` with reduce-into-object keyed on
norm-ed command (tilde-vs-absolute path collision fix)
- Snippet-wins precedence on collision
- 3 manual scenario traces pass: tilde+tilde, absolute+tilde, idempotency
== Slice E — Doc honesty pass (Sonnet code-implementer, selective-merged) ==
Files: README.md, docs/{INSTALL,ARCHITECTURE,PROFILE-OUTCOME-ONLY}.md
Note: Slice E worktree was based on an older main commit; merged
selectively to preserve current-main values (565 DNAs, not worktree's 518)
- README:62 plugin marketplace URL: KeiSei84/KeiSeiKit → KeiSei84/KeiSeiKit-1.0
(consistent with line 66 git clone URL + Cargo.toml repository field)
- README:9-15: per-claim [REAL: <command>] markers on all 8 numerics
- README:124-132 + PROFILE-OUTCOME-ONLY.md:43-55 + ARCHITECTURE.md:288-302:
rephrase 100-row router claim — now describes Wilson lower-bound
(δ=0.10, q*=0.70) continuous metric with file:line pointer to select.rs
- INSTALL.md: ESTIMATE-HTC marker covering all install-time / disk-size
numerics in profile table (RULE 0.18 compliance)
- PROFILE-OUTCOME-ONLY.md privacy section: discloses agent-toolstats.jsonl
sidecar (was undocumented per W3 finding)
- PROFILE-OUTCOME-ONLY.md uninstall: added 6th rm -f for .bak-* cleanup
(closes orphan-accumulation per W3+W4 audits)
[FROM-JOURNAL: tasks.jsonl this session — 12 audit agents waves 5+6 +
4 parallel fix-implementer worktrees ran ~25 min wall-time]
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
784dfbae6f |
fix(audit-batch-2): regressions from prev batch + 2nd-wave audit findings
12-agent audit (waves 3+4 Opus+Sonnet) on commit |
||
|
|
3759fb0f64 |
fix(audit-batch): CI green + RULE 0.4/0.16/0.18 honesty pass
12-agent audit (2 waves Opus+Sonnet, 6 slices each) flagged 3 HIGH-tier
issues that BOTH waves agreed on, plus 5 doc-honesty findings. This
batch fixes the lot.
== CI green (was failing on main
|
||
|
|
94a7d682c4 |
feat(mcp-server): production publish path via keigit.com (Forgejo npm)
Wire @keisei/mcp-server publish to the author-operated keigit.com Forgejo npm registry. Verified live: keigit.com → 45.77.41.204 (Vultr, public DNS), Caddy → Forgejo 9.0.3, TLS valid, /api/v1/version=200. Why keigit, not GitHub Packages or npm.org: - keigit IS the canonical npm registry for the @keisei scope (operator runs it; no separate vendor account needed) - npm scope @keisei stays @keisei (no rename to match a github org) - Public DNS resolves from any client; auth via per-user PAT - One auth surface for both the git remote and the npm registry Files changed (7): - _ts_packages/packages/mcp-server/package.json · removed `private: true` (was blocking ALL publish, including ours) · added publishConfig.registry = https://keigit.com/api/packages/keisei/npm/ so accidental `npm publish` cannot route to npm.org · added repository field (provenance link to KeiSeiKit-1.0) · added license: Apache-2.0 - README.md (2 hunks): maturity row + install section say "published to keigit.com", show ~/.npmrc setup - PLUGIN.md (3 hunks): same updates referencing keigit - .claude-plugin/mcp-template.json: _comment updated - docs/encyclopedia/substrate-overview.md (1 hunk): MCP row says "alpha" not "stable" + clarifies registry+scope - .github/workflows/release.yml: npm-publish job rewired: · KEIGIT_TOKEN secret instead of NPM_TOKEN as gate · Two-row .npmrc temp-write: @keisei → keigit.com (always when KEIGIT_TOKEN set), npm.org auth as optional fallback · .npmrc cleanup via `if: always()` step - .gitignore: _ts_packages/.npmrc + .npmrc excluded (RULE 0.8) Verification: - node -e 'require("./.../package.json")' parses clean, publishConfig pinned to keigit, private:false [REAL: ran in session] - `npm run build --workspace=@keisei/mcp-server` → tsc -b exit 0, dist/index.js produced [REAL: built in session] - Server starts: `node dist/index.js` lives >1s, doesn't throw, reports expected `[adapters] not installed` for un-built siblings - keigit.com reachable from this machine: HTTP 200 root + Forgejo 9.0.3 version endpoint [REAL: curl ran in session] Required user-side setup before first publish: 1. Create user/org `keisei` on keigit.com (web UI; currently /keisei → 404) 2. Generate a keigit PAT with write:package scope 3. Add as github repo secret KEIGIT_TOKEN 4. Push tag v0.14.1+ → release workflow's npm-publish job picks it up History note: - Earlier in this session a github-packages-scope-rename variant (commit |
||
|
|
542a0a816e |
Revert "feat(mcp-server): production-ready publish path via GitHub Packages"
This reverts commit
|
||
|
|
a6f1c72472 |
feat(mcp-server): production-ready publish path via GitHub Packages
Renamed @keisei/mcp-server → @keisei84/mcp-server (scope must match
github org KeiSei84 for GitHub Packages publish). Replaced private:true
with publishConfig pinned to npm.pkg.github.com so an accidental
`npm publish` cannot leak to npm.org. CI npm-publish job rewired to
GitHub Packages auth (GITHUB_TOKEN with packages:write permission).
Why GitHub Packages, not npm.org:
- Authentication piggybacks on existing github org / PAT — no separate
account or NPM_TOKEN required for the core kit
- Scope @keisei84 maps 1:1 to org KeiSei84 (npm rule for github)
- Doesn't require public DNS for our private Forgejo (Tailscale-only
100.91.246.53 cannot be the publish target — IP-leak in public ref)
- Published artefacts live under github.com/orgs/KeiSei84/packages,
same access surface as the source repo
Why not @keisei (un-scoped or different scope):
- npm scope @keisei IS reachable on npm.org but we don't own it there
(would require email-verified npm account claim + ongoing maintenance)
- @keisei84 requires zero new accounts; works the moment KeiSei84 org
has packages enabled (github default)
Files changed (11):
- _ts_packages/packages/mcp-server/package.json — rename + publishConfig
+ repository field (required by GitHub Packages); removed private:true
- _ts_packages/package-lock.json — regenerated via `npm install`
(workspace recognises @keisei84/mcp-server symlink)
- README.md (2 hunks) — maturity row says "alpha" not
"alpha (unpublished)"; install section documents `~/.npmrc` setup
for `@keisei84:registry=https://npm.pkg.github.com/`
- PLUGIN.md (3 hunks) — same `~/.npmrc` setup; .mcp.json references
@keisei84/mcp-server; "not yet on npm" replaced with "lives on
GitHub Packages, not npm.org"
- .claude-plugin/mcp-template.json — args use @keisei84 scope
- _ts_packages/README.md (4 hunks) — package layout + npx examples
- docs/INSTALL.md, install/lib-rust.sh — comment refs
- docs/encyclopedia/substrate-overview.md (2 hunks) — package table +
publishing notes (was "published to keigit.com npm" — wrong; keigit
is a separate community-publish path for user-contributed packages,
not the destination for core @keisei84 packages)
- .github/workflows/release.yml — npm-publish job rebuilt:
· permissions: packages:write
· Two-scope .npmrc temp-write: @keisei84 → npm.pkg.github.com (always),
@keisei → npm.org (only if NPM_TOKEN secret set, else skipped per pkg)
· NODE_AUTH_TOKEN sourced from GITHUB_TOKEN
· .npmrc cleaned up via `if: always()` step
- .gitignore — _ts_packages/.npmrc + .npmrc excluded (RULE 0.8: auth
tokens never in git; CI temp-creates per-job)
Verification:
- `npm install` clean against new scope: node_modules/@keisei84/mcp-server
symlinks to packages/mcp-server, other adapters untouched in
node_modules/@keisei/* [REAL: install ran 2026-05-03 in this session]
- `npm run build --workspace=@keisei84/mcp-server` produces dist/index.js
[REAL: tsc -b exit 0]
- Server starts cleanly: `node dist/index.js` runs >1s, emits expected
"[adapters] not installed" warnings for un-built sibling adapters,
doesn't throw
- 17 references to old @keisei/mcp-server scope migrated; 0 left
[REAL: grep -rn "@keisei/mcp-server" returns 0 lines]
Bad-commit-hygiene note:
- Two earlier local commits (cb8dc2a + revert 474fe1c) attempted a
keigit.com-pinned variant; soft-reset past them so this commit lands
on top of public
|
||
|
|
2bb2f10af0 |
docs: add 6-file substrate encyclopedia (1739 LOC)
Generated by parallel Haiku writer agents during 4-wave audit; covers the substrate at the top-down explanatory level the reviewer asked for. - substrate-overview.md (425 LOC) — top-down: what runs at install, daily, nightly; data-flow ASCII diagrams; how the 4 layers fit - hooks-and-blocks.md (394 LOC) — every hook + every assembler block, with trigger event + severity + rule reference - rust-crates-A-G.md (507 LOC) — first third of the 106 crates, one paragraph per crate - rust-crates-H-N.md (194 LOC) — middle third - rust-crates-O-Z.md (59 LOC) — last third (smaller because alphabet) - skills-and-agents.md (160 LOC) — 67 skills + 43 agent manifests, one row each Encyclopedia complements the auto-generated DNA-INDEX.md: that file is mechanical (count + DNA prefix + sha8), this is narrative (what does this thing do, when does it fire, how to use it). Username-path leaks scrubbed via sed pre-commit: - /Users/<user>/Projects/KeiSeiKit-public/ → <repo>/ - /Users/<user>/ → <home>/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6b66914f97 |
feat(install): outcome-only minimum profile
Reviewer suggested an evaluation footprint that lands "the smallest substrate any caller-LLM can use", with 5 files and ~200 LOC ceiling in $HOME. This commit ships that profile. Files installed in $HOME by `./install.sh --profile=outcome-only`: 1. ~/.claude/hooks/agent-outcome-backfill.sh (PostToolUse:Agent) 2. ~/.claude/hooks/error-spike-detector.sh (PostToolUse:Bash, rolling 20-call window) 3. ~/.claude/agents/ledger.sqlite (full v9 schema via kei-ledger init, or sqlite3-fallback DDL) 4. ~/.claude/CLAUDE.md (1-line STATUS-TRUTH MARKER instruction appended) 5. ~/.claude/settings.json (jq-merge of 2 hook entries) Plus optional 6th: kei-model-router binary built from _primitives/_rust if cargo on PATH; deferred otherwise (warning printed, install continues). Files added to repo: - install/lib-profile-outcome-only.sh (145 LOC) — profile orchestrator with --dry-run support; sources lib-log/lib-backup/lib-hooks helpers; exits before heavy install phases when --profile=outcome-only - install/sql/outcome-only-schema.sql (69 LOC) — flattened v9-equivalent SQLite DDL (agents + skill_invocations + indexes), used by sqlite3 fallback when kei-ledger CLI is unavailable - docs/PROFILE-OUTCOME-ONLY.md (97 LOC) — reviewer-facing doc: 5-file install table, what is NOT installed, kei-model-router activation explanation, privacy posture (no telemetry), 4-line uninstall paste Files modified: - install.sh (+12 LOC) — sources outcome-only lib, adds short-circuit before menu when --profile=outcome-only, accepts in profile validator - install/lib-args.sh (+9 LOC) — registers --dry-run flag (sets OUTCOME_DRY_RUN=1), adds outcome-only + --dry-run lines to --help - README.md (+7 LOC) — adds Outcome-only Quick-start section pointing to PROFILE-OUTCOME-ONLY.md Verification: - bash -n clean on all 3 modified shell files - Dry-run produces exactly 5 numbered $HOME paths (verified end-to-end: HOME=/tmp/kei-fake-home bash install.sh --profile=outcome-only --dry-run) - Real install against fake $HOME succeeds (5 files present, ledger init via kei-ledger binary, router build correctly skipped on toolchain absence with warning) - Ledger schema includes agents + skill_invocations tables + 3 indexes + 2 triggers via real migration path (not the SQL fallback) [FROM-JOURNAL: end-to-end install dry-run + real-run measured at ~/.claude/memory/time-metrics/sessions.jsonl this session, both <2s wall] Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d2068cded7 |
docs: reviewer-response — honesty pass + portable format specs
External reviewer raised 7 overclaim/scope concerns. Agents verified each
against source; this commit applies all fixes that landed in docs.
Honesty pass:
- README:25-29 — Cortex daemon track listed as alpha (was beta); MCP server
marked "alpha (unpublished) — install via local dist build"; Phase B
noted "auto-codification not yet wired (manual via /escalate-recurrence)";
keigit framed as author-operated mirror (KeiSei84 / private Forgejo),
not neutral community service
- README:95-97 — Cortex CLI/daemon track downgraded beta→alpha
with rationale (browser-app + VSCode-extension are concept-level)
- docs/ARCHITECTURE.md — added "Model router — current state (2026-05-03)"
subsection: per-call fixed estimate routing, NO 100-row Bayesian threshold
in current source (select.rs:74-124); reviewer suggestion deferred
- docs/SLEEP-LAYER.md — added Phase B scope clarification: morning report
is read-only markdown, no auto-codification path
- docs/PUBLISHING.md — aligned framing with README:43 ("author-operated
mirror" not "community registry"); added vendor-neutrality note that
substrate works against any npm-compatible registry
- mcp-server/package.json — added "private": true and description note
to prevent accidental publish before maturity gate
Portable format specs (reviewer asked for memory-repo agnosticism):
- docs/MEMORY-FORMAT.md (196 LOC) — JSONL schemas for traces / decisions /
agent-events with jq/awk/pandas recipes, grounded in actual writers
- docs/DNA-FORMAT.md (159 LOC) — DNA wire format ("type::caps::sha8")
with shell+python parsers
- docs/LEDGER-SCHEMA.md (199 LOC) — full SQLite DDL (agents +
skill_invocations + indexes + triggers) with sample queries
Auto-regen artifact:
- docs/DNA-INDEX.md — kei-registry regenerated count 564→565
Verification:
- All claims traced to file:line in source by agent a52b29ae
- All new docs ≤200 LOC per Constructor Pattern
- Reality verification verdicts: README/MCP/Phase-B/Cortex VERIFIED;
Bayesian-router PARTIAL (overclaim removed); keigit PARTIAL (framing
fixed in this commit); memory-format VERIFIED-FALSE (spec added)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
036bc6a52e |
docs: SKILL.md triggers + STATUS-TRUTH footer + phase placeholders
Group G — markdown tech-debt cleanup (post-audit 2026-05-02).
- 36 SKILL.md files: added "## When to use" section. Was missing across the
catalog; orchestrator routing by keyword could not auto-dispatch.
- 20 code-implementer agent .md files: added Output Footer block prescribing
RULE 0.16 STATUS-TRUTH MARKER schema in agent's final report. Previously only
code-implementer-rust.md had it; other 27 language/role variants were silent
about the marker, breaking RULE 0.16 §3 status-truth aggregation for non-Rust
batches.
- skills/site-create/: added phase-5-preview.md and phase-6-deploy.md skeleton
files. SKILL.md table-of-contents referenced 7 phases; only 5 existed on disk.
- skills/{ai-animation,rag-pipeline}/skill.md: added migration banner comment
noting they should be SKILL.md (canonical filename). Case-rename via git is a
separate orchestrator task (macOS APFS is case-insensitive; Linux deploy needs
explicit rename).
- 3 deprecated skills (site-builder, competitor-analysis, design-inspiration):
added concrete removed-after dates (was vague "before v2").
- docs/CONVERGENCE-PLAN.md:129: TBD on _blocks/evidence-grading.md duplicate
resolved (file exists, not duplicated).
- docs/DNA-INDEX.md: count edits made then overwritten by auto-encyclopedia-refresh
hook during agent run. The .kei-registry-ignore files in test fixtures (Group F)
are the structural fix; kei-registry walker implementation is the follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
52a02dfbff |
feat(live-graph): WebSocket activity stream — orchestrator-centric live view
User pushback: "транслирует в онлайне какие агенты создаются? основное
окно агента, а дальше при запусках появляются новые ветки, мы показываем
в онлайне как агенты собираются и работают"
Earlier `kei-graph-export` rendered the static SUBSTRATE (all 581 atoms,
catalog-style). User wanted the LIFECYCLE: orchestrator at center, every
new agent as a fading-in branch, every tool call as a pulse, every
completion as a fade-out. TTL = until done; pure online, no history
accumulation per user direction.
Three-layer architecture, all conforming to schema /tmp/agent-events-schema.md:
LAYER 1 — Event emitters (4 hooks)
hooks/agent-event-spawn.sh PreToolUse:Agent → agent_spawn event
hooks/agent-event-done.sh PostToolUse:Agent → agent_done event
(parses STATUS-TRUTH MARKER for outcome,
computes cost_usd from token×pricing table)
hooks/tool-use-event.sh PreToolUse:Bash|Read|Edit|Write|Grep|Glob|NotebookEdit
→ tool_use event
hooks/skill-record.sh EXTENDED — second emit step writes skill_use
event in addition to existing kei-ledger
record-skill call
All 4 are POSIX /bin/sh, defensive (never block, exit 0), bypass via
KEI_EVENTS_BYPASS=1. Append-only JSONL to
~/.claude/memory/agent-events.jsonl.
Smoke: 4 synthetic invocations cover spawn/done/tool/filter cases.
LAYER 2 — kei-graph-stream Rust daemon
_primitives/_rust/kei-graph-stream/ (~480 LOC, 5 files + 1 test)
- Tails events.jsonl every 200ms (poll-based, no notify dep).
- Parses each event, updates AliveState (insert on spawn, remove on done).
- Broadcasts {"type":"event","data":<event>} to all WebSocket clients.
- On client connect: sends {"type":"snapshot","alive":[...]} first.
- Heartbeat: {"type":"ping"} every 30s.
- axum 0.7 + ws feature (already in Cargo.lock via kei-cortex).
- Bypass: KEI_GRAPH_STREAM_BYPASS=1.
Bound to 127.0.0.1:8201 (loopback only). Endpoints:
GET /stream → WebSocket upgrade
GET /health → "kei-graph-stream alive"
4 unit + 1 integration test. cargo build clean.
Installed binary: ~/.cargo/bin/kei-graph-stream
Launchd plist: io.keisei.graph-stream (RunAtLoad, KeepAlive)
Loaded as PID 52678, /health 200 OK verified.
LAYER 3 — live-graph.html (single-file frontend)
~/Projects/lbm-graph-viz/live-graph.html (~464 LOC, self-contained)
- SVG full-viewport, dark #0f172a, CSS grid background.
- Pinned center node "main" (orchestrator), gold #fbbf24, glowing.
- Agents radiate via D3 force-simulation; color-by-model
(sonnet=green, opus=red, haiku=blue, default=gray).
- On agent_spawn: fade-in 300ms, edge from main to new node.
- On tool_use: pulse on agent node (r 8→12→8 over 400ms) +
floating tool name label fades 800ms.
- On agent_done: outcome-color flash → fade-out 800ms → remove.
- WebSocket client: ws://127.0.0.1:8201/stream, exponential-backoff
reconnect (1s→30s).
- Top-right status badge: ● connected | ○ reconnecting | ✕ disconnected.
- Bottom counters: alive / spawned / tool calls / done / last event age.
- No build step. D3 v7 from CDN. Pure HTML+JS+CSS.
End-to-end smoke (this machine, just now):
- daemon health 200 OK
- hook injected agent_spawn → daemon broadcasts → AliveState=1
- hook injected agent_done → daemon broadcasts → AliveState=0
- frontend file syntax-checked clean
What this does NOT do (deferred, by user direction "это онлайн"):
- History persistence — agents who finished are GONE from the graph.
Per-session log remains in events.jsonl + sleep-sync if user wants
to consult later, but the live view is RIGHT NOW only.
- Sub-agent attribution beyond "main" — orchestrator-direct tool calls
show on the orchestrator node. Sub-agent's internal tool calls would
need session-id correlation; current schema has agent_id="main"
placeholder for non-Agent tool calls.
- Replay mode — no time-scrubber. Possible follow-up if useful.
- Auth on WebSocket — bound to 127.0.0.1 only. Local-only by design.
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
behaviour-verified: yes
follow-up-required:
- Sub-agent tool-call attribution (correlate session_id chain)
- Replay mode with time scrubber (if user finds use)
- Tool aggregator nodes ("Bash bucket" with N) instead of per-agent pulses
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
a31a056f61 |
feat(graph): live runtime DNA viewer — kei-graph-export + lbm-graph-viz adapter
User pushback: "можно нашего Кейси подключить к обсидиан? будет в
онлайне строить граф из всех наших агентов?"
Closer-to-question architecture: don't build new Obsidian plugin —
re-use the legacy `~/Projects/lbm-graph-viz/` D3 viewer (lineage:
keicode → living-graph → lbm → lbm-graph-viz → keisei-graph). Strip
its Hebbian/co-change edges, replace with DNA-derived edges from the
kei-registry + kei-ledger. Open in any browser, file://...index.html.
NEW Rust crate `_primitives/_rust/kei-graph-export/` (~440 LOC, 5 files)
Reads:
~/.claude/registry.sqlite (730 active blocks)
~/.claude/agents/ledger.sqlite (6 agents post-cleanup)
_manifests/*.toml (38 agent manifests)
Emits 581-node, 291-edge graph. Edge types:
block_dep 171 manifest → atom (blocks=[])
path_ref 99 manifest → atom (path:NAME refs)
branch_lineage 11 parent_branch → branch
agent_uses_manifest 10 agent → manifest (slug from branch name)
Output formats:
--format spaces-fragment → `window.RUNTIME_SPACE = {...}` JS file
--format json → raw {nodes, links} for downstream tools
Block-name lookup is multi-resolution: each block is registered under
display name + lowercased + file-stem slug (from path basename) so
manifest references like `blocks = ["baseline"]` resolve to a registry
row whose `name` column holds "BASELINE — inherit from Main Claude".
Without this fix the graph had 0 block_dep edges; with it, 171.
NEW background updater `hooks/graph-export-watcher.sh` + launchd plist
template `_primitives/templates/io.keisei.graph-export.plist`
5-second loop:
while true; do
kei-graph-export --format spaces-fragment --output <viz>/data-runtime.js.tmp
mv <viz>/data-runtime.js.tmp <viz>/data-runtime.js # atomic
sleep 5
done
launchd plist substitutes `HOME_DIR` and `HOOKS_DIR` placeholders at
install time. RunAtLoad=true, KeepAlive=true. Logs to
~/.claude/memory/graph-export.log. Bypass: GRAPH_EXPORT_BYPASS=1.
Loaded into user-side launchd (PID 16474 confirmed running). File
mtime advances every 5s — live updates verified.
PATCH `~/Projects/lbm-graph-viz/index.html` (outside kit, surgical)
Three changes:
1. Add `<script src="data-runtime.js">` BEFORE `spaces.js` (window
global available when SPACES is defined).
2. After spaces.js: `if (window.RUNTIME_SPACE) SPACES.runtime = window.RUNTIME_SPACE;`
3. Auto-refresh setInterval(5s): fetch data-runtime.js, eval (re-
assigns window.RUNTIME_SPACE), hash-compare, re-render via
`rebuildGraph()` if currently viewing the runtime space.
window.RUNTIME_SPACE (not const RUNTIME_SPACE) avoids the
"const cannot be re-declared" error on subsequent eval() calls.
Effect: open file://~/Projects/lbm-graph-viz/index.html in any
browser, switch to "Runtime" space — full DNA graph of every agent /
atom / skill / branch / manifest / hook / primitive / rule, force-
laid-out by D3. Updates every 5 seconds without page reload.
What this does NOT do (deferred):
- Obsidian mirror — separate work, would emit .md per node into
~/Projects/KeiSeiVault/. Useful for backlinks navigation but
file-watcher latency similar to current 5s polling.
- Skill-invocation edges — table is empty until next Skill tool
use; will populate naturally.
- Scoped queries (orphan finder, hot-path PageRank). Out of scope
for v1; the JSON --format export feeds any downstream tool.
- `agent_uses_manifest` heuristic warns on unknown subagent slugs
(e.g. `physics-deriver` with no manifest yet). Non-fatal.
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
behaviour-verified: yes
follow-up-required:
- Obsidian vault mirror (Phase C, separate work)
- Skill-edges populate from real Skill use (not blockered)
- Hot-path PageRank highlighting in viewer (cosmetic)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
e073df6c98 |
feat(tracking): close 3 last observability gaps — toolStats + skill-record + numeric-claims journal
Closes the loop on "without full tracking the system can't make decisions" (user pushback on partial coverage). Three gaps that left the inference layer blind are now wired: GAP #1 — agent toolStats / token counts / cache hits captured ================================================================ `agent-outcome-backfill.sh` now appends one JSONL row per spawn to `~/.claude/memory/time-metrics/agent-toolstats.jsonl` with: agent_id, outcome, stubs, ts, tool_use_count, duration_ms, tool_stats {Read:N, Bash:M, ...}, tokens_in, tokens_out, cache_read, cache_write Sidecar journal (no schema migration). Production payload's .tool_response.totalToolUseCount / totalDurationMs / toolStats / usage fields land directly. Smoke-tested with synthetic spawn — row written. GAP #2 — skill_invocations table actually receives writes ================================================================ The `skill_invocations` table (schema v8) had 0 rows because no caller existed for `skill_metrics::record_invocation`. Added two pieces: (a) `kei-ledger record-skill <name> --success {0|1}` CLI subcommand Mirrors record-cost; same dispatch shape. Optional `--agent-id`, `--trajectory-id`, `--duration-ms`, `--db`. Validates non-empty name + duration ≥ 0. Outputs `{"ok":true,"skill":"...","ts":N}`. (b) `hooks/skill-record.sh` — PostToolUse:Skill hook. 50 LOC POSIX. Detects Skill tool calls, derives success heuristic from tool_response (exit_code / status / content non-empty), shells out to `kei-ledger record-skill`. Bypass via SKILL_RECORD_BYPASS=1. 83 kei-ledger tests pass (16 unit + 67 integration). Smoke-tested end-to-end: `kei-ledger record-skill test-skill --success 1` inserts a row with correct fields. Phase D nightly skill-metrics decisions (archive if unused N days, re-extract if success<60% over M days, validated if >20 calls + >90% success) now have data to consume. GAP #3 — numeric-claims.jsonl receives every evidence-tagged claim ================================================================ RULE 0.18 mandated three markers `[REAL:]` / `[FROM-JOURNAL:]` / `[ESTIMATE-HTC:]` on every numeric/duration/cost claim, but no hook appended valid claims to the journal — the calibration data RULE 0.18 promised never accumulated. `hooks/numeric-claims-record.sh` — Stop hook, 140 LOC POSIX. Reads transcript_path from stdin, locates the last assistant message via recursive flatten (same pattern as agent-outcome-backfill.sh after the production-payload-shape fix), regex-extracts every `<phrase> [<TIER>: <pointer>]` triple, appends one JSONL row per claim. Idempotent within 1-second window to avoid double-recording on repeat Stop fires. Bypass via NUMERIC_CLAIMS_RECORD_BYPASS=1. Smoke test: synthetic transcript with 3 markers (REAL + ESTIMATE-HTC + FROM-JOURNAL) produced exactly 3 well-formed JSONL rows. Settings.json ================================================================ - PostToolUse:Skill matcher created (or augmented if already present) with skill-record.sh. - Stop:* matcher gains numeric-claims-record.sh after the existing chain (stop-verify, task-timer, session-end-dump, extract-task- durations, chat-numeric-postflag, affect-threshold-check, enrich-from-jsonl). What this does NOT do (deferred): - Backfill `skill_invocations` from past traces (history started today; Phase D cohort builds forward from now). - Migrate the agent toolStats sidecar JSONL into a proper ledger column. Append-only file is fine for the current scale. - Refactor main.rs (now 233 LOC, was 212; pre-existing CP debt flagged by skill-record agent — separate cleanup PR). === STATUS-TRUTH MARKER === shipped: functional stubs: 0 cargo-check: PASS behaviour-verified: yes follow-up-required: - kei-ledger main.rs Constructor Pattern split (212→233 LOC) - Verify in next session: skill_invocations gets rows from real Skill tool use; numeric-claims.jsonl gets rows from real assistant messages with markers Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
033b9efbad |
fix(outcome-hook): production payload uses object.content[*].text shape
Hook never fired in production despite passing unit tests. Diagnosed via debug-log + payload dump: real Claude Code PostToolUse:Agent sends `tool_response` as an OBJECT (not string, not array), with the agent's reply at `tool_response.content[0].text` — keys: agentId / agentType / content / prompt / status / toolStats / totalDurationMs / totalTokens / totalToolUseCount / usage. Original jq filter handled string + object (`$r.content // $r.text`) but `$r.content` returns the array verbatim; `jq -r` then dumps the JSON literal which has `\n` as escape sequences, defeating the `grep -m1 '^shipped:'` line-anchor. Fix: recursive `flatten` jq function: string → as-is array of any → recurse, join "\n" object with .text → return .text object with .content → recurse into content anything else → "" Verified end-to-end: latest 4 code-implementer spawns now write outcome=functional to ledger correctly. Beta posterior in kei-model-router begins receiving signal. Production cleanup: - Removed verbose debug-log + payload-dump diagnostic. Toggle via `AGENT_OUTCOME_DEBUG=1` env if hook stops firing in some future Claude Code version. - Hook source committed to `hooks/agent-outcome-backfill.sh` so `install.sh` deploys it on fresh installs (was only in user-home previously — gap from `feat/substrate-path-atoms` agent run). === STATUS-TRUTH MARKER === shipped: functional stubs: 0 cargo-check: NOT-RUN behaviour-verified: yes follow-up-required: - none Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
af46684330 |
feat(secrets+catalog): orphan-detector for env vars + image/video/voice models
Two parallel agents (both Sonnet 4.6 via the just-activated tier system)
extended the substrate-unified-registry. First end-to-end proof that the
Phase 4 router refactor saves money: no Opus spawns this round.
PART 1 — `kei-registry secrets` subcommand (Agent A — code-implementer)
Reads env-var NAMES from `~/.claude/secrets/.env` (RULE 0.8 SSoT) and
per-project `secrets/*.env`, greps the kit tree for usages, reports
orphans (defined but unreferenced). Live run on this kit found 26 keys,
11 ORPHAN — actionable cleanup candidates incl. GitHub OAuth client
creds, Godaddy keys, KeiGit admin creds, KEI_MEMORY_TOKEN.
Files:
- `_primitives/_rust/kei-registry/src/secrets.rs` (152 LOC) — pure
read-side cube. SecretsReport + KeyRow types, env-file parser
(KEY=value lines, validates `^[A-Z][A-Z0-9_]*$`), walkdir-based
scanner with skips (target/ node_modules/ .git/ _generated/),
word-boundary regex per key. ASCII + JSON render.
- `_primitives/_rust/kei-registry/src/secrets_tests.rs` (125 LOC) —
5 unit tests covering env parse, scan correctness, word-boundary
regression (`MY_KEY` ≠ `MY_KEY_EXTRA`), JSON roundtrip, ORPHAN marker.
- `_primitives/_rust/kei-registry/src/secrets_handler.rs` (58 LOC) —
CLI dispatch handler.
- `cli.rs`, `handlers.rs`, `lib.rs` extended with Secrets variant.
Resolves the asymmetry called out in the design discussion: paths got
atomization (commit
|
||
|
|
be1a864629 |
feat(outcome-hook): PostToolUse:Agent backfills outcome + stubs in ledger
Phase 4 follow-up: the outcome-backfill hook the kei-model-router
needs to learn from. Without an outcome signal the Beta posterior
sees 205 NULL rows and can never converge → router falls back to
top-tier on every spawn. This hook closes that loop.
Spawned by orchestrator as a code-implementer agent (Sonnet 4.6 by
default after the manifest refactor in
|
||
|
|
3422bdc8c3 |
feat(path-atoms): atomize ~/.claude memory + rules path references
Phase 1 of substrate-unified-registry: move all references to user
home memory/rules out of plain strings and into content-addressable
path atoms. Public artefacts now contain opaque `{path::NAME}/file.md`
references; the actual home prefix lives only in the path-atom file's
frontmatter, registered in the local kei-registry.
NEW path atoms (`_blocks/path-*.md`):
- `path-user-memory.md` → template `~/.claude/memory`
- `path-user-rules.md` → template `~/.claude/rules`
Both files use frontmatter `type: atom, kind: path, template: ..., expand_at: render`.
BlockMdScanner auto-registers them; DNA index shows them under their
unprefixed names (`user-memory`, `user-rules`) for human lookup, while
the body sha8 makes them content-addressable.
Resolver (`_assembler/src/registry_client.rs`):
- `is_path_atom(conn, name)` — checks DB by name + filename convention
(`_blocks/path-<name>.md`) + frontmatter `kind: path`. Defensive:
filename + frontmatter must BOTH agree.
- `frontmatter_has_kind_path(body)` — minimal YAML parser. Tolerates
CRLF, quoted values, rejects substring matches (`pathological` ≠ `path`).
- 5 unit tests cover positive + 4 negative cases.
Resolver wire-up (`_assembler/src/assembler.rs:147 write_references`):
- For each `references.extra` entry starting with `path:NAME/...`:
- Lookup `NAME` via `is_path_atom`.
- On success: emit `{path::NAME}/<suffix>` — opaque, kit-resolvable.
- On miss: stderr warn + passthrough. Never fatal.
- Non-`path:` refs pass through unchanged. Backward compatible.
- 2 unit tests cover passthrough paths.
Manifest migration (38 manifests touched):
- `~/.claude/rules/<file>` → `path:user-rules/<file>`
- `~/.claude/memory/<file>` → `path:user-memory/<file>`
- 96 references migrated; 1 prose-style reference in security-auditor
left as plain text (lives inside a domain_in description, not in
references.extra — out of scope for this resolver).
Regenerated 38 `_generated/*.md` + 1 new `frontend-validator.md`.
Regenerated `docs/DNA-INDEX.md` (now includes 2 path-atoms by name).
Verification (cited):
- `git ls-files | grep denisparfionovich` → 0 hits outside allowlist
(NOTICE/README byline + `.github/workflows/leak-check.yml` detection
rule).
- `_generated/` contains 99 occurrences of `{path::user-...}/`.
- assembler tests: 29 passed (5 new). kei-registry tests: 10 passed
(8 short_path from earlier commit + 2 unrelated).
- assembler resolver verified end-to-end: ml-implementer.md line
479-485 shows `{path::user-rules}/ml-protocol.md` etc.
What this does NOT do (deferred):
- No registry-DB schema change. Path atoms ride existing Atom block-
type via convention, not via new `BlockType::PathAtom` variant.
- No git-branch tracking (Phase 2 of plan).
- No `kei-registry status` cross-cutting CLI (Phase 3 of plan).
- No path-atom orphan detection CLI (Phase 4).
The path:user-memory and path:user-rules cover 100% of the username-
leak surface from the current manifest set; future categories
(kit-root, registry-db, sync-repo, secrets-env, project-root) can
land additively without architectural changes.
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
behaviour-verified: yes
follow-up-required:
- Phase 2 (git-branch tracker hook)
- Phase 3 (kei-registry status subcommand)
- Phase 4 (orphan detection CLI)
- Sync user-side install: ~/.claude/agents/_manifests/ still has
pre-migration absolute paths; will pick up new format on next
`install.sh --add` (out of scope for this commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
22ae9d1de5 |
fix(kei-registry): short_path strips _blocks/_manifests/_atoms/_roles/_caps/agents
Root-cause of the username-path leak in DNA-INDEX.md (107 atom rows in v0.17 — sed-patched in |
||
|
|
a23910d445 |
chore(security): scrub username paths from public artefacts + leak-check CI
Public repo had absolute paths revealing username: - 5 _manifests/*.toml — companion_memory_files had author-time hardcoded ~/.claude/projects/-Users-<user>/memory/... paths - 5 _generated/*.md — same paths rendered through to public output - docs/DNA-INDEX.md — 107 absolute paths (kei-dna-index emits absolute for atoms but relative for primitives — generator inconsistency) - skills/escalate-recurrence/SKILL.md — 2 instructional path examples Substitution: ~/.claude/projects/-Users-<user>/memory/ -> ~/.claude/memory/ /Users/<user>/Projects/KeiSeiKit-public/ -> <relative> Defence-in-depth: - .github/workflows/leak-check.yml — CI gate (PR + push to main) - (local) .git/hooks/pre-commit — maintainer-side guard with allowlist for legitimate detection-rule files (the hook + the workflow itself) NOTICE + README byline allowlisted (intentional copyright). No secrets exposed — only metadata (username + private-memory filenames). DNA-INDEX root-cause fix in kei-dna-index Rust binary tracked as TODO. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
740889c422 |
chore: regenerate DNA-INDEX after kit changes (kei-db-contract + Wave B follow-up)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f3f5f79760 |
feat(frontend-loop): kei-db-contract primitive + frontend-validator agent + auto-dev-guard hook
Frontend continuous-quality loop landed. Three composable cubes:
Wave 1 — kei-db-contract primitive (~870 LOC, 7 cubes per Constructor Pattern):
- Diffs SQL CREATE TABLE migrations against TypeScript type/interface declarations
- 4 drift modes: ORPHAN-SQL, ORPHAN-TS, TYPE-MISMATCH, NULL-MISMATCH
- Reuses sqlparser-rs (Apache 2.0) + regex + walkdir + serde_json + clap
- CLI: kei-db-contract <project-root> [--output json|text] [--strict]
- 5/5 integration tests pass (cargo check + cargo test green)
- Smoke-tested on keisei-marketplace: drift_count=266 across 30 tables
(expected — marketplace uses raw better-sqlite3 without explicit row types)
Wave 2 — frontend-validator agent + dev-guard skill extension:
- New _manifests/frontend-validator.toml (substrate_role: edit-local, tools: Bash+Read+Glob+Grep)
- Agent runs: stack detect → tsc --noEmit → eslint → kei-db-contract → playwright (optional)
- Severity rules: TYPE_CHECK FAIL = block, DB_CONTRACT drift > 0 = block, lint = advisory
- skills/dev-guard/SKILL.md extended: 4th agent triggered on .tsx/.ts/.dart edits or DB-layer touches
- adaptive-depth table extended with frontend + DB-layer rows
Wave 3 — auto-dev-guard.sh hook (PostToolUse:Edit|Write):
- Trivial-edit gate: skip if delta < 30 LOC (avoid spawn fatigue)
- File-pattern match: *.tsx|*.ts|*.svelte|*.vue|*.dart OR migrations/*.sql OR src/db/** OR src/types/** OR prisma/schema.prisma OR drizzle.config.*
- Auto-runs kei-db-contract for DB-layer edits if binary on PATH
- Stderr advisory only (exit 0 always — never blocks)
- Bypass: KEI_DISABLED_HOOKS or KEI_HOOK_PROFILE in {advisory-off, minimal, off}
- Smoke-tested with synthetic Edit input (39 LOC delta on .tsx → emits advisory)
- Registered in hooks/hooks.json under PostToolUse:Write|Edit chain
Reusability map (Constructor Pattern compose):
shared cubes: detect-stack, tsc, eslint, kei-db-contract, kei-visual-snapshot (deferred)
orchestrators: /dev-start (pre), /dev-guard (during, NOW with frontend-validator),
/dev-ship (final), /site-create (init)
Verify-before-commit (RULE 0.13):
- cargo check -p kei-db-contract: PASS
- cargo test -p kei-db-contract: 5 passed
- jq . hooks/hooks.json: valid
- bash hooks/auto-dev-guard.sh < synthetic-input: works (frontend-relevant edit detected, exit 0)
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
cargo-test: PASS (5 tests, 0 failures)
behaviour-verified: yes
follow-up-required:
- kei-visual-snapshot primitive (Playwright wrap) — Wave 4, deferred
- /dev-start frontend-contract-designer agent + /dev-ship frontend-final-gate — Wave 5, after Wave 1-3 obkatka
- install.sh wiring for kei-db-contract binary
- hermes-style emit-on-drift advisory mode
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
902fb3e81a |
feat(kei-memory): functional schema fix + 4-wave architecture refactor
Wave A — Functional ingest fix (root cause of empty Sleep reports):
- Rewrote TraceLine struct to match real Claude Code trace JSONL:
type (was kind), timestamp ISO8601 (was epoch ts), message Object,
cwd / gitBranch / parentUuid / uuid / subtype / toolUseID / toolUseResult
- New src/extract.rs: extract_tool_uses + extract_tool_result walks
message.content[] for nested tool_use / tool_result blocks
- New src/classifier.rs: explicit table classifier (tool_error, user_correction,
retry_loop, permission_denied, tool_use:<name>, ...) replaces shallow heuristic
- New src/error.rs: KeiMemoryError enum (IO/Parse/Db) replaces semantic
mismatch where IO error was wrapped as rusqlite::InvalidParameterName
- New src/trace_line.rs: TraceLine + helpers (cube extraction)
- Schema migration v3: events.cwd column + 3 hot-query indices
(events.tool, events.file_path, events.ts) + UNIQUE on patterns
- New tests/ingest_real_trace.rs: synth-fixture asserts tool/file/cwd/class extraction
Wave B — Lib crate split:
- Cargo.toml: [lib] target added alongside existing [[bin]]
- src/lib.rs: pub re-export of all 18 modules
- src/main.rs: 11 mod declarations replaced by single use kei_memory::{…}
- tests/integration.rs: #[path] hack replaced by use kei_memory::{…}
Wave C — TF-IDF dedup + single-JOIN + filter_map fix:
- Schema migration v2: tokens.idf_dirty column + flag-based dedup
- index_document no longer triggers per-call recompute_idf rebuild
- top_similar uses single JOIN via vectors_for_overlapping_sessions helper
(was N round-trips, one session_vector per candidate)
- All filter_map(|r| r.ok()) row-error swallowing replaced with ? propagation
- New tests/tfidf_idf_dedup.rs: 4 tests covering dedup behaviour, IDF emptiness,
JOIN-pruning, empty-query safety
Wave D — Commands split + nits:
- New src/dump.rs (43 LOC) + src/stats.rs (33 LOC):
CLI renderers extracted from commands.rs (was inline SQL + format)
- src/commands.rs: thin wrappers, -42 LOC
- src/injection_guard.rs: inline tests removed (-26 LOC), file under 200 LOC threshold
- tests/injection_guard_unit.rs (new): 4 tests in proper integration crate
- src/patterns.rs: INSERT replaced with INSERT...ON CONFLICT...DO UPDATE
(idempotent re-ingest, uses Wave A's UNIQUE index)
- src/analyze.rs + src/coaccess.rs: filter_map row-error fixes
- src/coaccess.rs: misleading PK comment rewritten
Verify-before-commit (RULE 0.13 §"Verify-before-commit"):
- cargo check --all-targets: PASS (1 unrelated dead-code warning)
- cargo test: 42 passed, 0 failed across 9 test binaries
- STATUS-TRUTH markers aggregated at .claude/agents/_merge/kei-memory-2026-05-01/
Architect-spotted ARCH-MAJOR + ARCH-MINOR + ARCH-NIT findings addressed:
- ARCH-MAJOR Cargo.toml binary-only (Wave B)
- ARCH-MAJOR schema missing indices (Wave A v3)
- ARCH-MAJOR ingest_jsonl choke point (Wave A — extract.rs + classifier.rs)
- ARCH-MAJOR idf O(N·V) per-call rebuild (Wave C)
- ARCH-MINOR patterns no UPSERT (Wave D)
- ARCH-MINOR commands.rs houses dump+stats (Wave D)
- ARCH-MINOR classifier silent contract (Wave A)
- ARCH-MINOR IO error wrapped as rusqlite (Wave A)
- ARCH-MINOR injection_guard inline tests (Wave D)
- ARCH-MINOR tfidf top_similar N round-trips (Wave C)
- ARCH-NIT 3× filter_map(|r| r.ok()) sites (Wave C + D)
- ARCH-NIT coaccess misleading comment (Wave D)
=== STATUS-TRUTH MARKER ===
shipped: functional
stubs: 0
cargo-check: PASS
cargo-test: PASS (42 tests, 0 failures)
behaviour-verified: yes
follow-up-required:
- tests/ingest_guard_tests.rs + tests/guard_test_corpus.rs still on #[path] hack (Wave B follow-up note, ~5 LOC)
- dead_code warning Severity::Warn unused (pre-existing, not blocking)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
0be354a920 |
KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE. |