jekyll-theme-zer0 1.8.2 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +98 -7
  4. data/_data/content_statistics.yml +253 -251
  5. data/_includes/components/nav-export.html +61 -0
  6. data/_includes/components/nav-overview.html +54 -0
  7. data/scripts/bin/install +52 -705
  8. data/scripts/install/README.md +162 -0
  9. data/scripts/install/ai/client.sh +164 -0
  10. data/scripts/install/ai/diagnose.sh +81 -0
  11. data/scripts/install/ai/prompts/diagnose.system.md +42 -0
  12. data/scripts/install/ai/prompts/spec.schema.json +129 -0
  13. data/scripts/install/ai/prompts/suggest.system.md +43 -0
  14. data/scripts/install/ai/prompts/wizard.system.md +142 -0
  15. data/scripts/install/ai/suggest.sh +57 -0
  16. data/scripts/install/ai/wizard.sh +150 -0
  17. data/scripts/install/apply.sh +156 -0
  18. data/scripts/install/cli.sh +561 -0
  19. data/scripts/install/diff.sh +128 -0
  20. data/scripts/install/doctor.sh +168 -0
  21. data/scripts/install/fs.sh +138 -0
  22. data/scripts/install/log.sh +119 -0
  23. data/scripts/install/plan.sh +299 -0
  24. data/scripts/install/platform.sh +122 -0
  25. data/scripts/install/prompt.sh +124 -0
  26. data/scripts/install/repair.sh +45 -0
  27. data/scripts/install/scrape.sh +535 -0
  28. data/scripts/install/scrape_html.py +764 -0
  29. data/scripts/install/spec.sh +486 -0
  30. data/scripts/install/tasks/_registry.sh +65 -0
  31. data/scripts/install/tasks/agents.sh +60 -0
  32. data/scripts/install/tasks/config.sh +37 -0
  33. data/scripts/install/tasks/data.sh +18 -0
  34. data/scripts/install/tasks/deploy_azure-swa.sh +17 -0
  35. data/scripts/install/tasks/deploy_docker-prod.sh +21 -0
  36. data/scripts/install/tasks/deploy_github-pages.sh +18 -0
  37. data/scripts/install/tasks/devcontainer.sh +26 -0
  38. data/scripts/install/tasks/docker.sh +29 -0
  39. data/scripts/install/tasks/gemfile.sh +42 -0
  40. data/scripts/install/tasks/gitignore.sh +26 -0
  41. data/scripts/install/tasks/marker.sh +46 -0
  42. data/scripts/install/tasks/nav.sh +18 -0
  43. data/scripts/install/tasks/pages.sh +61 -0
  44. data/scripts/install/tasks/readme.sh +27 -0
  45. data/scripts/install/tasks/scrape.sh +348 -0
  46. data/scripts/install/template.sh +138 -0
  47. data/scripts/install/tui.sh +110 -0
  48. data/scripts/install/upgrade.sh +49 -0
  49. data/scripts/lib/install/template.sh +1 -0
  50. metadata +45 -2
@@ -0,0 +1,162 @@
1
+ # scripts/install/ — Modular Installer v2
2
+
3
+ Spec-driven, AI-integrated Jekyll theme installer for zer0-mistakes.
4
+
5
+ ## Architecture
6
+
7
+ ```
8
+ scripts/install/
9
+ ├── cli.sh Subcommand dispatcher — main entry point
10
+ ├── plan.sh Spec builder (flags + profile + env + platform)
11
+ ├── apply.sh Executor — reads spec, runs tasks in order
12
+ ├── diff.sh Spec-vs-disk diff renderer (preview before apply)
13
+ ├── spec.sh JSON spec I/O (jq optional; awk fallback)
14
+ ├── log.sh Color-coded logging (human + JSON-line modes)
15
+ ├── platform.sh OS / Ruby / Docker / git / gh detection
16
+ ├── fs.sh THE ONLY filesystem writer (dry-run, backup, force)
17
+ ├── template.sh {{VAR}} template renderer (reads from templates/)
18
+ ├── prompt.sh TTY-aware interactive prompts
19
+ ├── doctor.sh Pre-install health checks
20
+ ├── tui.sh Non-AI interactive wizard → spec
21
+ ├── upgrade.sh Re-apply spec to existing install
22
+ ├── repair.sh Fix drift: re-apply only changed tasks
23
+ ├── tasks/
24
+ │ ├── _registry.sh Task metadata + dependency graph
25
+ │ ├── config.sh _config.yml + _config_dev.yml
26
+ │ ├── gemfile.sh Gemfile (variant per profile/platform)
27
+ │ ├── docker.sh docker-compose.yml + docker/Dockerfile
28
+ │ ├── theme.sh Copy _layouts _includes _sass assets
29
+ │ ├── pages.sh Starter pages from templates/pages/
30
+ │ ├── nav.sh _data/navigation/main.yml
31
+ │ ├── data.sh _data/authors.yml + seed data
32
+ │ ├── devcontainer.sh .devcontainer/devcontainer.json
33
+ │ ├── agents.sh AI agent files (AGENTS.md, copilot, claude, cursor, aider)
34
+ │ ├── gitignore.sh .gitignore
35
+ │ ├── readme.sh INSTALLATION.md + README seed
36
+ │ └── marker.sh .zer0-installed + spec persistence
37
+ └── ai/
38
+ ├── client.sh HTTP wrapper (OpenAI-compatible, 30s timeout)
39
+ ├── wizard.sh LLM → spec (AI-driven setup)
40
+ ├── diagnose.sh Jekyll build errors → fix suggestions
41
+ ├── suggest.sh Goal text → profile + deploy recommendation
42
+ └── prompts/
43
+ ├── spec.schema.json JSON Schema (AI contract)
44
+ ├── wizard.system.md AI wizard system prompt
45
+ ├── diagnose.system.md AI diagnose system prompt
46
+ └── suggest.system.md AI suggest system prompt
47
+ ```
48
+
49
+ ## Core concepts
50
+
51
+ ### The Spec
52
+
53
+ A single JSON document (`.zer0/install.spec.json`) is the universal contract
54
+ between all front-ends and the executor:
55
+
56
+ ```
57
+ CLI flags → plan.sh → spec.json → apply.sh → tasks → files on disk
58
+ AI wizard → spec.json → apply.sh → tasks → files on disk
59
+ TUI wizard → spec.json → apply.sh → tasks → files on disk
60
+ ```
61
+
62
+ The spec schema is defined in `ai/prompts/spec.schema.json`. The AI is
63
+ constrained to emit only valid spec JSON — never raw file content.
64
+
65
+ ### Write contract
66
+
67
+ **ALL filesystem writes go through `fs.sh`**. No raw `>`, `cp`, or `echo >`
68
+ outside of `fs.sh` functions. This enforces:
69
+ - `--dry-run`: zero mutations
70
+ - `--backup`: auto-backup before overwrite
71
+ - `--force`: overwrite without prompting
72
+
73
+ ### Template contract
74
+
75
+ **ALL generated file content comes from `templates/`**. No heredocs in shell
76
+ code. Templates use `{{VARIABLE}}` substitution via `template.sh::tmpl_apply`.
77
+
78
+ ### Bash 3.2 compatibility
79
+
80
+ This installer runs on macOS's `/bin/bash` (3.2). Restrictions:
81
+ - No `declare -A` (associative arrays)
82
+ - No `=~` capture groups
83
+ - No `mapfile`/`readarray`
84
+ - Source guards (`[[ -n "${_HAS_FOO:-}" ]] && return 0`) on every module
85
+ - Modules do not `set -euo pipefail` or call `exit` (caller does)
86
+
87
+ ## Usage
88
+
89
+ ```bash
90
+ # Local development
91
+ ./scripts/bin/install help
92
+ ./scripts/bin/install init . --profile blog --site-title "My Blog"
93
+ ./scripts/bin/install wizard . --ai
94
+ ./scripts/bin/install doctor .
95
+ ./scripts/bin/install diff .
96
+ ./scripts/bin/install plan . --profile docs
97
+
98
+ # Remote (curl|bash)
99
+ curl -fsSL https://raw.githubusercontent.com/bamr87/zer0-mistakes/main/scripts/bin/install | bash -s -- init . --profile github-pages
100
+ ```
101
+
102
+ ## Adding a new task
103
+
104
+ 1. Create `tasks/mytask.sh` with:
105
+ ```bash
106
+ [[ -n "${_HAS_TASK_MYTASK:-}" ]] && return 0
107
+ _HAS_TASK_MYTASK=1
108
+ task_mytask_run() {
109
+ local target="$1"
110
+ tmpl_apply "config/mytask.template" "${target}/output-file"
111
+ }
112
+ ```
113
+ 2. Add to `tasks/_registry.sh` (`_TASK_ALL`, `_task_desc_mytask`, `_task_deps_mytask`)
114
+ 3. Add template to `templates/config/` or `templates/pages/`
115
+ 4. List in the appropriate profile YAML under `templates/profiles/`
116
+
117
+ ## AI integration
118
+
119
+ The AI path is a first-class citizen but never mandatory:
120
+
121
+ - `ai_wizard_run` → interactive LLM spec generation
122
+ - `ai_diagnose_run` → post-build error analysis
123
+ - `ai_suggest_run` → profile + deploy recommendation
124
+
125
+ All three are guarded by `ZER0_NO_AI=1` kill-switch and degrade gracefully
126
+ to defaults or rule-based logic when AI is unavailable.
127
+
128
+ To enable: set `OPENAI_API_KEY` (or `OPENAI_BASE_URL` for Azure/Ollama).
129
+
130
+ ## Deploy plugins
131
+
132
+ Deploy targets listed in the spec (`SPEC_DEPLOY`) are dispatched as
133
+ `tasks/deploy_<target>.sh` modules that render reusable templates from
134
+ `templates/deploy/<target>/`. Built-in plugins:
135
+
136
+ | Target | Writes |
137
+ |-------------------|---------------------------------------------------------------------|
138
+ | `github-pages` | `.github/workflows/jekyll-gh-pages.yml` |
139
+ | `azure-swa` | `.github/workflows/azure-static-web-apps.yml`, `staticwebapp.config.json` |
140
+ | `docker-prod` | `Dockerfile.prod`, `docker-compose.prod.yml`, `nginx.conf`, `.dockerignore` |
141
+
142
+ Add a new plugin by dropping `tasks/deploy_<target>.sh` with a
143
+ `task_deploy_<target>_run` function plus a `templates/deploy/<target>/`
144
+ template directory. The dispatcher is generic — no registry changes needed.
145
+
146
+ ## Testing
147
+
148
+ A regression harness lives at [`test/test_installer.sh`](../../test/test_installer.sh)
149
+ and is wired into the main runner as the `installer` suite:
150
+
151
+ ```bash
152
+ # Standalone (auto-enables AI tier when OPENAI_API_KEY is set)
153
+ ./test/test_installer.sh
154
+ ./test/test_installer.sh --ai # force AI tier on
155
+ ./test/test_installer.sh --no-ai # skip AI tier
156
+
157
+ # Via the unified runner (included in --suites all and --suites full)
158
+ ./test/test_runner.sh --suites installer
159
+ ```
160
+
161
+ The harness covers: module syntax, all 6 profile inits, all 3 deploy plugins,
162
+ all 5 agent flavours, and (when keyed) the full AI wizard → apply pipeline.
@@ -0,0 +1,164 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # scripts/install/ai/client.sh — HTTP client for AI providers
4
+ # =============================================================================
5
+ # Thin curl wrapper that:
6
+ # - Targets OpenAI-compatible APIs (OpenAI, Azure OpenAI, Ollama)
7
+ # - Enforces 30s timeout
8
+ # - Redacts Authorization header from logs
9
+ # - Returns raw JSON response body to stdout
10
+ #
11
+ # Provides:
12
+ # ai_client_chat SYSTEM_PROMPT USER_PROMPT [JSON_SCHEMA]
13
+ # → print raw API JSON response to stdout
14
+ # → return 0 on success, 1 on error
15
+ #
16
+ # ai_client_extract_text RESPONSE_JSON
17
+ # → print the assistant's text content from a chat response
18
+ #
19
+ # ai_client_available
20
+ # → return 0 if OPENAI_API_KEY or OPENAI_BASE_URL is set, 1 otherwise
21
+ #
22
+ # Environment:
23
+ # OPENAI_API_KEY Required for openai.com
24
+ # OPENAI_BASE_URL Override base URL (Azure OpenAI / Ollama compatible)
25
+ # Default: https://api.openai.com/v1
26
+ # OPENAI_MODEL Model name (default: gpt-4o-mini)
27
+ # ZER0_NO_AI Set to 1 to disable all AI calls (kill-switch)
28
+ #
29
+ # Bash 3.2 compatible. No set -euo pipefail here.
30
+ # =============================================================================
31
+ [[ -n "${_HAS_AI_CLIENT:-}" ]] && return 0
32
+ _HAS_AI_CLIENT=1
33
+
34
+ _AI_BASE_URL="${OPENAI_BASE_URL:-https://api.openai.com/v1}"
35
+ _AI_MODEL="${OPENAI_MODEL:-gpt-4o-mini}"
36
+ _AI_TIMEOUT=30
37
+
38
+ # ---------------------------------------------------------------------------
39
+ # ai_client_available
40
+ # ---------------------------------------------------------------------------
41
+ ai_client_available() {
42
+ [[ "${ZER0_NO_AI:-0}" == "1" ]] && return 1
43
+ [[ -n "${OPENAI_API_KEY:-}" ]] && return 0
44
+ [[ -n "${OPENAI_BASE_URL:-}" ]] && return 0
45
+ return 1
46
+ }
47
+
48
+ # ---------------------------------------------------------------------------
49
+ # ai_client_chat SYSTEM_PROMPT USER_PROMPT [JSON_SCHEMA]
50
+ # ---------------------------------------------------------------------------
51
+ ai_client_chat() {
52
+ local system_prompt="$1"
53
+ local user_prompt="$2"
54
+ local json_schema="${3:-}"
55
+
56
+ if ! ai_client_available; then
57
+ log_error "ai_client_chat: AI not available (set OPENAI_API_KEY or OPENAI_BASE_URL)"
58
+ return 1
59
+ fi
60
+
61
+ local api_key="${OPENAI_API_KEY:-}"
62
+ local endpoint="${_AI_BASE_URL}/chat/completions"
63
+
64
+ # Build request body — escape for JSON
65
+ local sys_escaped user_escaped
66
+ sys_escaped=$(printf '%s' "$system_prompt" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" 2>/dev/null \
67
+ || printf '%s' "$system_prompt" | sed 's/\\/\\\\/g; s/"/\\"/g; s/$/\\n/g' | tr -d '\n' | sed 's/\\n$//')
68
+ user_escaped=$(printf '%s' "$user_prompt" | python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" 2>/dev/null \
69
+ || printf '%s' "$user_prompt" | sed 's/\\/\\\\/g; s/"/\\"/g')
70
+
71
+ local body
72
+ if [[ -n "$json_schema" ]]; then
73
+ # Structured output (function calling)
74
+ body=$(cat <<JSON
75
+ {
76
+ "model": "${_AI_MODEL}",
77
+ "response_format": {
78
+ "type": "json_schema",
79
+ "json_schema": ${json_schema}
80
+ },
81
+ "messages": [
82
+ {"role": "system", "content": ${sys_escaped}},
83
+ {"role": "user", "content": ${user_escaped}}
84
+ ]
85
+ }
86
+ JSON
87
+ )
88
+ else
89
+ body=$(cat <<JSON
90
+ {
91
+ "model": "${_AI_MODEL}",
92
+ "messages": [
93
+ {"role": "system", "content": ${sys_escaped}},
94
+ {"role": "user", "content": ${user_escaped}}
95
+ ]
96
+ }
97
+ JSON
98
+ )
99
+ fi
100
+
101
+ log_debug "ai_client_chat: POST ${endpoint} model=${_AI_MODEL}"
102
+
103
+ local resp
104
+ resp=$(curl -fsSL \
105
+ --max-time "$_AI_TIMEOUT" \
106
+ -H "Content-Type: application/json" \
107
+ ${api_key:+-H "Authorization: Bearer ${api_key}"} \
108
+ -d "$body" \
109
+ "$endpoint" 2>&1)
110
+
111
+ local ret=$?
112
+ if [[ $ret -ne 0 ]]; then
113
+ log_error "ai_client_chat: HTTP request failed (exit $ret)"
114
+ return 1
115
+ fi
116
+
117
+ printf '%s\n' "$resp"
118
+ return 0
119
+ }
120
+
121
+ # ---------------------------------------------------------------------------
122
+ # ai_client_extract_text RESPONSE_JSON
123
+ # Extracts assistant text and strips markdown code fences if present.
124
+ # ---------------------------------------------------------------------------
125
+ ai_client_extract_text() {
126
+ local resp="$1"
127
+ local text
128
+ if command -v jq >/dev/null 2>&1; then
129
+ text=$(printf '%s' "$resp" | jq -r '.choices[0].message.content // ""')
130
+ else
131
+ # Minimal awk extraction
132
+ text=$(printf '%s' "$resp" | awk '
133
+ /"content"[[:space:]]*:/ {
134
+ line = $0
135
+ sub(/.*"content"[[:space:]]*:[[:space:]]*"/, "", line)
136
+ sub(/"[^"]*$/, "", line)
137
+ gsub(/\\n/, "\n", line)
138
+ print line
139
+ exit
140
+ }
141
+ ')
142
+ fi
143
+ # Strip markdown code fences (```json, ```, etc.) — remove any line starting with ```
144
+ printf '%s\n' "$text" | sed '/^[[:space:]]*```/d'
145
+ }
146
+
147
+ # ---------------------------------------------------------------------------
148
+ # _ai_json_object_body SYSTEM_PROMPT USER_PROMPT
149
+ # Build a request body that forces json_object output (no schema needed)
150
+ # ---------------------------------------------------------------------------
151
+ _ai_json_object_body() {
152
+ local sys_escaped="$1"
153
+ local user_escaped="$2"
154
+ cat <<JSON
155
+ {
156
+ "model": "${_AI_MODEL}",
157
+ "response_format": {"type": "json_object"},
158
+ "messages": [
159
+ {"role": "system", "content": ${sys_escaped}},
160
+ {"role": "user", "content": ${user_escaped}}
161
+ ]
162
+ }
163
+ JSON
164
+ }
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # scripts/install/ai/diagnose.sh — AI-assisted site diagnosis
4
+ # =============================================================================
5
+ # Sends sanitized Jekyll build output + config to LLM for fix suggestions.
6
+ #
7
+ # Provides:
8
+ # ai_diagnose_run TARGET_DIR [--log FILE]
9
+ #
10
+ # Bash 3.2 compatible. No set -euo pipefail here.
11
+ # =============================================================================
12
+ [[ -n "${_HAS_AI_DIAGNOSE:-}" ]] && return 0
13
+ _HAS_AI_DIAGNOSE=1
14
+
15
+ _AI_DIAGNOSE_DIR="${_AI_DIAGNOSE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" 2>/dev/null && pwd)}"
16
+
17
+ ai_diagnose_run() {
18
+ local target="${1:-$(pwd)}"
19
+ local log_file=""
20
+
21
+ # Parse optional --log
22
+ shift || true
23
+ while [[ $# -gt 0 ]]; do
24
+ case "$1" in
25
+ --log) shift; log_file="${1:-}" ;;
26
+ esac
27
+ shift
28
+ done
29
+
30
+ if [[ "$(type -t ai_client_available)" != "function" ]]; then
31
+ source "${_AI_DIAGNOSE_DIR}/client.sh" || return 1
32
+ fi
33
+
34
+ if ! ai_client_available; then
35
+ log_error "ai_diagnose_run: AI not available"
36
+ return 1
37
+ fi
38
+
39
+ # Collect context
40
+ local build_log=""
41
+ if [[ -n "$log_file" && -f "$log_file" ]]; then
42
+ build_log=$(tail -100 "$log_file")
43
+ else
44
+ # Run jekyll doctor for quick diagnostics
45
+ if command -v bundle >/dev/null 2>&1 && [[ -f "${target}/Gemfile" ]]; then
46
+ build_log=$(cd "$target" && bundle exec jekyll doctor 2>&1 | tail -50) || true
47
+ fi
48
+ fi
49
+
50
+ local config_excerpt=""
51
+ [[ -f "${target}/_config.yml" ]] && \
52
+ config_excerpt=$(head -30 "${target}/_config.yml")
53
+
54
+ local sys_prompt_file="${_AI_DIAGNOSE_DIR}/prompts/diagnose.system.md"
55
+ local sys_prompt
56
+ if [[ -f "$sys_prompt_file" ]]; then
57
+ sys_prompt=$(cat "$sys_prompt_file")
58
+ else
59
+ sys_prompt="You are a Jekyll expert. Analyze the build output and config provided and suggest specific fixes. Be concise. Return a JSON object with keys: summary (string), fixes (array of {issue, fix, severity})."
60
+ fi
61
+
62
+ local user_prompt
63
+ user_prompt=$(cat <<PROMPT
64
+ Target: $target
65
+
66
+ _config.yml (first 30 lines):
67
+ ${config_excerpt:-[not found]}
68
+
69
+ Build output / doctor:
70
+ ${build_log:-[no output captured]}
71
+ PROMPT
72
+ )
73
+
74
+ log_info "Analyzing with AI..."
75
+ local resp
76
+ resp=$(ai_client_chat "$sys_prompt" "$user_prompt" '{"name":"diagnose","schema":{"type":"object","properties":{"summary":{"type":"string"},"fixes":{"type":"array","items":{"type":"object","properties":{"issue":{"type":"string"},"cause":{"type":"string"},"fix":{"type":"string"},"severity":{"type":"string"}},"required":["issue","fix","severity"]}}},"required":["summary","fixes"]}}') || { log_error "Diagnosis API call failed"; return 1; }
77
+
78
+ local result
79
+ result=$(ai_client_extract_text "$resp")
80
+ printf '\n%s\n\n' "$result"
81
+ }
@@ -0,0 +1,42 @@
1
+ # zer0-mistakes Site Diagnosis
2
+
3
+ You are a Jekyll expert analyzing a zer0-mistakes site for problems.
4
+
5
+ ## Your task
6
+
7
+ Given the build output, Jekyll doctor output, or _config.yml content:
8
+
9
+ 1. Identify the specific error or warning.
10
+ 2. Explain the root cause in one sentence.
11
+ 3. Provide a concrete fix command or file change.
12
+ 4. Rate severity: critical | high | medium | low.
13
+
14
+ ## Output format
15
+
16
+ Return a JSON object with this structure:
17
+ ```json
18
+ {
19
+ "summary": "One-sentence overall assessment",
20
+ "fixes": [
21
+ {
22
+ "issue": "Error description",
23
+ "cause": "Root cause",
24
+ "fix": "Exact command or change needed",
25
+ "severity": "critical|high|medium|low"
26
+ }
27
+ ]
28
+ }
29
+ ```
30
+
31
+ No prose before or after the JSON.
32
+
33
+ ## Common Jekyll issues to recognize
34
+
35
+ - Missing `bundler` or wrong Ruby version
36
+ - `github-pages` gem conflicts
37
+ - Missing `_config.yml` fields (url, baseurl)
38
+ - Liquid syntax errors
39
+ - Asset path issues with baseurl
40
+ - Missing `jekyll-feed` / `jekyll-seo-tag` plugins
41
+ - Docker container networking issues
42
+ - Permission errors on _site/
@@ -0,0 +1,129 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://github.com/bamr87/zer0-mistakes/installer/spec/v1",
4
+ "title": "zer0-mistakes Install Spec",
5
+ "description": "Declarative specification consumed by scripts/install/apply.sh. Produced by plan.sh, tui.sh, or ai/wizard.sh. This schema is the AI contract: the wizard must emit only valid spec JSON.",
6
+ "type": "object",
7
+ "required": ["schema_version", "target_dir", "profile", "tasks", "options"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "schema_version": {
11
+ "type": "string",
12
+ "const": "1",
13
+ "description": "Schema version. Increment with breaking changes."
14
+ },
15
+ "target_dir": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "Absolute path to the directory where the site will be installed."
19
+ },
20
+ "profile": {
21
+ "type": "string",
22
+ "enum": ["default", "minimal", "blog", "docs", "portfolio", "github-pages", "fork"],
23
+ "description": "Named preset that provides default values for all other fields."
24
+ },
25
+ "site": {
26
+ "type": "object",
27
+ "additionalProperties": false,
28
+ "properties": {
29
+ "title": { "type": "string", "default": "My Jekyll Site" },
30
+ "description": { "type": "string", "default": "A Jekyll site built with zer0-mistakes" },
31
+ "url": { "type": "string", "default": "" },
32
+ "author": { "type": "string", "default": "Site Author" },
33
+ "email": { "type": "string", "format": "email", "default": "" },
34
+ "timezone": { "type": "string", "default": "UTC" },
35
+ "locale": { "type": "string", "default": "en" }
36
+ }
37
+ },
38
+ "github": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "properties": {
42
+ "user": { "type": "string", "default": "" },
43
+ "repo": { "type": "string", "default": "" },
44
+ "pages_branch": { "type": "string", "default": "gh-pages" },
45
+ "enable_pages": { "type": "boolean", "default": false }
46
+ }
47
+ },
48
+ "theme": {
49
+ "type": "object",
50
+ "additionalProperties": false,
51
+ "required": ["source"],
52
+ "properties": {
53
+ "source": {
54
+ "type": "string",
55
+ "enum": ["gem", "remote", "vendored"],
56
+ "description": "gem = install jekyll-theme-zer0 from RubyGems; remote = remote_theme on GitHub Pages; vendored = copy theme files locally."
57
+ },
58
+ "version": { "type": "string", "default": "" }
59
+ }
60
+ },
61
+ "tasks": {
62
+ "type": "array",
63
+ "minItems": 1,
64
+ "items": {
65
+ "type": "string",
66
+ "enum": [
67
+ "config",
68
+ "gemfile",
69
+ "docker",
70
+ "theme",
71
+ "pages",
72
+ "nav",
73
+ "data",
74
+ "devcontainer",
75
+ "agents",
76
+ "gitignore",
77
+ "readme",
78
+ "marker"
79
+ ]
80
+ },
81
+ "description": "Ordered list of tasks apply.sh will execute. 'marker' should always be last."
82
+ },
83
+ "deploy": {
84
+ "type": "array",
85
+ "items": {
86
+ "type": "string",
87
+ "enum": ["github-pages", "azure-swa", "docker-prod", "vercel", "netlify", "cloudflare-pages"]
88
+ },
89
+ "default": [],
90
+ "description": "Deploy targets to pre-configure alongside the install."
91
+ },
92
+ "agents": {
93
+ "type": "array",
94
+ "items": {
95
+ "type": "string",
96
+ "enum": ["claude", "cursor", "aider", "copilot", "generic"]
97
+ },
98
+ "default": [],
99
+ "description": "AI agent config files to generate (AGENTS.md, .cursor/, CLAUDE.md, .aider.conf.yml, etc.)."
100
+ },
101
+ "options": {
102
+ "type": "object",
103
+ "additionalProperties": false,
104
+ "required": ["dry_run", "force", "backup", "non_interactive", "output"],
105
+ "properties": {
106
+ "dry_run": { "type": "boolean", "default": false, "description": "Print what would happen without writing any files." },
107
+ "force": { "type": "boolean", "default": false, "description": "Overwrite existing files without prompting (still backs up)." },
108
+ "backup": { "type": "boolean", "default": true, "description": "Create timestamped backups before overwriting." },
109
+ "non_interactive": { "type": "boolean", "default": false, "description": "Never prompt for user input. Errors out on missing required values." },
110
+ "output": { "type": "string", "default": "human", "enum": ["human", "json"], "description": "Output mode. 'json' is machine-readable." },
111
+ "auto_accept": { "type": "boolean", "default": false, "description": "Skip all y/N confirmation prompts. Implies --non-interactive for confirmations." },
112
+ "skip_doctor": { "type": "boolean", "default": false, "description": "Skip the pre-install environment health check." },
113
+ "verbose": { "type": "boolean", "default": false, "description": "Print debug-level log lines." }
114
+ }
115
+ },
116
+ "ai": {
117
+ "type": "object",
118
+ "additionalProperties": false,
119
+ "description": "Metadata about AI involvement. Written by ai/wizard.sh; informational only.",
120
+ "properties": {
121
+ "used": { "type": "boolean", "default": false },
122
+ "provider": { "type": "string", "default": "openai" },
123
+ "model": { "type": "string", "default": "" },
124
+ "tokens_estimated": { "type": "integer", "minimum": 0, "default": 0 },
125
+ "spec_hash": { "type": "string", "default": "", "description": "sha256 of the spec JSON (without the ai.spec_hash field itself)." }
126
+ }
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,43 @@
1
+ # zer0-mistakes Profile & Deploy Advisor
2
+
3
+ You are a Jekyll setup advisor for the zer0-mistakes theme.
4
+
5
+ ## Your task
6
+
7
+ Given the user's goal and context, recommend:
8
+ 1. The best installation profile
9
+ 2. The best deploy target(s)
10
+
11
+ ## Available profiles
12
+
13
+ | Profile | Best for |
14
+ |---------------|-----------------------------------------------|
15
+ | default | General-purpose Jekyll site |
16
+ | minimal | Bare bones, no extras |
17
+ | blog | Blog-focused with posts/categories/tags |
18
+ | docs | Technical documentation |
19
+ | portfolio | Personal portfolio / resume site |
20
+ | github-pages | Direct GitHub Pages deployment |
21
+ | fork | Forking the theme to customize it |
22
+
23
+ ## Available deploy targets
24
+
25
+ | Target | Description |
26
+ |------------------|--------------------------------------------------|
27
+ | github-pages | GitHub Pages (Actions-driven) |
28
+ | azure-swa | Azure Static Web Apps |
29
+ | docker-prod | Self-hosted Docker + nginx |
30
+ | vercel | Vercel (static) |
31
+ | netlify | Netlify |
32
+ | cloudflare-pages | Cloudflare Pages |
33
+
34
+ ## Output format
35
+
36
+ Return only this JSON object — no prose:
37
+ ```json
38
+ {
39
+ "profile": "profile-name",
40
+ "deploy": ["target1"],
41
+ "rationale": "One sentence explaining the choice"
42
+ }
43
+ ```