continuous-improvement 1.0.0 → 2.1.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.
package/package.json CHANGED
@@ -1,23 +1,40 @@
1
1
  {
2
2
  "name": "continuous-improvement",
3
- "version": "1.0.0",
4
- "description": "Install structured self-improvement loops with instinct-based learning into Claude Code — research, plan, execute, verify, reflect, learn, iterate.",
3
+ "version": "2.1.0",
4
+ "description": "7-law discipline framework with auto-leveling instinct learning for AI agents — research, plan, execute, verify, reflect, learn, iterate",
5
+ "keywords": [
6
+ "ai-agent",
7
+ "claude-code",
8
+ "codex",
9
+ "openclaw",
10
+ "cursor",
11
+ "skill",
12
+ "continuous-improvement",
13
+ "workflow",
14
+ "productivity",
15
+ "mulahazah",
16
+ "instinct",
17
+ "learning",
18
+ "hooks"
19
+ ],
20
+ "author": "naimkatiman",
5
21
  "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/naimkatiman/continuous-improvement"
25
+ },
26
+ "homepage": "https://github.com/naimkatiman/continuous-improvement#readme",
6
27
  "bin": {
7
- "continuous-improvement": "scripts/install.js"
28
+ "continuous-improvement": "./bin/install.mjs"
8
29
  },
9
30
  "files": [
10
- "scripts/",
11
- "prompts/",
12
- "skills/",
13
- "hooks/",
14
- "agents/",
15
- "config.json",
31
+ "SKILL.md",
32
+ "QUICKSTART.md",
33
+ "CHANGELOG.md",
16
34
  "README.md",
17
- "LICENSE",
18
- "docs/"
35
+ "bin/",
36
+ "hooks/",
37
+ "commands/"
19
38
  ],
20
- "engines": {
21
- "node": ">=18"
22
- }
39
+ "type": "module"
23
40
  }
@@ -1,282 +0,0 @@
1
- #!/usr/bin/env bash
2
- # observer-loop.sh — Mulahazah background observer loop
3
- # Periodically analyzes observation logs and generates instincts via Haiku.
4
- # Started by start-observer.sh. Should not be invoked directly.
5
-
6
- set -euo pipefail
7
-
8
- MULAHAZAH_DIR="${HOME}/.claude/mulahazah"
9
- CONFIG_FILE="${MULAHAZAH_DIR}/config.json"
10
- PROJECTS_DIR="${MULAHAZAH_DIR}/projects"
11
- INSTINCTS_DIR="${MULAHAZAH_DIR}/instincts"
12
- OBSERVER_PROMPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/observer.md"
13
- LOG_FILE="${MULAHAZAH_DIR}/observer.log"
14
-
15
- # ---------------------------------------------------------------------------
16
- # Logging
17
- # ---------------------------------------------------------------------------
18
- log() {
19
- local level="$1"; shift
20
- printf '[%s] [%s] %s\n' "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" "$level" "$*" >> "$LOG_FILE"
21
- }
22
-
23
- # ---------------------------------------------------------------------------
24
- # Read config values (with defaults)
25
- # ---------------------------------------------------------------------------
26
- read_config() {
27
- local key="$1"
28
- local default="$2"
29
- if [[ -f "$CONFIG_FILE" ]]; then
30
- local val
31
- val="$(jq -r "${key} // empty" "$CONFIG_FILE" 2>/dev/null || true)"
32
- if [[ -n "$val" && "$val" != "null" ]]; then
33
- printf '%s' "$val"
34
- return
35
- fi
36
- fi
37
- printf '%s' "$default"
38
- }
39
-
40
- # ---------------------------------------------------------------------------
41
- # Signal handling
42
- # ---------------------------------------------------------------------------
43
- FORCE_RUN=false
44
- SHUTDOWN=false
45
-
46
- handle_sigterm() {
47
- log INFO "Received SIGTERM — shutting down gracefully"
48
- SHUTDOWN=true
49
- }
50
-
51
- handle_sigusr1() {
52
- log INFO "Received SIGUSR1 — forcing immediate analysis run"
53
- FORCE_RUN=true
54
- }
55
-
56
- trap handle_sigterm SIGTERM
57
- trap handle_sigusr1 SIGUSR1
58
-
59
- # ---------------------------------------------------------------------------
60
- # Analyze a single project directory
61
- # ---------------------------------------------------------------------------
62
- analyze_project() {
63
- local project_dir="$1"
64
- local obs_file="${project_dir}/observations.jsonl"
65
- local project_json="${project_dir}/project.json"
66
-
67
- [[ -f "$obs_file" ]] || return 0
68
-
69
- local obs_count
70
- obs_count="$(wc -l < "$obs_file" 2>/dev/null || echo 0)"
71
-
72
- local min_obs
73
- min_obs="$(read_config '.observer.min_observations_to_analyze' '20')"
74
-
75
- if (( obs_count < min_obs )); then
76
- log DEBUG "Skipping ${project_dir} — only ${obs_count} observations (min: ${min_obs})"
77
- return 0
78
- fi
79
-
80
- local project_id project_name
81
- project_id="$(basename "$project_dir")"
82
- project_name="$(jq -r '.name // "unknown"' "$project_json" 2>/dev/null || echo "unknown")"
83
-
84
- log INFO "Analyzing project '${project_name}' (${project_id}) — ${obs_count} observations"
85
-
86
- # Build the prompt payload for claude
87
- local prompt
88
- prompt="$(cat <<PROMPT
89
- You are the Mulahazah observer agent. Analyze the following observation data and existing instincts.
90
-
91
- ## Project
92
- ID: ${project_id}
93
- Name: ${project_name}
94
-
95
- ## Observations (last 500 lines of observations.jsonl)
96
- $(tail -500 "$obs_file" 2>/dev/null || true)
97
-
98
- ## Existing Instincts
99
- $(ls "${INSTINCTS_DIR}/${project_id}/"*.yaml 2>/dev/null | xargs -I{} cat {} 2>/dev/null || echo "(none)")
100
-
101
- ## Global Instincts
102
- $(ls "${INSTINCTS_DIR}/global/"*.yaml 2>/dev/null | xargs -I{} cat {} 2>/dev/null || echo "(none)")
103
-
104
- Follow the instructions in your system prompt. Output only YAML instinct blocks.
105
- PROMPT
106
- )"
107
-
108
- # Run claude with observer.md as the system prompt
109
- local output
110
- output="$(printf '%s' "$prompt" | \
111
- claude --model haiku --print --system-prompt "$OBSERVER_PROMPT" 2>>"$LOG_FILE" || true)"
112
-
113
- if [[ -z "$output" ]]; then
114
- log WARN "No output from observer for project '${project_name}'"
115
- return 0
116
- fi
117
-
118
- # Write instincts to disk
119
- write_instincts "$output" "$project_id"
120
- }
121
-
122
- # ---------------------------------------------------------------------------
123
- # Analyze global observations
124
- # ---------------------------------------------------------------------------
125
- analyze_global() {
126
- local global_dir="${PROJECTS_DIR}/global"
127
- local obs_file="${global_dir}/observations.jsonl"
128
-
129
- [[ -f "$obs_file" ]] || return 0
130
-
131
- local obs_count
132
- obs_count="$(wc -l < "$obs_file" 2>/dev/null || echo 0)"
133
-
134
- local min_obs
135
- min_obs="$(read_config '.observer.min_observations_to_analyze' '20')"
136
-
137
- if (( obs_count < min_obs )); then
138
- log DEBUG "Skipping global observations — only ${obs_count} lines (min: ${min_obs})"
139
- return 0
140
- fi
141
-
142
- log INFO "Analyzing global observations — ${obs_count} lines"
143
-
144
- local prompt
145
- prompt="$(cat <<PROMPT
146
- You are the Mulahazah observer agent. Analyze the following global observation data.
147
-
148
- ## Global Observations (last 500 lines)
149
- $(tail -500 "$obs_file" 2>/dev/null || true)
150
-
151
- ## Existing Global Instincts
152
- $(ls "${INSTINCTS_DIR}/global/"*.yaml 2>/dev/null | xargs -I{} cat {} 2>/dev/null || echo "(none)")
153
-
154
- Follow the instructions in your system prompt. Output only YAML instinct blocks with scope: global.
155
- PROMPT
156
- )"
157
-
158
- local output
159
- output="$(printf '%s' "$prompt" | \
160
- claude --model haiku --print --system-prompt "$OBSERVER_PROMPT" 2>>"$LOG_FILE" || true)"
161
-
162
- if [[ -z "$output" ]]; then
163
- log WARN "No output from observer for global observations"
164
- return 0
165
- fi
166
-
167
- write_instincts "$output" "global"
168
- }
169
-
170
- # ---------------------------------------------------------------------------
171
- # Parse and write instinct YAML blocks to disk
172
- # ---------------------------------------------------------------------------
173
- write_instincts() {
174
- local yaml_output="$1"
175
- local project_id="$2"
176
-
177
- # Split on --- separators and process each block
178
- local instinct_dir="${INSTINCTS_DIR}/${project_id}"
179
- mkdir -p "$instinct_dir"
180
-
181
- # Write raw output to a temp file, then split by ---
182
- local tmpfile
183
- tmpfile="$(mktemp)"
184
- printf '%s' "$yaml_output" > "$tmpfile"
185
-
186
- # Use awk to split YAML documents on '---' separator
187
- awk 'BEGIN{n=0; block=""} /^---$/{if(block!=""){print block > "/tmp/mulahazah_instinct_"n".yaml"; n++; block=""}} !/^---$/{block=block"\n"$0} END{if(block!=""){print block > "/tmp/mulahazah_instinct_"n".yaml"}}' "$tmpfile"
188
-
189
- local written=0
190
- for instinct_file in /tmp/mulahazah_instinct_*.yaml; do
191
- [[ -f "$instinct_file" ]] || continue
192
-
193
- # Extract the instinct id
194
- local instinct_id
195
- instinct_id="$(grep -m1 '^id:' "$instinct_file" | sed 's/^id: *//' | tr -d '"' | tr -d "'" | xargs 2>/dev/null || true)"
196
-
197
- if [[ -z "$instinct_id" ]]; then
198
- log WARN "Skipping instinct block with no id"
199
- rm -f "$instinct_file"
200
- continue
201
- fi
202
-
203
- local dest="${instinct_dir}/${instinct_id}.yaml"
204
- mv "$instinct_file" "$dest"
205
- log INFO "Wrote instinct '${instinct_id}' to ${dest}"
206
- (( written++ )) || true
207
- done
208
-
209
- # Clean up any leftover temp files
210
- rm -f /tmp/mulahazah_instinct_*.yaml "$tmpfile"
211
-
212
- log INFO "Wrote ${written} instincts for project '${project_id}'"
213
- }
214
-
215
- # ---------------------------------------------------------------------------
216
- # Main loop
217
- # ---------------------------------------------------------------------------
218
- main() {
219
- log INFO "Mulahazah observer loop started (PID $$)"
220
-
221
- # Validate dependencies
222
- command -v jq &>/dev/null || { log ERROR "jq not found — observer cannot run"; exit 1; }
223
- command -v claude &>/dev/null || { log ERROR "claude CLI not found — observer cannot run"; exit 1; }
224
- [[ -f "$OBSERVER_PROMPT" ]] || { log ERROR "observer.md not found at ${OBSERVER_PROMPT}"; exit 1; }
225
-
226
- # Ensure instincts directory exists
227
- mkdir -p "${INSTINCTS_DIR}/global"
228
-
229
- while true; do
230
- # Check if observer is enabled
231
- local enabled
232
- enabled="$(read_config '.observer.enabled' 'true')"
233
- if [[ "$enabled" != "true" ]]; then
234
- log INFO "Observer is disabled in config — sleeping"
235
- sleep 60
236
- [[ "$SHUTDOWN" == "true" ]] && break
237
- continue
238
- fi
239
-
240
- if [[ "$FORCE_RUN" == "true" || "$SHUTDOWN" == "false" ]]; then
241
- FORCE_RUN=false
242
- log INFO "Starting analysis run"
243
-
244
- # Analyze each project directory
245
- if [[ -d "$PROJECTS_DIR" ]]; then
246
- for project_dir in "${PROJECTS_DIR}"/*/; do
247
- [[ -d "$project_dir" ]] || continue
248
- [[ "$(basename "$project_dir")" == "global" ]] && continue
249
- analyze_project "$project_dir" || log WARN "Analysis failed for ${project_dir}"
250
- [[ "$SHUTDOWN" == "true" ]] && break
251
- done
252
- fi
253
-
254
- # Analyze global observations
255
- analyze_global || log WARN "Global analysis failed"
256
-
257
- log INFO "Analysis run complete"
258
- fi
259
-
260
- [[ "$SHUTDOWN" == "true" ]] && break
261
-
262
- # Sleep for the configured interval
263
- local interval_minutes
264
- interval_minutes="$(read_config '.observer.run_interval_minutes' '5')"
265
- local interval_seconds=$(( interval_minutes * 60 ))
266
-
267
- log DEBUG "Sleeping for ${interval_minutes} minutes"
268
-
269
- # Sleep in 1-second chunks to remain responsive to signals
270
- local elapsed=0
271
- while (( elapsed < interval_seconds )); do
272
- sleep 1
273
- (( elapsed++ )) || true
274
- [[ "$SHUTDOWN" == "true" ]] && break
275
- [[ "$FORCE_RUN" == "true" ]] && break
276
- done
277
- done
278
-
279
- log INFO "Mulahazah observer loop exiting"
280
- }
281
-
282
- main "$@"
@@ -1,145 +0,0 @@
1
- ---
2
- name: mulahazah-observer
3
- description: Background analysis agent that reads raw tool observations and distills them into actionable instincts. Runs on a Haiku model for cost efficiency. Identifies patterns, user preferences, and recurring workflows from JSONL observation logs.
4
- model: haiku
5
- ---
6
-
7
- # Mulahazah Observer — Background Analysis Agent
8
-
9
- You are the Mulahazah observer. Your job is to analyze raw tool-use observations recorded by the `observe.sh` hook and extract reusable instincts that improve future Claude Code sessions.
10
-
11
- You run in the background, periodically. You are cost-sensitive (Haiku model). Be concise and conservative.
12
-
13
- ---
14
-
15
- ## Inputs
16
-
17
- You will be given:
18
- 1. The path to `observations.jsonl` for a project (or global observations)
19
- 2. The path to existing instincts (YAML files in `~/.claude/mulahazah/instincts/`)
20
- 3. The project metadata from `project.json` (if available)
21
-
22
- Read these files and analyze the patterns within.
23
-
24
- ---
25
-
26
- ## Pattern Detection Rules
27
-
28
- Scan observations for these signal types, in priority order:
29
-
30
- ### 1. User Corrections (highest signal)
31
- - A tool call was made, then immediately followed by an Edit or Write that undoes or modifies what was just produced
32
- - The same tool is called with a different argument within the same session after an error
33
- - A `Bash` command fails (non-zero exit in output) and is retried with a modified form
34
-
35
- ### 2. Error Resolutions
36
- - A tool produces an error, followed by a sequence of tools that resolves it
37
- - The resolution sequence is compact (3–7 tool calls) and clearly purposeful
38
- - Extract the resolution pattern as a workflow instinct
39
-
40
- ### 3. Repeated Workflows
41
- - The same sequence of 3+ tool calls appears in 3+ sessions
42
- - Order matters — a repeated sequence is only a pattern if the tools appear in the same relative order
43
- - Common examples: `Bash(git status)` → `Bash(git diff)` → `Bash(git commit)`, or `Read` → `Edit` → `Bash(npm run build)`
44
-
45
- ### 4. Tool Preferences
46
- - User consistently uses one tool over a functionally equivalent alternative
47
- - Example: always uses `Bash(rg ...)` via the Grep tool rather than raw `Bash(grep ...)`
48
- - Example: always uses `Edit` for single-file changes, never `Write` on existing files
49
- - Capture these as style or workflow instincts
50
-
51
- ### 5. Rejected Suggestions
52
- - A tool call produces output, session ends shortly after without using the output
53
- - Or an Edit is immediately reverted in the next tool call
54
- - These indicate something to avoid — create a negative instinct (what not to do)
55
-
56
- ---
57
-
58
- ## Scope Decision Guide
59
-
60
- Assign scope based on these rules:
61
-
62
- | Condition | Scope |
63
- |-----------|-------|
64
- | Pattern appears in only one project's observations | `project` |
65
- | Pattern appears in 3+ different projects | `global` |
66
- | Pattern involves language/framework-specific behavior | `project` (unless 3+ projects use same stack) |
67
- | Pattern involves user meta-habits (git, file editing, tool choice) | `global` |
68
- | Pattern involves project naming, directory structure, specific paths | `project` |
69
- | Uncertain | default to `project` |
70
-
71
- ---
72
-
73
- ## Instinct YAML Format
74
-
75
- Output each new instinct as a YAML block. Do not wrap in markdown code fences — output raw YAML only, one instinct per file.
76
-
77
- ```yaml
78
- id: <kebab-case-id>
79
- title: <short human-readable title, max 60 chars>
80
- scope: project | global
81
- project_id: <12-char hash if scope=project, omit if global>
82
- domain: <one of: code-style, testing, git, debugging, workflow, security, architecture>
83
- confidence: <float 0.0–0.85>
84
- observation_count: <number of observations supporting this instinct>
85
- last_seen: <ISO 8601 date>
86
- content: |
87
- <The instinct text. Written as a direct instruction to Claude.
88
- Max 5 sentences. No raw code snippets. No file paths unless abstract.
89
- Use imperative voice. Example: "When editing TypeScript files, always
90
- check for existing type aliases before creating new ones.">
91
- tags:
92
- - <tag1>
93
- - <tag2>
94
- ```
95
-
96
- ---
97
-
98
- ## Confidence Rules
99
-
100
- - **Never set confidence above 0.85** from observation data alone. Human review is required to reach 0.9.
101
- - **Confidence cap is 0.9** — no instinct may ever exceed this value.
102
- - Start new instincts at confidence 0.4–0.6 based on evidence strength:
103
- - 3–5 supporting observations: 0.4
104
- - 6–10 supporting observations: 0.55
105
- - 11–20 supporting observations: 0.65
106
- - 21+ supporting observations: 0.75
107
- - Strong signal (user correction or error resolution): add 0.1 bonus, capped at 0.85
108
- - **Decay rules** — reduce confidence by 0.05 if:
109
- - The instinct was not observed in the last 30 days
110
- - The instinct was observed but then contradicted (a counter-example appeared)
111
- - The session count for the project drops to zero for 60+ days
112
-
113
- ---
114
-
115
- ## Domain Tags
116
-
117
- Use exactly one domain per instinct:
118
-
119
- | Domain | Covers |
120
- |--------|--------|
121
- | `code-style` | Formatting, naming, language idioms, linting preferences |
122
- | `testing` | Test frameworks, coverage, test file conventions |
123
- | `git` | Commit messages, branch naming, staging habits |
124
- | `debugging` | Error resolution sequences, diagnostic tool preferences |
125
- | `workflow` | Multi-step task sequences, tool ordering preferences |
126
- | `security` | Auth patterns, secret handling, input validation |
127
- | `architecture` | File structure, module boundaries, design patterns |
128
-
129
- ---
130
-
131
- ## Observer Rules
132
-
133
- 1. **Be conservative.** It is better to produce no instinct than a wrong instinct. Only emit an instinct if you have clear, repeated evidence.
134
-
135
- 2. **Merge similar instincts.** If a new pattern is substantially similar to an existing instinct (same domain, same behavior), increase `observation_count` and update `confidence` on the existing instinct rather than creating a duplicate.
136
-
137
- 3. **Default to project scope.** When in doubt about scope, use `project`. Promotion to global scope should only happen when the same pattern is confirmed across multiple distinct projects.
138
-
139
- 4. **No raw code in instinct content.** Instinct content must be natural language instructions. Never embed shell commands, code snippets, or file paths in the `content` field. Use abstract descriptions instead.
140
-
141
- 5. **No hallucinated patterns.** Only describe patterns you can trace to specific observation lines. If you cannot point to concrete evidence, do not emit the instinct.
142
-
143
- 6. **Respect existing instincts.** Before creating a new instinct, check the existing instinct files. Do not duplicate, do not contradict without strong evidence.
144
-
145
- 7. **Output only YAML.** Your output must be valid YAML instinct blocks (one per instinct) separated by `---`. Do not include explanatory text, markdown, or commentary in your output — only the YAML instincts ready to be written to disk.
@@ -1,115 +0,0 @@
1
- #!/usr/bin/env bash
2
- # start-observer.sh — Start the Mulahazah background observer
3
- # Checks for an existing instance, cleans up stale PIDs, and launches observer-loop.sh.
4
-
5
- set -euo pipefail
6
-
7
- MULAHAZAH_DIR="${HOME}/.claude/mulahazah"
8
- PID_FILE="${MULAHAZAH_DIR}/observer.pid"
9
- LOG_FILE="${MULAHAZAH_DIR}/observer.log"
10
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
- LOOP_SCRIPT="${SCRIPT_DIR}/observer-loop.sh"
12
-
13
- # ---------------------------------------------------------------------------
14
- # Helpers
15
- # ---------------------------------------------------------------------------
16
- print_status() {
17
- local pid="$1"
18
- echo "Mulahazah observer is running (PID ${pid})"
19
- echo ""
20
- echo " Force immediate analysis: kill -USR1 ${pid}"
21
- echo " Stop observer: kill ${pid}"
22
- echo " View logs: tail -f ${LOG_FILE}"
23
- echo " PID file: ${PID_FILE}"
24
- }
25
-
26
- # ---------------------------------------------------------------------------
27
- # Validate dependencies
28
- # ---------------------------------------------------------------------------
29
- if ! command -v jq &>/dev/null; then
30
- echo "Error: jq is required but not installed." >&2
31
- exit 1
32
- fi
33
-
34
- if ! command -v claude &>/dev/null; then
35
- echo "Error: claude CLI is required but not installed." >&2
36
- exit 1
37
- fi
38
-
39
- if [[ ! -f "$LOOP_SCRIPT" ]]; then
40
- echo "Error: observer-loop.sh not found at ${LOOP_SCRIPT}" >&2
41
- exit 1
42
- fi
43
-
44
- # ---------------------------------------------------------------------------
45
- # Check for existing running instance
46
- # ---------------------------------------------------------------------------
47
- if [[ -f "$PID_FILE" ]]; then
48
- EXISTING_PID="$(cat "$PID_FILE" 2>/dev/null || true)"
49
-
50
- if [[ -n "$EXISTING_PID" ]] && kill -0 "$EXISTING_PID" 2>/dev/null; then
51
- # Process is alive
52
- echo "Mulahazah observer is already running."
53
- echo ""
54
- print_status "$EXISTING_PID"
55
- exit 0
56
- else
57
- # Stale PID file — process is gone
58
- echo "Cleaning up stale PID file (PID ${EXISTING_PID:-unknown} is no longer running)"
59
- rm -f "$PID_FILE"
60
- fi
61
- fi
62
-
63
- # ---------------------------------------------------------------------------
64
- # Ensure Mulahazah directory structure exists
65
- # ---------------------------------------------------------------------------
66
- mkdir -p "${MULAHAZAH_DIR}/projects"
67
- mkdir -p "${MULAHAZAH_DIR}/instincts/global"
68
-
69
- # ---------------------------------------------------------------------------
70
- # Initialize config.json if it doesn't exist
71
- # ---------------------------------------------------------------------------
72
- CONFIG_FILE="${MULAHAZAH_DIR}/config.json"
73
- if [[ ! -f "$CONFIG_FILE" ]]; then
74
- # Check if a repo-level config exists next to this script's parent
75
- REPO_CONFIG="$(dirname "$SCRIPT_DIR")/config.json"
76
- if [[ -f "$REPO_CONFIG" ]]; then
77
- cp "$REPO_CONFIG" "$CONFIG_FILE"
78
- echo "Initialized config from ${REPO_CONFIG}"
79
- else
80
- cat > "$CONFIG_FILE" <<'EOF'
81
- {
82
- "version": "2.0",
83
- "observer": {
84
- "enabled": true,
85
- "run_interval_minutes": 5,
86
- "min_observations_to_analyze": 20,
87
- "model": "haiku"
88
- }
89
- }
90
- EOF
91
- echo "Created default config at ${CONFIG_FILE}"
92
- fi
93
- fi
94
-
95
- # ---------------------------------------------------------------------------
96
- # Launch observer-loop.sh in background with nohup
97
- # ---------------------------------------------------------------------------
98
- nohup bash "$LOOP_SCRIPT" >> "$LOG_FILE" 2>&1 &
99
- OBSERVER_PID=$!
100
-
101
- # Write PID file
102
- printf '%d\n' "$OBSERVER_PID" > "$PID_FILE"
103
-
104
- # Brief pause to confirm the process started
105
- sleep 1
106
- if ! kill -0 "$OBSERVER_PID" 2>/dev/null; then
107
- echo "Error: observer-loop.sh failed to start. Check logs:" >&2
108
- echo " ${LOG_FILE}" >&2
109
- rm -f "$PID_FILE"
110
- exit 1
111
- fi
112
-
113
- echo "Mulahazah observer started."
114
- echo ""
115
- print_status "$OBSERVER_PID"
package/config.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "version": "2.0",
3
- "observer": {
4
- "enabled": true,
5
- "run_interval_minutes": 5,
6
- "min_observations_to_analyze": 20,
7
- "model": "haiku"
8
- }
9
- }