12-agent audit (waves 3+4 Opus+Sonnet) on commit 88de01c found that 2 of
my prior fixes had regressions, plus the prev batch missed 8 stale-text
sites and 2 latent bugs. This batch closes them all.
== Regressions in audit-batch (88de01c) — now fixed ==
1. PRAGMA user_version=9 placement — could silently downgrade schema on
cross-version install (existing v10 DB → re-run reset to 9 →
migrations replay → ALTER TABLE duplicate-column errors)
- install/sql/outcome-only-schema.sql: PRAGMA moved OUTSIDE the
transaction (after COMMIT) for portability across SQLite versions
- install/lib-profile-outcome-only.sh::_outcome_install_ledger:
added downgrade guard — reads existing user_version BEFORE running
ANY init path; if >9, skips entirely (preserves newer schema)
- VERIFIED: simulated v10 DB → re-run prints "skipping init to
preserve newer schema"; user_version stays at 10 (was downgraded
to 9 in the prior batch) [REAL: ran in this session]
2. backup_file mv→cp workaround left orphan backups + bypassed rollback
contract (BACKUP_PAIRS not registered)
- install/lib-profile-outcome-only.sh: now manually appends to
BACKUP_PAIRS so rollback trap restores on later failure;
removes the .bak on success path
- Comment updated to explain the workaround vs backup_file mv
3. CLAUDE.md skip-guard "STATUS-TRUTH MARKER" was too broad —
false-positive on existing kit users (RULE 0.16 doc text matches)
- lib-profile-outcome-only.sh: changed grep to literal HTML comment
marker `<!-- outcome-only profile (KeiSeiKit) -->` (specific marker
written by the installer itself)
== Tier 1 missed in prev batch — now fixed ==
4. _ts_packages/package-lock.json referenced packages/cortex-ui which
does NOT exist on disk → npm ci would fail with ELSPROBLEMS in CI
- Regenerated via fresh `rm package-lock.json && npm install`
- npm ci now exits 0 cleanly [REAL: ran in this session]
- Lockfile shrunk 2403→0 lines on the cortex-ui section (full regen)
5. v3 triggers (branch length cap ≤256) were MISSING from
outcome-only-schema.sql — sqlite3 fallback path skipped a schema
feature that the Rust kei-ledger flow enforces, creating cross-flow
drift
- Added trg_agents_branch_len_ins + trg_agents_branch_len_upd
mirroring migrations_list.rs:30-44
- Header comment in outcome-only-schema.sql rewritten to match
current behavior (was stale)
- VERIFIED: end-to-end install creates 2 triggers [REAL: sqlite3
.schema | grep trg_agents_branch_len returns 2]
6. README.md:232 said "102 crates" while README.md:9 said "105 crates"
— internal contradiction in same doc
- README:232 → "105 workspace crates"
7. ARCHITECTURE.md:165 "53 Rust crates + 13 shell primitives" stale
- Updated to "105 Rust workspace crates (47 declared in MANIFEST.toml
`full` profile) + 14 shell primitives"
8. ARCHITECTURE.md:157 "45 /commands" stale
- Updated to 68
9. plugin.json + marketplace.json description strings still had
pre-fix counts (23 primitives / 39 skills / 9 hooks / 12 agents)
- Both rewritten to match README:9 SSoT (38 agents / 68 skills /
38 hooks / 105 workspace crates / 47 installable + 14 shell)
10. PROFILE-OUTCOME-ONLY.md:28-29 "What does NOT get installed" still
cited 102/67/37/82
- Updated to 105/68/38/85
11. encyclopedia/substrate-overview.md §6/§11/§12 still said
"80-char DNA"; §13 said "495 DNA indices"; §6 said "11 install
profiles (.../Cursor/Continue/etc)"
- All 4 sites fixed to current language (≥33-char variable, 565
DNAs, 12 install profiles)
12. docs/DNA-INDEX.md:1352 said wire format is "(80 chars)"
- Updated to "(≥33 chars; role + caps slugs are variable — see
docs/DNA-FORMAT.md)"
== Tier 2 honesty fixes ==
13. Wagner et al. 2004 citation in SLEEP-LAYER.md:26 lacked [VERIFIED]
marker (W3 doc consistency caught it)
- Added [VERIFIED: doi:10.1038/nature02223] + clarification that
the original study did not isolate a specific sleep stage; SWS
attribution comes from secondary literature (Diekelmann/Born)
14. PHILOSOPHY.md:125 attributed "overnight consolidation of un-finished
intentions" to Wagner 2004 — that paper is about insight gain on
the Number Reduction Task, not Zeigarnik-effect cued memory
- Rewritten to accurately describe Wagner 2004's actual finding +
[VERIFIED: doi:10.1038/nature02223]
Verification:
- `npm ci` in _ts_packages/ exits 0 [REAL: ran in this session]
- `cargo check --workspace` exits 0 in _primitives/_rust [REAL: ran in
this session]
- Outcome-only end-to-end fresh install produces user_version=9 +
2 triggers (correct schema shape)
- Outcome-only re-run against v10 DB preserves user_version=10
(downgrade guard works)
- CLAUDE.md skip-guard now triggers ONLY on literal marker, not on
RULE 0.16 phrase
NOT addressed in this batch (deferred to a future round):
- github KeiSei84/{KeiSeiKit, KeiSeiKit-1.0} 404 (user-side action:
publish repo or update refs)
- keigit user `keisei` does not exist (user-side: create org or
rename scope)
- KEIGIT_TOKEN secret not configured (user-side action)
- Forgejo registration disabled (admin-side)
- safeEqual timing leak in TS server (LOW per W3 reassessment)
- HTTP bind 0.0.0.0 default (MEDIUM)
- Unbounded request body (MEDIUM)
- Outcome-only confirm-screen bypass (RULE 0.1 spirit)
- Ledger fallthrough false summary
- Node 20 deprecation (deadline 2026-06-02, 30 days)
- Hook count triple-discrepancy (38 README / 53 DNA-INDEX / 35 maturity-row)
- 100-row router claim still in README:117 + PROFILE-OUTCOME-ONLY.md
- INSTALL.md numerics without [REAL:] markers
- Stale .bak files accumulation policy (cosmetic)
- README per-claim [REAL: ] markers for 6 of 7 numerics
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 1207cf5) ==
- _primitives/_rust/Cargo.toml — workspace tokio gains `io-std` feature
(needed by kei-mcp/src/main.rs which calls tokio::io::{stdin,stdout})
- _primitives/_rust/kei-mcp/Cargo.toml — dev-deps tokio gains `test-util`
feature (needed by tests/tools_call_timeout.rs for tokio::time::advance
and Builder::start_paused). Both verified locally:
`cargo check -p kei-mcp` ✓
`cargo test --no-run -p kei-mcp` ✓ (3 test binaries link)
[REAL: ran 2026-05-03 in this session]
== HIGH-tier audit fixes (consensus across waves) ==
1. SQLi escape in agent-outcome-backfill.sh:110
- 4 of 12 agents flagged: TOOL_USE_ID was JSON-derived and
interpolated raw into SQL. Allowlist on $SHIPPED protected today
but a future case-statement removal opened the surface.
- Fix: tiny `_sql_esc` helper that doubles single-quotes (SQL-99
standard escape), applied to SHIPPED + TOOL_USE_ID. STUBS already
integer-validated.
2. PRAGMA user_version=9 in install/sql/outcome-only-schema.sql
- W1 outcome-only critic flagged: the SQL fallback installed a
v9-equivalent flat schema but left user_version=0. A LATER
`kei-ledger init` (e.g. when user upgrades to full kit) would
re-run migrations v1-v9 and ALTER TABLE ADD COLUMN duplicate-error
mid-migration → broken DB.
- Fix: set PRAGMA user_version=9 before COMMIT so the binary's
migration runner sees current ≥ target and short-circuits.
3. backup_file mv→cp + uninstall macOS-portable awk
- W1+W2 outcome-only flagged: lib-backup.sh uses `mv` which DELETES
the target before _jq_merge_hooks runs; `|| true` swallowed the
subsequent jq read-error → silent settings.json loss.
- Fix in lib-profile-outcome-only.sh: `cp -p` aside, drop `|| true`,
return 1 on merge failure (trap restores).
- PROFILE-OUTCOME-ONLY.md uninstall used GNU sed `,+1` extension
which BSD sed (macOS) does not support — uninstall silently
no-op'd on macOS, leaving orphan CLAUDE.md text.
- Fix: replace with portable `awk` recipe; also added `rm -f` for
the agent-toolstats.jsonl sidecar (privacy completeness).
== Doc honesty pass (RULE 0.18 numerics + RULE 0.4 citations) ==
4. README.md count drift — verified all values against filesystem:
* 102→105 Rust crates (Cargo.toml workspace `members` count)
* 67→68 skills (`ls skills/ | wc -l`)
* 35→38 hooks (`grep -c '"command":' settings-snippet.json`)
* 37→38 agent manifests (`ls _manifests/*.toml | wc -l`)
* 82→85 substrate blocks (`find _blocks/ -name '*.md' | wc -l`)
* 18 capability atoms VERIFIED via `find _capabilities/ -name '*.md'`
(encyclopedia §3 row count of 17 is in a separate file and is a
known internal display issue, not changed in this commit)
* 495→565 active DNAs (per docs/DNA-INDEX.md header 2026-05-03)
Each value now carries a `[REAL: <command>]` style trailer per
RULE 0.18.
5. README.md DNA "80-char identity" → "≥33-char variable-length"
- W1+W2 reviewer-pass flagged FALSE: docs/DNA-FORMAT.md SSoT says
minimum 33 chars; 80 was nowhere in code or spec
- Fix in README.md:36 + docs/PHILOSOPHY.md:39 + docs/DNA-INDEX.md:1352
6. README.md "Eleven install profiles (... Cursor / Continue / Zed /
Aider / Docker / Nix)" — Cursor/Continue/Zed/Aider/Docker/Nix were
never install profiles, they were bridge targets
- Fix: list 12 actual profiles from _primitives/MANIFEST.toml,
mention bridges as separate concept
7. .claude-plugin/plugin.json license MIT → Apache-2.0
- W2-Sonnet reviewer flagged: LICENSE file is Apache-2.0 (since
2026-04-30 per NOTICE), but plugin.json still declared MIT —
plugin marketplace would show wrong license
8. docs/ARCHITECTURE.md:318 placeholder URL `https://example.invalid/...`
- W2-Sonnet reviewer flagged: dead link in published docs
- Fix: remove the bad href, describe ssl-rule-file as per-user
install outside the public repo
9. skills/sleep-on-it/SKILL.md Wagner et al. 2004 citation
- W1+W2 reviewer flagged RULE 0.4 violation: citation without
verification marker
- Fix: added [VERIFIED: doi:10.1038/nature02223] + clarification
that the original paper showed slow-wave-sleep (not strictly REM)
insight gain — our metaphor is a loose mapping
10. encyclopedia/substrate-overview.md §5 fabricated TS deps
- W1-Opus doc-consistency flagged RULE 0.4.b violation: 5 of 6
package rows had INVENTED dependency strings
(`recall-ai-sdk ^1.0.0`, `nodemailer-mock ^2.0.0`,
`telegram-typings ^4.10.0`, etc — none exist in the actual
package.json files)
- Fix: regenerated table from real `package.json` reads via
`node -p "require(...).dependencies"` for each of the 6 packages
- Fix: also corrected version drift (5 packages all 0.14.0 now)
Verification:
- Outcome-only end-to-end install against fake $HOME succeeds:
hooks installed, ledger schema at user_version=9, settings.json
created cleanly, all 5 documented files present
[REAL: ran 2026-05-03 in this session]
- `cargo check -p kei-mcp` + `cargo test --no-run -p kei-mcp` clean
Audit findings NOT yet addressed (deferred to next batch):
- README:65 git clone github URL — repo is private; reviewer flagged
external strangers cannot clone; will resolve via Quick Start rewrite
- npm.pkg.github.com / @keisei84 leftover sweep — both waves verified
ZERO refs, no fix needed
- safeEqual timing leak in TS server (W2 sec MEDIUM)
- HTTP server bind 0.0.0.0 (W2 sec MEDIUM)
- Unbounded request body (W2 ci MEDIUM)
- --dry-run silent ignored on non-outcome profiles (W1+W2 MEDIUM)
- Doc-link missing for MEMORY/DNA/LEDGER format specs from README
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 a5ef896) was pushed; reverted by 083bc06 because keigit
is the right registry. Current commit lands the keigit wiring on
top of the revert.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 368df5b. Bad commits never reached remote.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>