Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"url": "https://github.com/ShaheerKhawaja"
},
"metadata": {
"description": "ProductionOS — AI engineering OS for Claude Code and Codex. 80 agents, 41 commands, 17 hooks.",
"description": "ProductionOS — AI engineering OS for Claude Code and Codex. 80 agents, 41 commands, 18 hooks.",
"version": "1.2.0-beta.1",
"homepage": "https://github.com/ShaheerKhawaja/ProductionOS",
"repository": "https://github.com/ShaheerKhawaja/ProductionOS",
Expand All @@ -15,7 +15,7 @@
{
"name": "productionos",
"source": "./",
"description": "Dual-target AI engineering OS — 80 agents, 41 commands, 17 hooks, one shared workflow registry.",
"description": "Dual-target AI engineering OS — 80 agents, 41 commands, 18 hooks, one shared workflow registry.",
"version": "1.2.0-beta.1",
"author": {
"name": "Shaheer Khawaja",
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "productionos",
"description": "AI engineering OS for Claude Code and Codex — 80 agents, 41 commands, 17 hooks.",
"description": "AI engineering OS for Claude Code and Codex — 80 agents, 41 commands, 18 hooks.",
"version": "1.2.0-beta.1",
"author": {
"name": "Shaheer Khawaja",
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/productionos/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ metadata:

# ProductionOS

ProductionOS is a dual-target AI engineering operating system with 80 agents, 41 commands, and 17 hooks.
ProductionOS is a dual-target AI engineering operating system with 80 agents, 41 commands, and 18 hooks.

Use this skill to translate the Claude-oriented workflow specs in this repo into Codex-native execution.

Expand Down
2 changes: 1 addition & 1 deletion SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ argument-hint: "[goal, command name, or repo path]"

# ProductionOS

ProductionOS is a dual-target AI engineering operating system with 80 agents, 41 commands, and 17 hooks.
ProductionOS is a dual-target AI engineering operating system with 80 agents, 41 commands, and 18 hooks.

Use this skill to translate the Claude-oriented workflow specs in this repo into Codex-native execution.

Expand Down
2 changes: 1 addition & 1 deletion docs/CODEX-PARITY-HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This document is generated from the runtime-neutral registry in [scripts/lib/runtime-targets.ts](../scripts/lib/runtime-targets.ts).

Current snapshot: 80 agents, 41 commands, 17 hooks, 14 templates, 28 tests.
Current snapshot: 80 agents, 41 commands, 18 hooks, 14 templates, 28 tests.

## Runtime Targets

Expand Down
87 changes: 87 additions & 0 deletions hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# ProductionOS Hooks

15 lifecycle hooks across 4 events. Auto-enforced via `hooks/hooks.json`. All hooks degrade gracefully if dependencies are missing.

## Hook Inventory

### SessionStart (1 hook)

| Hook | What | Dependencies |
|------|------|-------------|
| `session-start.sh` | Init state, display banner, load instincts, context recovery | python3, bun |

### PreToolUse (5 hooks)

| Hook | Matcher | What | Dependencies |
|------|---------|------|-------------|
| `scope-enforcement.sh` | Edit/Write/Bash | Block out-of-scope file edits | python3, jq |
| `repo-boundary-guard.sh` | Edit/Write/Bash | Block cross-repo operations | python3, jq |
| `protected-file-guard.sh` | Edit/Write/Bash | Block writes to .env, keys, certs | python3, jq |
| `pre-edit-security.sh` | Edit/Write/Bash | Advisory on auth/payment file edits | python3, jq |
| `pre-commit-gitleaks.sh` | Bash | Secret detection in git commits | python3, jq, gitleaks (optional) |

### PostToolUse (4 hooks)

| Hook | Matcher | What | Dependencies |
|------|---------|------|-------------|
| `self-learn.sh` | Edit/Write | Cross-session pattern capture | python3, jq |
| `post-edit-telemetry.sh` | Edit/Write | Log file edits to analytics | python3, jq |
| `post-edit-review-hint.sh` | Edit/Write | Suggest review after 10+ edits | python3 |
| `eval-gate.sh` | Edit/Write | Quality gate (tests + tsc + eval) | bun, jq |

### Stop (3 hooks)

| Hook | What | Dependencies |
|------|------|-------------|
| `stop-session-handoff.sh` | Generate session summary + Obsidian log | python3, jq |
| `stop-extract-instincts.sh` | Extract patterns to instincts directory | python3 |
| `stop-eval-gate.sh` | Session-end evaluation score | bun |

### Non-Lifecycle (1 hook)

| Hook | What |
|------|------|
| `pre-push-gate.sh` | Git pre-push validation (tests + tsc) |

## Error Handling

All hooks include:
- `set -euo pipefail` for strict error handling
- Binary availability checks (`_HAS_BUN`, `_HAS_PYTHON`, `_HAS_JQ`)
- `_log_error()` function writing to `~/.productionos/logs/hook-errors.log`
- Graceful degradation when dependencies are missing (skip, don't crash)

## Error Log

Hook failures are logged to:
```
~/.productionos/logs/hook-errors.log
```

Format: `[ISO8601] ERROR hook-name.sh: description`

## Configuration

Hooks are registered in `hooks/hooks.json`. The file is read by Claude Code on session start.

### Disable a Specific Hook

Remove the hook entry from `hooks/hooks.json`. Do not delete the `.sh` file.

### Disable All Hooks

Remove the `hooks` key from `hooks/hooks.json` or rename the file.

### Eval-Gate Frequency

The eval-gate runs tests after every 10 edits (configurable):
- Fast gate (tests + tsc): every 10 edits
- Full eval: every 20 edits

## Adding a New Hook

1. Create `hooks/my-hook.sh` with `#!/usr/bin/env bash` + `set -euo pipefail`
2. Include the binary check preamble (copy from any existing hook)
3. Add entry to `hooks/hooks.json` under the appropriate event
4. Make executable: `chmod +x hooks/my-hook.sh`
5. Test: `echo '{}' | bash hooks/my-hook.sh`
19 changes: 18 additions & 1 deletion hooks/eval-gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
# Enforces 8/10 quality standard — blocks session completion if below threshold.
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
EDIT_COUNT_FILE="$STATE_DIR/sessions/edit-count-$$"
Expand Down Expand Up @@ -38,7 +50,12 @@ if [ "$CURRENT_COUNT" -gt 0 ] && [ $((CURRENT_COUNT % EVAL_INTERVAL)) -eq 0 ]; t
fi

# Run full eval (slower, only at 20+ edits)
if [ "$CURRENT_COUNT" -ge 20 ]; then
if [ "$CURRENT_COUNT" -ge 20 ] && [ "$_HAS_BUN" = "1" ]; then
# Verify eval script exists before running
if [ ! -f "$PLUGIN_ROOT/scripts/eval-runner.ts" ] && [ ! -f "$PLUGIN_ROOT/package.json" ]; then
_log_error "eval-runner.ts not found, skipping full eval"
exit 0
fi
EVAL_SCORE=$(bun run eval 2>&1 | grep "OVERALL" | grep -oE '[0-9]+\.[0-9]+' || echo "0")
# Validate EVAL_SCORE is a plain decimal number before use
if [[ "$EVAL_SCORE" =~ ^[0-9]+\.[0-9]+$ ]]; then
Expand Down
12 changes: 12 additions & 0 deletions hooks/post-bash-telemetry.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env bash
# ProductionOS PostToolUse — log bash command telemetry
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
Expand Down
12 changes: 12 additions & 0 deletions hooks/post-edit-review-hint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
# ProductionOS PostToolUse — auto code review hint after edits
# Tracks edit count per session. After 10+ edits, suggests running review.
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
Expand Down
12 changes: 12 additions & 0 deletions hooks/post-edit-telemetry.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env bash
# ProductionOS PostToolUse — log edit telemetry (project-scoped)
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
Expand Down
12 changes: 12 additions & 0 deletions hooks/pre-commit-gitleaks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
# Only triggers on Bash tool invocations containing 'git commit'
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}

STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
INPUT=$(cat)

Expand Down
12 changes: 12 additions & 0 deletions hooks/pre-edit-security.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env bash
# ProductionOS PreToolUse — security advisory on sensitive file edits
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"

Expand Down
12 changes: 12 additions & 0 deletions hooks/pre-push-gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
# Also called by the Stop hook for session-end validation.
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}

PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
# Handle being called from .git/hooks/ (symlink target)
if [ ! -f "$PLUGIN_ROOT/package.json" ]; then
Expand Down
12 changes: 12 additions & 0 deletions hooks/protected-file-guard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
# Returns JSON: {"decision":"block","reason":"..."} or {"decision":"allow"}
# Handles Edit, Write, AND Bash tools (detects file writes in shell commands)
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"

Expand Down
12 changes: 12 additions & 0 deletions hooks/repo-boundary-guard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
# - No active project detected → ALLOW everything
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}

STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
INPUT=$(cat)

Expand Down
12 changes: 12 additions & 0 deletions hooks/scope-enforcement.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
# GAP-22 (git apply/am)
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}

# ─── Fast Exit: No scope enforcement active ─────────────────
SCOPE_FILE="${PRODUCTIONOS_AGENT_SCOPE:-}"
if [ -z "$SCOPE_FILE" ] || [ ! -f "$SCOPE_FILE" ]; then
Expand Down
12 changes: 12 additions & 0 deletions hooks/self-learn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
# v2: Cross-session pattern aggregation

set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"

Expand Down
12 changes: 12 additions & 0 deletions hooks/session-start.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env bash
# ProductionOS session start — init state, track session, detect project, show status
set -euo pipefail

# === Binary availability (degrade gracefully if missing) ===
_HAS_BUN=$(command -v bun >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_PYTHON=$(command -v python3 >/dev/null 2>&1 && echo "1" || echo "0")
_HAS_JQ=$(command -v jq >/dev/null 2>&1 && echo "1" || echo "0")
_LOG_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}/logs"
mkdir -p "$_LOG_DIR" 2>/dev/null || true

_log_error() {
local msg="$1"
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] ERROR $(basename "$0"): $msg" >> "$_LOG_DIR/hook-errors.log" 2>/dev/null || true
}
# Resolve plugin root — works for both marketplace install and git clone
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
STATE_DIR="${PRODUCTIONOS_HOME:-$HOME/.productionos}"
Expand Down
Loading