docs: pi 0.84.3 runtime mechanics, isolation baseline, personality layering, gateway patterns
Establishes this repository as the authoritative source for Pi agent configuration across scenarios, starting with the documentation layer. Key verified findings (probe harness included, zero model tokens): - The skills section of the system prompt is emitted only when an active tool named 'read' exists (system-prompt.js:59,113). Therefore --no-tools silently makes every SKILL.md unreachable and --skill a no-op. - registerTool accepts a plain JSON Schema object, so tool definitions can be served from a backend instead of duplicated in TypeScript. - An extension can shadow a built-in tool by name, which is how a dedicated agent gets a path-restricted 'read' while still satisfying the rule above. - .pi/SYSTEM.md replaces pi's coding-assistant prompt, but the replacement branch contributes neither the tool list nor the guidelines. - Without --no-skills/--no-extensions, user-global resources leak into every scenario; probed leak was find-skills, modsearch, summarize. Measured effect of the full baseline: system prompt 2619 -> 960 characters, coding-assistant framing and pi-docs paths removed, skill finally reachable. Secrets are guarded by scripts/verify-no-secrets.sh, installed as a pre-commit hook. Backups deliberately live outside the repository.
This commit is contained in:
Executable
+107
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
# ---------------------------------------------------------------------------
|
||||
# Refuse to commit credentials.
|
||||
#
|
||||
# This repository stores Pi configuration for several agent scenarios. Some of
|
||||
# the files it mirrors (models.json, auth.json, *.env) legitimately contain
|
||||
# plaintext API keys on the live host. Templates with ${PLACEHOLDER} markers
|
||||
# belong in git; rendered files with real values never do.
|
||||
#
|
||||
# Usage:
|
||||
# scripts/verify-no-secrets.sh # scan staged changes (pre-commit)
|
||||
# scripts/verify-no-secrets.sh --all # scan every tracked file
|
||||
#
|
||||
# Install as a hook:
|
||||
# ln -sf ../../scripts/verify-no-secrets.sh .git/hooks/pre-commit
|
||||
# ---------------------------------------------------------------------------
|
||||
set -uo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT" || exit 1
|
||||
|
||||
MODE="${1:-staged}"
|
||||
|
||||
if [ "$MODE" = "--all" ]; then
|
||||
mapfile -t FILES < <(git ls-files)
|
||||
else
|
||||
mapfile -t FILES < <(git diff --cached --name-only --diff-filter=ACMR)
|
||||
fi
|
||||
|
||||
if [ "${#FILES[@]}" -eq 0 ]; then
|
||||
echo "verify-no-secrets: nothing to scan"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FAILED=0
|
||||
|
||||
fail() {
|
||||
printf '\033[31mBLOCKED\033[0m %s\n %s\n' "$1" "$2" >&2
|
||||
FAILED=1
|
||||
}
|
||||
|
||||
# --- Rule 1: filenames that must never be committed ------------------------
|
||||
FORBIDDEN_NAMES='(^|/)(models\.json|auth\.json|trust\.json|models-store\.json)$|(^|/)\.env$|\.env\.[^/]*$|(^|/)id_(ed25519|rsa)|\.(pem|p12)$|\.rendered(\..*)?$|(^|/)secrets/(?!.*\.(example|template)$)'
|
||||
for f in "${FILES[@]}"; do
|
||||
# .env.example / .env.template are allowed
|
||||
case "$f" in
|
||||
*.env.example|*.env.template|*.example|*.template) continue ;;
|
||||
esac
|
||||
if printf '%s' "$f" | grep -qP "$FORBIDDEN_NAMES"; then
|
||||
fail "$f" "filename is on the never-commit list"
|
||||
fi
|
||||
done
|
||||
|
||||
# --- Rule 2: high-confidence credential content ----------------------------
|
||||
# Only applied to text files. Placeholders are explicitly tolerated.
|
||||
PLACEHOLDER='\$\{[A-Z_][A-Z0-9_]*\}|<[A-Z_][A-Z0-9_]*>|REDACTED|CHANGE_?ME|EXAMPLE|xxx+|\.\.\.'
|
||||
|
||||
declare -a PATTERNS=(
|
||||
'sk-[A-Za-z0-9]{20,}' # OpenAI-style
|
||||
'sk-ant-[A-Za-z0-9_-]{20,}' # Anthropic
|
||||
'ghp_[A-Za-z0-9]{30,}' # GitHub PAT
|
||||
'gho_[A-Za-z0-9]{30,}'
|
||||
'github_pat_[A-Za-z0-9_]{30,}'
|
||||
'AIza[A-Za-z0-9_-]{30,}' # Google
|
||||
'xox[baprs]-[A-Za-z0-9-]{10,}' # Slack
|
||||
'[0-9]{8,10}:AA[A-Za-z0-9_-]{30,}' # Telegram bot token
|
||||
'tvly-[A-Za-z0-9]{20,}' # Tavily
|
||||
'-----BEGIN [A-Z ]*PRIVATE KEY-----'
|
||||
)
|
||||
|
||||
# key-ish assignment with a long opaque value
|
||||
ASSIGN='(?i)(api[_-]?key|apikey|secret|token|password|passwd|access[_-]?key)["'"'"' ]*[:=]["'"'"' ]*[A-Za-z0-9/_+=-]{16,}'
|
||||
|
||||
for f in "${FILES[@]}"; do
|
||||
[ -f "$f" ] || continue
|
||||
# skip binaries
|
||||
if ! grep -Iq . "$f" 2>/dev/null; then continue; fi
|
||||
|
||||
for pat in "${PATTERNS[@]}"; do
|
||||
if hit=$(grep -nP "$pat" "$f" 2>/dev/null | head -1); then
|
||||
[ -n "$hit" ] && fail "$f" "credential pattern: ${hit:0:120}"
|
||||
fi
|
||||
done
|
||||
|
||||
if hit=$(grep -nP "$ASSIGN" "$f" 2>/dev/null | grep -vP "$PLACEHOLDER" | head -1); then
|
||||
[ -n "$hit" ] && fail "$f" "credential-like assignment: ${hit:0:120}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$FAILED" -ne 0 ]; then
|
||||
cat >&2 <<'MSG'
|
||||
|
||||
verify-no-secrets: commit refused.
|
||||
|
||||
If a match is a false positive, either
|
||||
- replace the value with a ${PLACEHOLDER} and keep the file as a *.template, or
|
||||
- move the file outside the repository, or
|
||||
- add a narrow exception to scripts/verify-no-secrets.sh with a comment
|
||||
explaining why the value is not a credential.
|
||||
|
||||
Do not bypass with --no-verify.
|
||||
MSG
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "verify-no-secrets: ${#FILES[@]} file(s) scanned, clean"
|
||||
exit 0
|
||||
Reference in New Issue
Block a user