fix(audit-m): tomd cache path-salt; bridges respects rollback; rollback rm-rf guard; placeholder URLs; research skill role-tag note; stack frontend-gap doc
- M1 (RULE 0.4): replace fabricated URLs 'https://example.invalid/PROJECT-D' and 'https://…/PROJECT-D' with plain text ('user's personal CLI predecessor'). - M2: tomd-preread cache key = basename + mtime + 8-char shasum of full path, so two files with the same basename+mtime at different paths no longer collide. Portable shasum shim; falls back to 'nohash' if shasum absent. - M3: install.sh --with-bridges gated on ROLLED_BACK=0 so bridges are NOT emitted into $PWD after an ERR-trap rollback. - M4: rollback() guards rm -rf "$orig" behind an existence check. - M5: skills/research/SKILL.md front-matter note — role tags like 'web-researcher' / 'meta-critic' are ad-hoc prompt labels for the generic kei-researcher subagent, NOT separate manifests. Prevents fruitless grep in _manifests/. - M6: README adds a 'Frontend-stack coverage gap' callout listing the planned-but-not-shipped frameworks (React-Vite, Vue-Nuxt, SvelteKit, Astro, Angular, plain-web). - M7: no-hand-edit-agents.sh documents at case block that the GENERATED marker is the SOLE source of truth — legacy unmarked .md files pass silently by design; re-run the assembler to adopt them.
This commit is contained in:
parent
a23cde32a8
commit
d155afc554
6 changed files with 40 additions and 8 deletions
|
|
@ -42,6 +42,8 @@ After install, the only remaining step is merging `settings-snippet.json` into y
|
|||
|
||||
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:
|
||||
|
|
@ -145,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
|
||||
|
|
|
|||
12
install.sh
12
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
|
||||
|
|
@ -353,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"
|
||||
|
|
|
|||
|
|
@ -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