Compare commits

..

No commits in common. "0f1b3d4506853a827465f4ca097bfdd9ef43a7bd" and "59f2f00314551fe51264cc6e7fe389772287c660" have entirely different histories.

16 changed files with 91 additions and 157 deletions

View file

@ -3,10 +3,10 @@
# Orchestrates the setup and management of the knowledge base.
# =============================================================================
include globals.env
export $(shell grep -v '^[#[:space:]]' globals.env | sed 's/=.*//')
include config.env
export $(shell sed 's/=.*//' config.env)
.PHONY: setup add-genome status lint lock doctor sync help
.PHONY: setup add-genome status lint lock help
help:
@echo "Available commands:"
@ -15,8 +15,6 @@ help:
@echo " make status - Check submodule and encryption status"
@echo " make lint - Verify schema, privacy flags, and metadata"
@echo " make lock - Lock all encrypted files across all genomes"
@echo " make doctor - Verify all required tools are installed"
@echo " make sync - Sync submodules and report unpushed commits"
lint:
@bash scripts/lint-genomes.sh
@ -38,21 +36,6 @@ status:
@echo "--- Encryption Status (First 10 files) ---"
@git-crypt status | head -n 10
doctor:
@echo "Checking required tools..."
@command -v git >/dev/null 2>&1 || { echo " MISSING: git"; exit 1; }
@command -v git-crypt >/dev/null 2>&1 || { echo " MISSING: git-crypt"; exit 1; }
@command -v curl >/dev/null 2>&1 || { echo " MISSING: curl"; exit 1; }
@command -v jq >/dev/null 2>&1 || { echo " MISSING: jq"; exit 1; }
@command -v bw >/dev/null 2>&1 || echo " OPTIONAL: bw (Bitwarden CLI) not found — key injection will be manual."
@echo "System ready."
sync:
@echo "Syncing submodules..."
@git submodule update --init --recursive
@echo "--- Unpushed commits per genome ---"
@git submodule foreach 'git log --oneline @{u}.. 2>/dev/null | head -5 || true'
lock:
@echo "Locking master repository..."
@git-crypt lock 2>/dev/null || true

39
config.env Normal file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env bash
# =============================================================================
# config.env
# Single Source of Truth for the Knowledge Genome Framework.
# =============================================================================
# --- PROVIDER SELECTION ---
PROVIDER="forgejo" # Options: "forgejo", "github"
# --- FORGEJO CONFIGURATION ---
FORGEJO_URL="https://git.keruhomelab.com"
FORGEJO_USER="keru"
# Note: FORGEJO_TOKEN must be exported in your shell for security.
# --- VAULTWARDEN CONFIGURATION ---
# Used for rendering template instructions
VAULTWARDEN_URL="https://vault.keruhomelab.com"
# --- MASTER REPOSITORY ---
MASTER_REPO="master-knowledge-genome"
GIST_URL="https://gist.github.com/442a6bf555914893e9891c11519de94f.git"
# --- GENOME REGISTRY ---
# Format: "name|description"
GENOMES=(
"genome-dev|Web development, TUI, Angular, software architecture"
"genome-finance|Personal finance, investments, market analysis"
"genome-homelab|Keru infrastructure, network configs, architecture logs"
)
# --- SYSTEM PATHS ---
WORK_DIR="${HOME}/knowledge-genome-setup"
KEYS_DIR="${WORK_DIR}/keys"
# Core directory resolution (DO NOT CHANGE)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEMPLATES_DIR="${SCRIPT_DIR}/templates"
LIB_DIR="${SCRIPT_DIR}/lib"
PROVIDERS_DIR="${SCRIPT_DIR}/providers"

View file

@ -1,25 +0,0 @@
# =============================================================================
# globals.env
# Static configuration — pure KEY=VALUE.
# Safe to: make include, docker-compose, env parsers, shell source.
# =============================================================================
# --- PROVIDER SELECTION ---
PROVIDER=forgejo
# --- FORGEJO ---
FORGEJO_URL=https://git.keruhomelab.com
FORGEJO_USER=keru
FORGEJO_SSH_PORT=222
# --- GITHUB (used when PROVIDER=github) ---
# GITHUB_USER=your-username
# GITHUB_ORG=your-org # Optional: set only for org repos; overrides GITHUB_USER
# Note: GITHUB_TOKEN must be exported in your shell for security.
# --- VAULTWARDEN ---
VAULTWARDEN_URL=https://vault.keruhomelab.com
# --- MASTER REPOSITORY ---
MASTER_REPO=master-knowledge-genome
GIST_URL=https://gist.github.com/442a6bf555914893e9891c11519de94f.git

View file

@ -16,10 +16,10 @@ check_deps() {
if [[ ${#missing[@]} -gt 0 ]]; then
error "Missing required tools: ${missing[*]}"
printf "\nInstall them using your package manager:\n"
printf " Debian/Ubuntu: sudo apt install %s\n" "${missing[*]}"
printf " MacOS: brew install %s\n" "${missing[*]}"
return 1
echo -e "\nInstall them using your package manager:"
echo " Debian/Ubuntu: sudo apt install ${missing[*]}"
echo " MacOS: brew install ${missing[*]}"
exit 1
fi
success "Environment check passed: all required tools found."

View file

@ -16,7 +16,7 @@ gcrypt_export_key() {
mkdir -p "${KEYS_DIR}"
git-crypt export-key "$key_path"
success "Symmetric key exported to: $key_path"
warn "SECURITY ALERT: Move this key to Vaultwarden and delete it from disk immediately."
warn "Action required: store this key in Vaultwarden and delete it from disk."
}
gcrypt_verify() {
@ -83,7 +83,7 @@ gcrypt_rotate_key() {
else
error "Old key not found at: ${old_key_path}"
error "Unlock manually before rotating: git-crypt unlock /path/to/${genome_name}.key"
return 1
exit 1
fi
else
info "Repository is already unlocked — proceeding."
@ -92,7 +92,7 @@ gcrypt_rotate_key() {
# 2. Ensure working tree is clean (private files excluded — they will be re-staged)
if ! git diff --quiet -- ':!raw/private' ':!wiki/private' 2>/dev/null; then
error "Working tree has uncommitted changes outside private/. Commit or stash them first."
return 1
exit 1
fi
# 3. Remove old key material only (preserves .git/git-crypt/ structure)
@ -154,7 +154,7 @@ gcrypt_print_key_instructions() {
local genome_name="$1"
local v_url="${VAULTWARDEN_URL:-https://your-vaultwarden.com}"
printf "\n ── %b ──\n\n" "${BOLD}Key Management: ${genome_name}${NC}"
echo -e "\n ── ${BOLD}Key Management: ${genome_name}${NC} ──\n"
echo " 1. Encode the key to base64:"
echo " base64 < ${KEYS_DIR}/${genome_name}.key"
echo ""

View file

@ -6,9 +6,6 @@
# Valid values for the 'type' frontmatter field.
# Must stay in sync with the type list in templates/agents-genome.md.
# Note: 'index' and 'log' are wiki-level singleton files (wiki/index.md, wiki/log.md).
# 'conflict' has no dedicated scaffold directory — it is a cross-cutting type
# that can live under any wiki/ subdirectory.
VALID_TYPES=("source" "entity" "concept" "query" "conflict" "private" "index" "log")
# ---------------------------------------------------------------------------
@ -124,7 +121,7 @@ check_knowledge_decay() {
# Parse date — handle both GNU date (Linux) and BSD date (macOS)
local updated_ts
if date --version >/dev/null 2>&1; then
if date --version &>/dev/null 2>&1; then
# GNU date
updated_ts=$(date -d "$last_updated" +%s 2>/dev/null)
else
@ -152,30 +149,6 @@ check_knowledge_decay() {
return 0
}
# ---------------------------------------------------------------------------
# check_page_size <file>
# Enforces the page length limits defined in agents-genome.md:
# soft cap: 400 lines → warn
# hard cap: 800 lines → error
# These limits ensure pages fit within the LLM context window without
# attention degradation and keep the wiki atomically navigable.
# ---------------------------------------------------------------------------
check_page_size() {
local file="$1"
local lines
lines=$(wc -l < "$file")
if [[ $lines -gt 800 ]]; then
error "Page too long (${lines} lines, hard cap 800): $file"
error " Split this page into focused sub-pages and link them."
return 1
elif [[ $lines -gt 400 ]]; then
warn "Page approaching limit (${lines} lines, soft cap 400): $file"
fi
return 0
}
# ---------------------------------------------------------------------------
# check_broken_links <file>
# Basic check for internal [[wikilinks]] that cannot be resolved locally.
@ -188,7 +161,7 @@ check_broken_links() {
# Extract link targets, stripping aliases: [[Link|Alias]] -> Link
local links
links=$(grep -oE '\[\[[^\]]+' "$file" 2>/dev/null | sed 's/^\[\[//' | cut -d'|' -f1)
links=$(grep -oP '\[\[\K[^\]]+' "$file" 2>/dev/null | cut -d'|' -f1)
for link in $links; do
local target="$link"

View file

@ -15,12 +15,11 @@ else
GREEN='' YELLOW='' CYAN='' RED='' BOLD='' NC=''
fi
info() { printf "%b\n" "${CYAN}[INFO]${NC} $*"; }
success() { printf "%b\n" "${GREEN}[OK]${NC} $*"; }
warn() { printf "%b\n" "${YELLOW}[WARN]${NC} $*"; }
error() { printf "%b\n" "${RED}[ERROR]${NC} $*" >&2; }
die() { error "$*"; exit 1; }
step() { printf "\n%b\n" "${BOLD}${YELLOW}━━━ $* ━━━${NC}"; }
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
step() { echo -e "\n${BOLD}${YELLOW}━━━ $* ━━━${NC}"; }
box() {
local max_len=0
@ -29,9 +28,9 @@ box() {
done
local border
border=$(printf '─%.0s' $(seq 1 $((max_len + 2))))
printf "%b\n" "${CYAN}${border}${NC}"
echo -e "${CYAN}${border}${NC}"
for line in "$@"; do
printf "${CYAN}${NC} %-${max_len}s ${CYAN}${NC}\n" "$line"
done
printf "%b\n" "${CYAN}${border}${NC}"
echo -e "${CYAN}${border}${NC}"
}

View file

@ -8,17 +8,14 @@ render_template() {
local template_file="$1"
local output_file="$2"
[[ ! -f "$template_file" ]] && { error "Template not found: ${template_file}"; return 1; }
[[ ! -f "$template_file" ]] && { error "Template not found: ${template_file}"; exit 1; }
local content
content=$(<"$template_file")
local genome_name_upper
genome_name_upper=$(tr '[:lower:]' '[:upper:]' <<< "${GENOME_NAME}")
content=$(cat "$template_file")
# Placeholder replacement
content="${content//\{\{GENOME_NAME\}\}/${GENOME_NAME}}"
content="${content//\{\{GENOME_NAME_UPPER\}\}/${genome_name_upper}}"
content="${content//\{\{GENOME_NAME_UPPER\}\}/${GENOME_NAME^^}}"
content="${content//\{\{GENOME_DESC\}\}/${GENOME_DESC}}"
content="${content//\{\{FORGEJO_URL\}\}/${FORGEJO_URL}}"
content="${content//\{\{FORGEJO_USER\}\}/${FORGEJO_USER}}"

View file

@ -31,8 +31,8 @@ provider_create_repo() {
case "$http_code" in
201) success "Repository '${name}' created successfully." ;;
409) info "Repository '${name}' already exists - skipping." ;;
401) error "Unauthorized. Check your FORGEJO_TOKEN."; return 1 ;;
*) error "Forgejo API returned HTTP ${http_code}. Check connectivity."; return 1 ;;
401) error "Unauthorized. Check your FORGEJO_TOKEN."; exit 1 ;;
*) error "Forgejo API returned HTTP ${http_code}. Check connectivity."; exit 1 ;;
esac
}
@ -44,7 +44,8 @@ provider_ssh_url() {
local host
# Extract hostname by removing protocol and trailing slashes
host=$(echo "${FORGEJO_URL}" | sed -e 's|^[^/]*//||' -e 's|/*$||')
echo "ssh://git@${host}:${FORGEJO_SSH_PORT:-222}/${FORGEJO_USER}/${1}.git"
# Using port 222 as default for many homelab Forgejo/Gitea setups
echo "ssh://git@${host}:222/${FORGEJO_USER}/${1}.git"
}
provider_web_url() {

View file

@ -37,7 +37,7 @@ provider_create_repo() {
case "$http_code" in
201) success "Repository '${name}' created on GitHub." ;;
422) info "Repository '${name}' already exists - skipping." ;;
*) error "GitHub API returned HTTP ${http_code}. Check token/permissions."; return 1 ;;
*) error "GitHub API returned HTTP ${http_code}. check token/permissions."; exit 1 ;;
esac
}

View file

@ -1,27 +0,0 @@
#!/usr/bin/env bash
# =============================================================================
# registry.sh - Knowledge Genome Registry
# Dynamic paths and genome definitions.
# =============================================================================
# Guard against double sourcing
[[ -n "${_REGISTRY_LOADED:-}" ]] && return
_REGISTRY_LOADED=1
# Resolve project root relative to this file
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Dynamic paths
WORK_DIR="${HOME}/knowledge-genome-setup"
KEYS_DIR="${WORK_DIR}/keys"
TEMPLATES_DIR="${PROJECT_ROOT}/templates"
LIB_DIR="${PROJECT_ROOT}/lib"
PROVIDERS_DIR="${PROJECT_ROOT}/providers"
# --- GENOME REGISTRY ---
# Format: "name|description"
GENOMES=(
"genome-dev|Web development, TUI, Angular, software architecture"
"genome-finance|Personal finance, investments, market analysis"
"genome-homelab|Keru infrastructure, network configs, architecture logs"
)

View file

@ -6,8 +6,7 @@
set -euo pipefail
source "lib/output.sh"
source "globals.env"
source "registry.sh"
source "config.env"
GENOME_NAME="${1:-}"
GENOME_DESC="${2:-}"
@ -20,8 +19,10 @@ fi
step "Adding New Genome: ${GENOME_NAME}"
# Sovrascrivo l'array per la sessione corrente
GENOMES=("${GENOME_NAME}|${GENOME_DESC}")
# FIX BUG 2: Uso source invece di bash per mantenere il context dell'array
source "scripts/setup-genomes.sh"
success "Genome '${GENOME_NAME}' added and linked successfully!"

View file

@ -2,14 +2,13 @@
# =============================================================================
# scripts/lint-genomes.sh
# Executes quality control across all registered genomes.
# Iterates from the GENOMES registry in registry.sh — not from filesystem patterns —
# Iterates from the GENOMES registry in config.env — not from filesystem patterns —
# so all genomes are covered regardless of their naming convention.
# =============================================================================
set -euo pipefail
source "lib/output.sh"
source "globals.env"
source "registry.sh"
source "config.env"
source "lib/lint.sh"
step "Starting Knowledge Genome Linting"
@ -31,15 +30,18 @@ for entry in "${GENOMES[@]}"; do
# Lint all .md files except AGENTS.md and core-karpathy reference
while IFS= read -r md_file; do
lint_markdown_file "$md_file" "$GENOME_NAME" && fe=0 || fe=$?
check_privacy_consistency "$md_file" && pce=0 || pce=$?
check_page_size "$md_file" && pse=0 || pse=$?
TOTAL_ERRORS=$((TOTAL_ERRORS + fe + pce + pse))
lint_markdown_file "$md_file" "$GENOME_NAME"
file_errors=$?
TOTAL_ERRORS=$((TOTAL_ERRORS + file_errors))
check_knowledge_decay "$md_file" && stale=0 || stale=$?
check_privacy_consistency "$md_file"
TOTAL_ERRORS=$((TOTAL_ERRORS + $?))
check_knowledge_decay "$md_file"
stale=$?
TOTAL_STALE=$((TOTAL_STALE + stale))
check_broken_links "$md_file" || true # warnings only, never contributes to errors
check_broken_links "$md_file"
done < <(find "$genome_dir" -name "*.md" \
! -name "AGENTS.md" \

View file

@ -6,12 +6,7 @@
set -euo pipefail
source "lib/output.sh"
source "globals.env"
if [[ -z "${WORK_DIR:-}" ]]; then
source "registry.sh"
fi
source "config.env"
source "lib/scaffold.sh"
source "lib/git-crypt.sh"
source "providers/${PROVIDER}.sh"
@ -30,10 +25,11 @@ for entry in "${GENOMES[@]}"; do
GENOME_PATH="${WORK_DIR}/${MASTER_REPO}/${GENOME_NAME}"
if [[ ! -d "${GENOME_PATH}" ]]; then
if [ ! -d "${GENOME_PATH}" ]; then
cd "${WORK_DIR}/${MASTER_REPO}"
info "Linking ${GENOME_NAME} as a submodule..."
# FIX BUG 1: Adding the submodule clones the empty remote repository
git submodule add "${SSH_URL}" "${GENOME_NAME}"
cd "${GENOME_NAME}"
@ -49,14 +45,12 @@ for entry in "${GENOMES[@]}"; do
git commit -m "feat: initial scaffold and git-crypt init for ${GENOME_NAME}"
git push -u origin main
# Key export and instructions
# Key export and instructions (Fix Obs B)
gcrypt_export_key "${GENOME_NAME}"
gcrypt_print_key_instructions "${GENOME_NAME}"
# Commit the submodule reference in the master repo
# Return to master to consolidate the submodule addition
cd "${WORK_DIR}/${MASTER_REPO}"
git commit -m "feat: add ${GENOME_NAME} as submodule"
git push origin main
fi
done

View file

@ -6,8 +6,7 @@
set -euo pipefail
source "lib/output.sh"
source "globals.env"
source "registry.sh"
source "config.env"
source "lib/scaffold.sh"
source "providers/${PROVIDER}.sh" # Required for remote creation
@ -19,7 +18,7 @@ provider_create_repo "${MASTER_REPO}" "Knowledge Genome Master Repository" "true
mkdir -p "${WORK_DIR}/${MASTER_REPO}"
cd "${WORK_DIR}/${MASTER_REPO}"
if [[ ! -d ".git" ]]; then
if [ ! -d ".git" ]; then
info "Initializing Git in Master repository..."
git init
@ -27,7 +26,7 @@ if [[ ! -d ".git" ]]; then
SSH_URL=$(provider_ssh_url "${MASTER_REPO}")
git remote add origin "${SSH_URL}"
if [[ -n "${GIST_URL:-}" ]]; then
if [ -n "${GIST_URL:-}" ]; then
info "Adding core-karpathy as an external reference..."
git submodule add "${GIST_URL}" core-karpathy || warn "Could not add core-karpathy submodule."
fi

View file

@ -9,10 +9,8 @@ set -euo pipefail
# Resolve script directory and source core components
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${SCRIPT_DIR}" # All child scripts use relative paths from project root
source "${SCRIPT_DIR}/lib/output.sh"
source "${SCRIPT_DIR}/globals.env"
source "${SCRIPT_DIR}/registry.sh"
source "${SCRIPT_DIR}/config.env"
source "${SCRIPT_DIR}/lib/deps.sh"
step "Starting Knowledge Genome Setup"
@ -26,7 +24,7 @@ check_git_identity
info "Initializing Master Repository..."
bash "${SCRIPT_DIR}/scripts/setup-master.sh"
# 3. Genomes Provisioning (as defined in registry.sh)
# 3. Genomes Provisioning (as defined in config.env)
info "Provisioning registered Genomes..."
bash "${SCRIPT_DIR}/scripts/setup-genomes.sh"