Merge branch 'fix/audit-v030' — 3 HIGH + 7 MED + 4 LOW audit findings resolved
This commit is contained in:
commit
ae8dd3fd37
8 changed files with 61 additions and 22 deletions
19
README.md
19
README.md
|
|
@ -1,13 +1,13 @@
|
|||
# KeiSeiKit — Constructor-Pattern Agent Kit for Claude Code
|
||||
|
||||
KeiSeiKit is a drop-in agent fleet for [Claude Code](https://claude.com/claude-code). It ships a curated set of composable behavioral blocks, a Rust assembler that builds agent `.md` files from TOML manifests deterministically, three pre-wired hooks, and six portable skills including an interactive `/new-agent` wizard. Everything follows a Constructor Pattern: one file per concern, manifests as single source of truth, and the generated agent files are regenerated on every relevant edit.
|
||||
KeiSeiKit is a drop-in agent fleet for [Claude Code](https://claude.com/claude-code). It ships a curated set of composable behavioral blocks, a Rust assembler that builds agent `.md` files from TOML manifests deterministically, four pre-wired hooks, and seven portable skills including an interactive `/new-agent` wizard. Everything follows a Constructor Pattern: one file per concern, manifests as single source of truth, and the generated agent files are regenerated on every relevant edit.
|
||||
|
||||
The kit is MIT-licensed and fully generic — install it on a fresh machine and you get a sane 12-agent fleet (implementers, critics, researchers, cost-guardians, and more — all namespaced under `kei-*` so they won't collide with your own same-named agents), a wizard for spinning up new project specialists, and a build pipeline that keeps every agent derivable from its manifest.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Rust** (stable toolchain) — the assembler is a small Cargo binary
|
||||
- **jq** — used by the three shell hooks for JSON parsing (`brew install jq` / `apt install jq`)
|
||||
- **jq** — used by the four shell hooks for JSON parsing (`brew install jq` / `apt install jq`)
|
||||
- **Claude Code** — the agents, hooks, and skills target Claude Code's agent / skill / hook surface
|
||||
|
||||
## Install
|
||||
|
|
@ -25,7 +25,7 @@ cd KeiSeiKit
|
|||
3. Copies generic manifests (skips if you already have a manifest with that name)
|
||||
4. Builds the Rust assembler (`cargo build --release`)
|
||||
5. Generates agent `.md` files in-place with `AGENT_ROOT=~/.claude/agents assemble --in-place`
|
||||
6. Copies the three hooks and six skills
|
||||
6. Copies the four hooks and seven skills
|
||||
|
||||
After install, the only remaining step is merging `settings-snippet.json` into your `~/.claude/settings.json` to activate the hooks. You can do this automatically with `./install.sh --activate-hooks` or answer `y` at the end-of-install TTY prompt.
|
||||
|
||||
|
|
@ -37,11 +37,13 @@ After install, the only remaining step is merging `settings-snippet.json` into y
|
|||
|---|---:|---|
|
||||
| Behavioral blocks | 33 | `baseline`, `evidence-grading`, `rule-math-first`, `stack-rust-axum`, `deploy-modal`, `api-fal-ai`, ... |
|
||||
| Generic agents (manifests) | 12 | `kei-code-implementer`, `kei-critic`, `kei-validator`, `kei-security-auditor`, `kei-architect`, `kei-researcher`, `kei-ml-implementer`, `kei-cost-guardian`, `kei-modal-runner`, ... |
|
||||
| Hooks | 3 | `assemble-agents` (PostToolUse), `assemble-validate` (PreToolUse Bash), `no-hand-edit-agents` (PreToolUse Edit/Write) |
|
||||
| Skills | 6 | `new-agent`, `research`, `test-gen`, `pr-review`, `refactor`, `debug-deep` |
|
||||
| Hooks | 4 | `assemble-agents` (PostToolUse), `assemble-validate` (PreToolUse Bash), `no-hand-edit-agents` (PreToolUse Edit/Write), `tomd-preread` (PreToolUse Read) |
|
||||
| Skills | 7 | `new-agent`, `research`, `test-gen`, `pr-review`, `refactor`, `debug-deep`, `compose-solution` |
|
||||
|
||||
Of the 33 blocks, the **8 base blocks** (`baseline`, `evidence-grading`, `memory-protocol`, `rule-pre-dev-gate`, `rule-test-first`, `rule-error-budget`, `rule-double-audit`, `rule-math-first`) are referenced directly by the 12 shipped manifests. The remaining **25 blocks** (`stack-*`, `deploy-*`, `api-*`, `scraper-*`, `domain-*`) are a library consumed by the `/new-agent` wizard: when you compose a project specialist, the wizard picks the appropriate stack / deploy / API / scraper / domain blocks and emits a manifest that references them. The kit's generic 12 agents do not import them by default.
|
||||
|
||||
> **Frontend-stack coverage gap.** The shipped `stack-*` blocks currently cover Next.js and Flutter. Pure frontend frameworks (React-Vite, Vue-Nuxt, SvelteKit, Astro, Angular, plain-web) are planned as a follow-up; contributions are welcome via PR. Blocks stay in a single `_blocks/` directory — no opt-in split planned.
|
||||
|
||||
## Creating a new agent
|
||||
|
||||
Run the wizard in Claude Code:
|
||||
|
|
@ -50,7 +52,7 @@ Run the wizard in Claude Code:
|
|||
/new-agent
|
||||
```
|
||||
|
||||
You'll be asked (via option-pickers, not free-text):
|
||||
You'll be asked (via multiple option-picker batches, not free-text) — each batch groups several click-only questions into a single `AskUserQuestion` call:
|
||||
|
||||
1. Project stack (Rust CLI / axum / SwiftUI / Flutter / FastAPI / Next.js / Go / Embedded / Python ML)
|
||||
2. Deploy target (local-only / EC2 / Cloudflare / Modal / Docker / none)
|
||||
|
|
@ -74,11 +76,12 @@ Then one free-text prompt for slug + description + path + gotchas. The wizard co
|
|||
Block edit (_blocks/<block>.md) <-- triggers rebuild of ALL agents
|
||||
```
|
||||
|
||||
Three hooks enforce the pipeline:
|
||||
Four hooks enforce the pipeline:
|
||||
|
||||
- **`assemble-agents`** (PostToolUse, Write/Edit) — rebuilds the affected agent(s) whenever a manifest or a block changes. No manual rebuild needed.
|
||||
- **`assemble-validate`** (PreToolUse, Bash) — blocks `git commit` inside `~/.claude` if any manifest fails validation. Keeps the repo in a buildable state at all times.
|
||||
- **`no-hand-edit-agents`** (PreToolUse, Edit/Write) — refuses edits to any `.md` under `~/.claude/agents/` that starts with the `<!-- GENERATED -->` marker, pointing you at the manifest instead. Override with `AGENT_MIGRATION=1` for emergencies only.
|
||||
- **`tomd-preread`** (PreToolUse, Read) — auto-converts opaque binary formats (`.docx`, `.doc`, `.xlsx`, `.pptx`, `.csv`) to markdown via the `tomd` primitive and redirects Claude to read the cached `.md` instead. Cache under `$KEISEI_TOMD_CACHE` (default `/tmp/keisei-tomd-cache`). Degrades silently if `jq` or the primitive is absent.
|
||||
|
||||
## Adding custom blocks
|
||||
|
||||
|
|
@ -144,7 +147,7 @@ All paths are idempotent: existing bridge files in the project are skipped, neve
|
|||
|
||||
`_primitives/` holds first-class building blocks that agents and pipelines depend on — executable utilities, not behavioral markdown. Currently one primitive ships with the kit:
|
||||
|
||||
- `tomd` — universal non-native-format → markdown converter (PDF, DOCX, XLSX, PPTX, CSV, code, images with OCR). Ported from [KeiAgent](https://example.invalid/KeiAgent) with KeiSeiKit-style error tags and a configurable cache directory (`KEISEI_TOMD_CACHE`, default `/tmp/keisei-tomd-cache`).
|
||||
- `tomd` — universal non-native-format → markdown converter (PDF, DOCX, XLSX, PPTX, CSV, code, images with OCR). Ported from the KeiAgent project (user's personal CLI predecessor) with KeiSeiKit-style error tags and a configurable cache directory (`KEISEI_TOMD_CACHE`, default `/tmp/keisei-tomd-cache`).
|
||||
|
||||
The matching hook `hooks/tomd-preread.sh` is a `PreToolUse(Read)` entry that auto-redirects Claude to a cached markdown conversion when a Read targets an opaque binary format — no agent has to know about `tomd` explicitly, but any agent that *does* need to shell out can invoke `~/.claude/agents/_primitives/tomd.sh report.pdf > report.md` directly.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ programs installed at `$HOME/.claude/agents/_primitives/` by `install.sh`.
|
|||
|---|---|---|
|
||||
| `tomd.sh` | Universal non-native-format → markdown converter (PDF, DOCX, XLSX, PPTX, CSV, images, code). | `~/.claude/agents/_primitives/tomd.sh <file>` |
|
||||
|
||||
`tomd.sh` is ported from [KeiAgent](https://…/KeiAgent) `bin/keiagent-tomd` —
|
||||
same format matrix, KeiSeiKit-style error tags (`[tomd]`), configurable
|
||||
cache directory (`KEISEI_TOMD_CACHE`).
|
||||
`tomd.sh` is ported from the KeiAgent project (user's personal CLI
|
||||
predecessor) `bin/keiagent-tomd` — same format matrix, KeiSeiKit-style
|
||||
error tags (`[tomd]`), configurable cache directory (`KEISEI_TOMD_CACHE`).
|
||||
|
||||
## Hook integration
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,21 @@ FILE=$(jq -r '.tool_input.file_path // empty')
|
|||
|
||||
# Only care about files directly under ~/.claude/agents/*.md
|
||||
# (not blocks/, manifests/, assembler/, template, generated preview)
|
||||
#
|
||||
# NOTE on staleness: we use the `<!-- GENERATED by _assembler -->` marker
|
||||
# on line 1 as the SOLE SOURCE OF TRUTH for "is this file generated?".
|
||||
# Legacy agent .md files that were produced before the assembler existed
|
||||
# (and therefore lack the marker) will pass this hook silently. That is
|
||||
# intentional — the marker is how the assembler self-declares ownership,
|
||||
# and any file without it is assumed hand-authored. Re-run the assembler
|
||||
# to adopt an older file into the managed set.
|
||||
case "$FILE" in
|
||||
"$HOME/.claude/agents/_"*) exit 0 ;;
|
||||
"$HOME/.claude/agents/"*.md) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
# Detect generated marker in the first 10 lines
|
||||
# Detect generated marker in the first 10 lines (sole truth — see NOTE above)
|
||||
if [ -f "$FILE" ] && head -10 "$FILE" | grep -q 'GENERATED by _assembler'; then
|
||||
NAME=$(basename "$FILE" .md)
|
||||
echo "[no-hand-edit-agents] BLOCKED: $FILE is generated." >&2
|
||||
|
|
|
|||
|
|
@ -32,10 +32,15 @@ esac
|
|||
|
||||
mkdir -p "$CACHE_DIR"
|
||||
|
||||
# Cache key: basename + mtime. Portable stat for macOS + Linux.
|
||||
# Cache key: basename + mtime + short path-hash. Path-hash disambiguates
|
||||
# two files with the same basename+mtime at different paths (otherwise they
|
||||
# would collide and Claude would silently read the wrong conversion).
|
||||
# Portable stat for macOS + Linux; portable shasum shim.
|
||||
BASENAME=$(basename "$FILE")
|
||||
MTIME=$(stat -f %m "$FILE" 2>/dev/null || stat -c %Y "$FILE" 2>/dev/null || echo 0)
|
||||
MD_FILE="$CACHE_DIR/${BASENAME%.*}-${MTIME}.md"
|
||||
PATH_HASH=$(printf '%s' "$FILE" | shasum 2>/dev/null | cut -c1-8)
|
||||
[ -n "$PATH_HASH" ] || PATH_HASH="nohash"
|
||||
MD_FILE="$CACHE_DIR/${BASENAME%.*}-${MTIME}-${PATH_HASH}.md"
|
||||
|
||||
if [ ! -s "$MD_FILE" ]; then
|
||||
"$TOMD" "$FILE" > "$MD_FILE" 2>/dev/null || true
|
||||
|
|
|
|||
22
install.sh
22
install.sh
|
|
@ -80,7 +80,11 @@ rollback() {
|
|||
orig="${pair%%|*}"
|
||||
bak="${pair#*|}"
|
||||
if [ -e "$bak" ]; then
|
||||
rm -rf "$orig"
|
||||
# Guard rm -rf: only remove $orig if it actually exists as a file or
|
||||
# directory. Harmless either way, but explicit is safer than brittle.
|
||||
if [ -d "$orig" ] || [ -f "$orig" ]; then
|
||||
rm -rf "$orig"
|
||||
fi
|
||||
mv "$bak" "$orig"
|
||||
say " restored $orig from $bak"
|
||||
fi
|
||||
|
|
@ -142,6 +146,10 @@ activate_hooks() {
|
|||
say "created $target from snippet (no prior settings.json)"
|
||||
return 0
|
||||
fi
|
||||
# Merge path: back up the pre-merge settings.json so rollback can restore
|
||||
# it if a later step ERR-traps. The "create new" path above exits before
|
||||
# reaching here, so backup_file is only invoked when $target exists.
|
||||
backup_file "$target"
|
||||
# Merge: walk each matcher-group in PostToolUse / PreToolUse, append hooks,
|
||||
# unique_by command. jq filter is written for readability, not golf.
|
||||
tmp="$(mktemp "$target.XXXXXX")"
|
||||
|
|
@ -349,6 +357,12 @@ elif [ -t 0 ] && [ -t 1 ]; then
|
|||
fi
|
||||
|
||||
# --- optional: render cross-tool bridges into $PWD -------------------------
|
||||
# If a prior step ERR-trapped into rollback(), we MUST NOT keep writing into
|
||||
# $PWD — the install is now aborted, and bridges should not land as
|
||||
# collateral on a failed run. rollback() sets ROLLED_BACK=1 before returning.
|
||||
if [ "${ROLLED_BACK:-0}" = "1" ]; then
|
||||
exit 2
|
||||
fi
|
||||
if [[ "$WITH_BRIDGES" == "1" ]]; then
|
||||
if [[ -f "./install.sh" && -d "./_bridges" ]]; then
|
||||
warn "not generating bridges — you are in the KeiSeiKit repo, not a project directory"
|
||||
|
|
@ -369,7 +383,7 @@ if [ "$DID_ACTIVATE" = "1" ]; then
|
|||
==========================================================================
|
||||
|
||||
To verify install:
|
||||
ls $AGENTS_DIR/*.md # should show ~14 generated agents
|
||||
ls $AGENTS_DIR/*.md # should show 12 generated agents
|
||||
$AGENTS_DIR/_assembler/target/release/assemble --validate
|
||||
|
||||
To create a new project-specialist agent:
|
||||
|
|
@ -383,7 +397,7 @@ else
|
|||
NEXT STEP: merge settings-snippet.json into ~/.claude/settings.json
|
||||
==========================================================================
|
||||
|
||||
KeiSeiKit ships 3 hooks (assemble-agents, assemble-validate, no-hand-edit).
|
||||
KeiSeiKit ships 4 hooks (assemble-agents, assemble-validate, no-hand-edit, tomd-preread).
|
||||
To activate them, merge entries from:
|
||||
$KIT_DIR/settings-snippet.json
|
||||
into your:
|
||||
|
|
@ -393,7 +407,7 @@ else
|
|||
./install.sh --activate-hooks
|
||||
|
||||
To verify install:
|
||||
ls $AGENTS_DIR/*.md # should show ~14 generated agents
|
||||
ls $AGENTS_DIR/*.md # should show 12 generated agents
|
||||
$AGENTS_DIR/_assembler/target/release/assemble --validate
|
||||
|
||||
To create a new project-specialist agent:
|
||||
|
|
|
|||
|
|
@ -116,6 +116,6 @@ Future invocations benefit from the K new blocks — kit is now smarter by K blo
|
|||
architectural decomposition if `research` is overkill
|
||||
- `_blocks/baseline.md`, `_blocks/rule-math-first.md` — block templates
|
||||
(Phase 6a shape references)
|
||||
- `_manifests/kei-*.toml` — 14 kit agents (Phase 7b handoff references)
|
||||
- `_manifests/kei-*.toml` — 12 kit agents (Phase 7b handoff references)
|
||||
- `_bridges/*.tmpl` — 11 tool bridges (architecture Phase 5 may reference
|
||||
them for agent-creation flows)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ independently researched and composed.
|
|||
For heavy / deep-domain / unfamiliar-domain tasks, delegate to the
|
||||
`research` skill (`skills/research/SKILL.md`, Variant C "Deep decomposition"
|
||||
is the pattern — Wave 0 decomposition, then Wave 1 per-component
|
||||
exploration). Invoke via the Agent tool with `subagent_type: kei-researcher`
|
||||
(or `researcher` if that agent is present in the user's global fleet). Pass
|
||||
`DESC` as the research question with the constraint:
|
||||
exploration). Invoke via the Agent tool with `subagent_type: kei-researcher`.
|
||||
Always prefer `kei-researcher` when it exists in the kit; bare `researcher`
|
||||
matches only the user's personal fleet and may have divergent handoffs — do
|
||||
not fall back to it silently. Pass `DESC` as the research question with the
|
||||
constraint:
|
||||
|
||||
> Decompose into 2-5 orthogonal components, each with a 1-line description
|
||||
> and 3-5 distinctive keywords suitable for grep prior-art search.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@ description: Deep research on any topic using parallel agents, web search, and c
|
|||
argument-hint: <topic or question>
|
||||
---
|
||||
|
||||
> **Role-tag convention.** Names like `web-researcher`, `meta-critic`,
|
||||
> `arch-analyst`, `{component}-critic` that appear later in this skill are
|
||||
> ad-hoc role tags passed to the generic `kei-researcher` subagent inside
|
||||
> its prompt — they are NOT separate manifests in the kit. Do not grep for
|
||||
> them in `_manifests/`; they will not be found. The only manifest behind
|
||||
> every research teammate is `kei-researcher`.
|
||||
|
||||
# Deep Research Skill
|
||||
|
||||
You are conducting deep research on: $ARGUMENTS
|
||||
|
|
|
|||
Loading…
Reference in a new issue