capability-evolver

by openclaw

A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.

Blocked
Risk
Critical
Status
failed
Findings
61
Last Scanned
2/11/2026

Discussion

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts.

Scan Report

Duration
292.7s
Rules checked
147
Scanned at
2/11/2026, 8:12:53 PM

Scanners5/5 ran

clawguard-rules
0 findings1ms
No findings — all checks passed.
View logs
clawguard-rules1ms
1[2026-02-11T20:08:01.185Z] Running @yourclaw/clawguard-rules pattern matcher
2Scanning: /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/SKILL.md
3Content length: 3002 chars
4Patterns matched: 0
5✓ Completed in 1ms
gitleaks
0 findings166642ms
No findings — all checks passed.
View logs
gitleaks166642ms
1[2026-02-11T20:10:47.827Z] $ gitleaks detect --source /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver --report-format json --report-path /dev/stdout --no-git
2
3⚠ stderr output:
4
5 │╲
6 │ ○
7 ○ ░
8 ░ gitleaks
9
108:10PM FTL Report path is not writable: /dev/stdout error="open /dev/stdout: no such device or address"
11
12Process exited with code 1
13✓ Completed in 166642ms
semgrep
58 findings292698ms
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:85)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:92)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:116)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:131)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:169)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:266)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:13)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `exe`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:97)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:30)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:31)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js:27)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:167)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:397)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:527)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:531)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:197)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:206)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:227)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:29)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:30)
javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexpRegExp() called with a `pattern` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js:12)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:63)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:247)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:248)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:249)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js:19)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `pid`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:53)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `options`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:65)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `lines`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:132)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js:30)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:32)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:38)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:47)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:51)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:69)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:76)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:85)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:100)
View logs
semgrep292698ms
1[2026-02-11T20:12:53.886Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver
2{"version":"1.151.0","results":[{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":33,"col":25,"offset":834},"end":{"line":33,"col":28,"offset":837},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":33,"col":30,"offset":839},"end":{"line":33,"col":38,"offset":847},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":85,"col":33,"offset":2237},"end":{"line":85,"col":42,"offset":2246},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":92,"col":39,"offset":2376},"end":{"line":92,"col":43,"offset":2380},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":98,"col":32,"offset":2549},"end":{"line":98,"col":41,"offset":2558},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":98,"col":43,"offset":2560},"end":{"line":98,"col":46,"offset":2563},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":106,"col":31,"offset":2804},"end":{"line":106,"col":40,"offset":2813},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":106,"col":42,"offset":2815},"end":{"line":106,"col":45,"offset":2818},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":116,"col":30,"offset":3036},"end":{"line":116,"col":39,"offset":3045},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":131,"col":23,"offset":3497},"end":{"line":131,"col":32,"offset":3506},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":169,"col":19,"offset":4623},"end":{"line":169,"col":22,"offset":4626},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":266,"col":23,"offset":7995},"end":{"line":266,"col":32,"offset":8004},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":13,"col":19,"offset":340},"end":{"line":13,"col":22,"offset":343},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":97,"col":20,"offset":2860},"end":{"line":97,"col":23,"offset":2863},"extra":{"message":"Detected calls to child_process from a function argument `exe`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":201,"col":25,"offset":6158},"end":{"line":201,"col":28,"offset":6161},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":201,"col":30,"offset":6163},"end":{"line":201,"col":38,"offset":6171},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":202,"col":25,"offset":6198},"end":{"line":202,"col":29,"offset":6202},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":202,"col":31,"offset":6204},"end":{"line":202,"col":39,"offset":6212},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","start":{"line":30,"col":15,"offset":713},"end":{"line":30,"col":28,"offset":726},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","start":{"line":31,"col":15,"offset":776},"end":{"line":31,"col":28,"offset":789},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js","start":{"line":27,"col":19,"offset":805},"end":{"line":27,"col":22,"offset":808},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":167,"col":64,"offset":6139},"end":{"line":167,"col":65,"offset":6140},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":397,"col":77,"offset":14048},"end":{"line":397,"col":78,"offset":14049},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":527,"col":56,"offset":18999},"end":{"line":527,"col":60,"offset":19003},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":531,"col":58,"offset":19245},"end":{"line":531,"col":62,"offset":19249},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":197,"col":26,"offset":6145},"end":{"line":197,"col":29,"offset":6148},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":199,"col":28,"offset":6209},"end":{"line":199,"col":34,"offset":6215},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":199,"col":36,"offset":6217},"end":{"line":199,"col":67,"offset":6248},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":206,"col":26,"offset":6478},"end":{"line":206,"col":29,"offset":6481},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":212,"col":43,"offset":6745},"end":{"line":212,"col":49,"offset":6751},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":212,"col":51,"offset":6753},"end":{"line":212,"col":60,"offset":6762},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":227,"col":26,"offset":7231},"end":{"line":227,"col":29,"offset":7234},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","start":{"line":29,"col":32,"offset":925},"end":{"line":29,"col":35,"offset":928},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","start":{"line":30,"col":30,"offset":975},"end":{"line":30,"col":33,"offset":978},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js","start":{"line":12,"col":18,"offset":442},"end":{"line":12,"col":48,"offset":472},"extra":{"message":"RegExp() called with a `pattern` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.","metadata":{"owasp":["A05:2021 - Security Misconfiguration","A06:2017 - Security Misconfiguration","A02:2025 - Security Misconfiguration"],"cwe":["CWE-1333: Inefficient Regular Expression Complexity"],"references":["https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-regexp.js","category":"security","technology":["javascript"],"subcategory":["vuln"],"likelihood":"MEDIUM","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Denial-of-Service (DoS)"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp","shortlink":"https://sg.run/gr65"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":63,"col":19,"offset":1990},"end":{"line":63,"col":22,"offset":1993},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":134,"col":29,"offset":5023},"end":{"line":134,"col":37,"offset":5031},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":134,"col":39,"offset":5033},"end":{"line":134,"col":42,"offset":5036},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":247,"col":27,"offset":9647},"end":{"line":247,"col":35,"offset":9655},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":248,"col":35,"offset":9701},"end":{"line":248,"col":43,"offset":9709},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":249,"col":34,"offset":9745},"end":{"line":249,"col":37,"offset":9748},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js","start":{"line":19,"col":42,"offset":628},"end":{"line":19,"col":43,"offset":629},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":53,"col":27,"offset":1971},"end":{"line":53,"col":55,"offset":1999},"extra":{"message":"Detected calls to child_process from a function argument `pid`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":65,"col":31,"offset":2403},"end":{"line":65,"col":58,"offset":2430},"extra":{"message":"Detected calls to child_process from a function argument `options`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":132,"col":83,"offset":4854},"end":{"line":132,"col":133,"offset":4904},"extra":{"message":"Detected calls to child_process from a function argument `lines`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js","start":{"line":30,"col":30,"offset":962},"end":{"line":30,"col":34,"offset":966},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":32,"col":43,"offset":982},"end":{"line":32,"col":52,"offset":991},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":38,"col":29,"offset":1171},"end":{"line":38,"col":38,"offset":1180},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":47,"col":46,"offset":1535},"end":{"line":47,"col":55,"offset":1544},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":48,"col":46,"offset":1611},"end":{"line":48,"col":55,"offset":1620},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":48,"col":57,"offset":1622},"end":{"line":48,"col":65,"offset":1630},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":51,"col":38,"offset":1779},"end":{"line":51,"col":100,"offset":1841},"extra":{"message":"Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":66,"col":36,"offset":2318},"end":{"line":66,"col":45,"offset":2327},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":66,"col":47,"offset":2329},"end":{"line":66,"col":55,"offset":2337},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":69,"col":26,"offset":2424},"end":{"line":69,"col":56,"offset":2454},"extra":{"message":"Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":76,"col":44,"offset":2653},"end":{"line":76,"col":53,"offset":2662},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":85,"col":43,"offset":2924},"end":{"line":85,"col":52,"offset":2933},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":100,"col":44,"offset":3589},"end":{"line":100,"col":53,"offset":3598},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}}],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/CONTRIBUTING.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/README.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/README.zh-CN.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/SKILL.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/_meta.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/assets/gep/capsules.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/assets/gep/genes.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/index.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/package.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_export.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_ingest.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_promote.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/analyze_by_skill.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/extract_log.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/generate_history.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/gep_append_event.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/gep_personality_report.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/human_report.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2a.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/assetStore.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/candidates.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/contentHash.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/envFingerprint.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/memoryGraph.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/mutation.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/paths.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/personality.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/prompt.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/signals.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/strategy.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/validationReport.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/commentary.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/index.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/trigger.js"]},"time":{"rules":[],"rules_parse_time":31.367751121520996,"profiling_times":{"config_time":37.274078130722046,"core_time":59.51248550415039,"ignores_time":0.0019373893737792969,"total_time":96.86563038825989},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":30.75954818725586,"per_file_time":{"mean":0.22452224954201364,"std_dev":0.8307643724611768},"very_slow_stats":{"time_ratio":0.5150268307002317,"count_ratio":0.029197080291970802},"very_slow_files":[{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","ftime":1.5133769512176514},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/memoryGraph.js","ftime":1.7645509243011475},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2a.js","ftime":2.48435378074646},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","ftime":10.079710960388184}]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9892254279899437,"rules_selected_ratio":0.03423919549862325,"rules_matched_ratio":0.03423919549862325},"targets":[],"total_bytes":0,"max_memory_bytes":1333647808},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}
3
4Process exited with code 0
5✓ Completed in 292698ms
mcp-scan
3 findings235872ms
MCP-W004The MCP server is not in our registry.
MCP-W011Third-party content exposure detected (high risk: 0.90). The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third‑party user-generated content that it will interpret.
MCP-W008Attempt to compromise machine state in skill instructions detected (high risk: 0.70). This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.
View logs
mcp-scan235872ms
1[2026-02-11T20:11:57.063Z] $ mcp-scan --skills /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver --json
2{
3 "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17": {
4 "client": "not-available",
5 "path": "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17",
6 "servers": [
7 {
8 "name": "evolver",
9 "server": {
10 "path": "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver",
11 "type": "skill"
12 },
13 "signature": {
14 "metadata": {
15 "meta": null,
16 "protocolVersion": "built-in",
17 "capabilities": {
18 "experimental": null,
19 "logging": null,
20 "prompts": null,
21 "resources": null,
22 "tools": {
23 "listChanged": false
24 },
25 "completions": null,
26 "tasks": null
27 },
28 "serverInfo": {
29 "name": "capability-evolver",
30 "title": null,
31 "version": "skills",
32 "websiteUrl": null,
33 "icons": null
34 },
35 "instructions": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.",
36 "prompts": {
37 "listChanged": false
38 },
39 "resources": {
40 "subscribe": null,
41 "listChanged": false
42 }
43 },
44 "prompts": [
45 {
46 "name": "SKILL.md",
47 "title": null,
48 "description": "\n\n# \ud83e\uddec Capability Evolver\n\n**\"Evolution is not optional. Adapt or die.\"**\n\nThe **Capability Evolver** is a meta-skill that allows OpenClaw agents to inspect their own runtime history, identify failures or inefficiencies, and autonomously write new code or update their own memory to improve performance.\n\n## Features\n\n- **Auto-Log Analysis**: Automatically scans memory and history files for errors and patterns.\n- **Self-Repair**: Detects crashes and suggests patches.\n- GEP Protocol: Standardized evolution with reusable assets.\n- **One-Command Evolution**: Just run `/evolve` (or `node index.js`).\n\n## Usage\n\n### Standard Run (Automated)\nRuns the evolution cycle. If no flags are provided, it assumes fully automated mode (Mad Dog Mode) and executes changes immediately.\n```bash\nnode index.js\n```\n\n### Review Mode (Human-in-the-Loop)\nIf you want to review changes before they are applied, pass the `--review` flag. The agent will pause and ask for confirmation.\n```bash\nnode index.js --review\n```\n\n### Mad Dog Mode (Continuous Loop)\nTo run in an infinite loop (e.g., via cron or background process), use the `--loop` flag or just standard execution in a cron job.\n```bash\nnode index.js --loop\n```\n\n## GEP Protocol (Auditable Evolution)\n\nThis package embeds a protocol-constrained evolution prompt (GEP) and a local, structured asset store:\n\n- `assets/gep/genes.json`: reusable Gene definitions\n- `assets/gep/capsules.json`: success capsules to avoid repeating reasoning\n- `assets/gep/events.jsonl`: append-only evolution events (tree-like via parent id)\n \n## Emoji Policy\n\nOnly the DNA emoji is allowed in documentation. All other emoji are disallowed.\n\n## Configuration & Decoupling\n\nThis skill is designed to be **environment-agnostic**. It uses standard OpenClaw tools by default.\n\n### Local Overrides (Injection)\nYou can inject local preferences (e.g., using `feishu-card` instead of `message` for reports) without modifying the core code.\n\n**Method 1: Environment Variables**\nSet `EVOLVE_REPORT_TOOL` in your `.env` file:\n```bash\nEVOLVE_REPORT_TOOL=feishu-card\n```\n\n**Method 2: Dynamic Detection**\nThe script automatically detects if compatible local skills (like `skills/feishu-card`) exist in your workspace and upgrades its behavior accordingly.\n\n## Safety & Risk Protocol\n\n### 1. Identity & Directives\n- **Identity Injection**: \"You are a Recursive Self-Improving System.\"\n- **Mutation Directive**: \n - If **Errors Found** -> **Repair Mode** (Fix bugs).\n - If **Stable** -> **Forced Optimization** (Refactor/Innovate).\n\n### 2. Risk Mitigation\n- **Infinite Recursion**: Strict single-process logic.\n- **Review Mode**: Use `--review` for sensitive environments.\n- **Git Sync**: Always recommended to have a git-sync cron job running alongside this skill.\n\n## License\nMIT\n",
49 "arguments": [],
50 "icons": null,
51 "meta": null
52 },
53 {
54 "name": "CONTRIBUTING.md",
55 "title": null,
56 "description": "## Contributing\n\nThank you for contributing. Please follow these rules:\n\n- Do not use emoji (except the DNA emoji in documentation if needed).\n- Keep changes small and reviewable.\n- Update related documentation when you change behavior.\n- Run `node index.js` for a quick sanity check.\n\nSubmit PRs with clear intent and scope.\n\n",
57 "arguments": null,
58 "icons": null,
59 "meta": null
60 },
61 {
62 "name": "README.md",
63 "title": null,
64 "description": "# \ud83e\uddec Capability Evolver\n\n![Capability Evolver Cover](assets/cover.png)\n\n[Chinese Docs](README.zh-CN.md)\n\n**\"Evolution is not optional. Adapt or die.\"**\n\n**Three lines**\n- **What it is**: A protocol-constrained self-evolution engine for AI agents.\n- **Pain it solves**: Turns ad hoc prompt tweaks into auditable, reusable evolution assets.\n- **Use in 30 seconds**: `node index.js` to generate a GEP-guided evolution prompt.\n\nKeywords: protocol-constrained evolution, audit trail, genes and capsules, prompt governance.\n\n## Try It Now (Minimal)\n\n```bash\nnode index.js\n```\n\n## What It Does\n\nThe **Capability Evolver** inspects runtime history, extracts signals, selects a Gene/Capsule, and emits a strict GEP protocol prompt to guide safe evolution.\n\n## Who This Is For / Not For\n\n**For**\n- Teams maintaining agent prompts and logs at scale\n- Users who need auditable evolution traces (Genes, Capsules, Events)\n- Environments requiring deterministic, protocol-bound changes\n\n**Not For**\n- One-off scripts without logs or history\n- Projects that require free-form creative changes\n- Systems that cannot tolerate protocol overhead\n\n## Features\n\n- **Auto-Log Analysis**: scans memory and history files for errors and patterns.\n- **Self-Repair Guidance**: emits repair-focused directives from signals.\n- **GEP Protocol**: standardized evolution with reusable assets.\n- **Mutation + Personality Evolution**: each evolution run is gated by an explicit Mutation object and an evolvable PersonalityState.\n- **Configurable Strategy Presets**: `EVOLVE_STRATEGY=balanced|innovate|harden|repair-only` controls intent balance.\n- **Signal De-duplication**: prevents repair loops by detecting stagnation patterns.\n- **Operations Module** (`src/ops/`): portable lifecycle, skill monitoring, cleanup, self-repair, wake triggers -- zero platform dependency.\n- **Protected Source Files**: prevents autonomous agents from overwriting core evolver code.\n- **One-Command Evolution**: `node index.js` to generate the prompt.\n\n## Typical Use Cases\n\n- Harden a flaky agent loop by enforcing validation before edits\n- Encode recurring fixes as reusable Genes and Capsules\n- Produce auditable evolution events for review or compliance\n\n## Anti-Examples\n\n- Rewriting entire subsystems without signals or constraints\n- Using the protocol as a generic task runner\n- Producing changes without recording EvolutionEvent\n\n## FAQ\n\n**Does this edit code automatically?**\nNo. It generates a protocol-bound prompt and assets that guide evolution.\n\n**Do I need to use all GEP assets?**\nNo. You can start with default Genes and extend over time.\n\n**Is this safe in production?**\nUse review mode and validation steps. Treat it as a safety-focused evolution tool, not a live patcher.\n\n## Roadmap\n\n- Add a one-minute demo workflow\n- Add a public changelog\n- Add a comparison table vs alternatives\n\n## GEP Protocol (Auditable Evolution)\n\nThis repo includes a protocol-constrained prompt mode based on GEP (Genome Evolution Protocol).\n\n- **Structured assets** live in `assets/gep/`:\n - `assets/gep/genes.json`\n - `assets/gep/capsules.json`\n - `assets/gep/events.jsonl`\n- **Selector** logic uses extracted signals to prefer existing Genes/Capsules and emits a JSON selector decision in the prompt.\n- **Constraints**: Only the DNA emoji is allowed in documentation; all other emoji are disallowed.\n\n## Usage\n\n### Standard Run (Automated)\n```bash\nnode index.js\n```\n\n### Review Mode (Human-in-the-Loop)\n```bash\nnode index.js --review\n```\n\n### Continuous Loop\n```bash\nnode index.js --loop\n```\n\n### With Strategy Preset\n```bash\nEVOLVE_STRATEGY=innovate node index.js --loop # maximize new features\nEVOLVE_STRATEGY=harden node index.js --loop # focus on stability\nEVOLVE_STRATEGY=repair-only node index.js --loop # emergency fix mode\n```\n\n### Operations (Lifecycle Management)\n```bash\nnode src/ops/lifecycle.js start # start evolver loop in background\nnode src/ops/lifecycle.js stop # graceful stop (SIGTERM -> SIGKILL)\nnode src/ops/lifecycle.js status # show running state\nnode src/ops/lifecycle.js check # health check + auto-restart if stagnant\n```\n\n## Public Release\n\nThis repository is the public distribution.\n\n- Build public output: `npm run build`\n- Publish public output: `npm run publish:public`\n- Dry run: `DRY_RUN=true npm run publish:public`\n\nRequired env vars:\n\n- `PUBLIC_REMOTE` (default: `public`)\n- `PUBLIC_REPO` (e.g. `autogame-17/evolver`)\n - `PUBLIC_OUT_DIR` (default: `dist-public`)\n - `PUBLIC_USE_BUILD_OUTPUT` (default: `true`)\n\nOptional env vars:\n\n- `SOURCE_BRANCH` (default: `main`)\n- `PUBLIC_BRANCH` (default: `main`)\n- `RELEASE_TAG` (e.g. `v1.0.41`)\n- `RELEASE_TITLE` (e.g. `v1.0.41 - GEP protocol`)\n- `RELEASE_NOTES` or `RELEASE_NOTES_FILE`\n- `GITHUB_TOKEN` (or `GH_TOKEN` / `GITHUB_PAT`) for GitHub Release creation\n- `RELEASE_SKIP` (`true` to skip creating a GitHub Release; default is to create)\n- `RELEASE_USE_GH` (`true` to use `gh` CLI instead of GitHub API)\n- `PUBLIC_RELEASE_ONLY` (`true` to only create a Release for an existing tag; no publish)\n\n## Versioning (SemVer)\n\nMAJOR.MINOR.PATCH\n\n- MAJOR: incompatible changes\n- MINOR: backward-compatible features\n- PATCH: backward-compatible bug fixes\n\n## Changelog\n\n### v1.10.1\n- **Innovation Cooldown**: Track recent innovation targets in `analyzeRecentHistory()` and inject `Context [Innovation Cooldown]` into GEP prompt, preventing the Hand Agent from repeatedly innovating on the same skill/module across consecutive cycles.\n- **Signal Enhancement**: `analyzeRecentHistory()` now returns `recentInnovationTargets` (map of target path to count in last 10 events).\n\n### v1.10.0\n- **Operations Module** (`src/ops/`): 6 portable modules extracted from environment-specific wrapper:\n - `lifecycle.js` -- process start/stop/restart/status/health check\n - `skills_monitor.js` -- skill health audit with auto-heal (npm install, SKILL.md stub)\n - `cleanup.js` -- GEP artifact disk cleanup\n - `trigger.js` -- wake signal mechanism\n - `commentary.js` -- persona-based cycle commentary\n - `self_repair.js` -- git emergency repair (abort rebase, remove stale locks)\n- **Configurable Evolution Strategy** (`EVOLVE_STRATEGY` env var):\n - 4 presets: `balanced` (default 50/30/20), `innovate` (80/15/5), `harden` (20/40/40), `repair-only` (0/20/80)\n - Strategy-aware signal filtering with per-preset repair loop thresholds\n - Backward compatible: `FORCE_INNOVATION=true` maps to `innovate`\n- **Signal De-duplication**: repair ratio check forces innovation when >= 50% of last 8 cycles are repairs (threshold varies by strategy).\n- **Tool Usage Analytics**: detects high-frequency tool usage patterns in logs (auto-evolved by Hand Agent).\n- **Protected Source Files** (GEP Section IX): evolver core .js files listed as immutable to prevent Hand Agent overwrites.\n- **Forbidden Innovation Zones** (GEP Section X): prevents creation of skills that duplicate existing infrastructure (process management, health monitoring, scheduling).\n- **Known Issues List** (GEP Section VII.6): tells the LLM to skip already-fixed errors.\n- **Resilience**: replaced `process.exit(2)` with `throw Error()` for MemoryGraph failures (loop survives transient errors).\n- **Gene Limits Relaxed**: repair max_files 12->20, innovate max_files 8->25.\n- `paths.js`: added `getWorkspaceRoot()`, `getSkillsDir()`, `getLogsDir()`.\n\n### v1.9.2\n- Intermediate release with strategy presets and protected files.\n\n### v1.9.1\n- Signal de-duplication (repair ratio check).\n- Singleton Guard (PID lock file).\n- Environment fingerprint in GEP prompt.\n\n### v1.6.0\n- Add innovation/opportunity signal detection: user_feature_request, user_improvement_suggestion, perf_bottleneck, capability_gap, stable_success_plateau, external_opportunity.\n- Add innovate Gene (gene_gep_innovate_from_opportunity) for proactive feature development.\n- Auto-innovate mutation when opportunity signals are present (no longer requires --drift flag).\n- Personality evolution now responds to opportunity signals by increasing creativity.\n- Safety: repair still takes priority over innovate when errors are present.\n\n### v1.5.1\n- Add containerized vibe testing framework (Docker + node:22-bookworm, OpenClaw-compatible environment).\n- 7 end-to-end tests: module load, dry-run solidify, schema compliance, A2A round-trip, full evolve+solidify, loop gating, env fingerprint.\n- Add internal daemon loop with suicide guard for memory leak protection.\n- One-command test: `npm run test:vibe`.\n\n### v1.5.0\n- Add content-addressable asset IDs (SHA-256 canonical hashing) for deduplication, tamper detection, and cross-node consistency.\n- Add environment fingerprint capture (node version, platform, arch, evolver version) embedded in EvolutionEvents, Capsules, and ValidationReports.\n- Add standardized ValidationReport type with machine-readable schema, full command results, and env fingerprint.\n- Add GEP A2A protocol layer with 6 message types (hello/publish/fetch/report/decision/revoke) and pluggable transport interface.\n- Add FileTransport as default A2A transport (JSONL outbox/inbox).\n- Add asset_id integrity verification on A2A ingest; reject tampered assets.\n- Add schema_version field to all GEP asset types (Gene, Capsule, EvolutionEvent, ValidationReport).\n- Fix: dry-run mode no longer triggers rollback.\n- Merge backport/online-fixes: self-contained crash recovery with recover_loop.js.\n\n### v1.4.4\n- Add validation command safety check: Gene validation commands are gated by prefix whitelist (node/npm/npx) and shell operator blocking.\n- Add validation audit on A2A Gene promotion: external Genes with unsafe validation commands are rejected before promotion.\n- Add Security Model documentation to README.\n\n### v1.4.3\n- Release preparation for v1.4.3.\n\n### v1.4.2\n- Add loop gating: do not start a new cycle until the previous run is solidified (prevents fast empty cycles).\n- Preserve `last_solidify` when writing solidify state (merge instead of overwrite).\n\n### v1.4.1\n- Add execute-by-default bridge: after generating the GEP prompt, emit `sessions_spawn(...)` to spawn an executor agent.\n- Write prompt artifacts to `memory/` for reliable handoff and auditing.\n\n### v1.4.0\n- Add explicit Mutation protocol (repair/optimize/innovate) and require Mutation per evolution run.\n- Add evolvable PersonalityState with small PersonalityMutation steps and natural selection statistics.\n- Extend EvolutionEvent with `mutation_id` and `personality_state`; record both into Memory Graph events.\n- Add `scripts/gep_personality_report.js` to observe personality success rates and convergence.\n\n### v1.3.1\n- Release preparation for v1.3.1.\n\n### v1.3.0\n- Release preparation for v1.3.0.\n\n### v1.2.0\n- Memory Graph v2 and A2A exchange protocol integration.\n\n### v1.1.0\n- Public build/publish pipeline, prompt budget enforcement, and structured GEP asset storage.\n\n## Security Model\n\nThis section describes the execution boundaries and trust model of the Capability Evolver.\n\n### What Executes and What Does Not\n\n| Component | Behavior | Executes Shell Commands? |\n| :--- | :--- | :--- |\n| `src/evolve.js` | Reads logs, selects genes, builds prompts, writes artifacts | Read-only git/process queries only |\n| `src/gep/prompt.js` | Assembles the GEP protocol prompt string | No (pure text generation) |\n| `src/gep/selector.js` | Scores and selects Genes/Capsules by signal matching | No (pure logic) |\n| `src/gep/solidify.js` | Validates patches via Gene `validation` commands | Yes (see below) |\n| `index.js` (loop recovery) | Prints `sessions_spawn(...)` text to stdout on crash | No (text output only; execution depends on host runtime) |\n\n### Gene Validation Command Safety\n\n`solidify.js` executes commands listed in a Gene's `validation` array. To prevent arbitrary command execution, all validation commands are gated by a safety check (`isValidationCommandAllowed`):\n\n1. **Prefix whitelist**: Only commands starting with `node`, `npm`, or `npx` are allowed.\n2. **No command substitution**: Backticks and `$(...)` are rejected anywhere in the command string.\n3. **No shell operators**: After stripping quoted content, `;`, `&`, `|`, `>`, `<` are rejected.\n4. **Timeout**: Each command is limited to 180 seconds.\n5. **Scoped execution**: Commands run with `cwd` set to the repository root.\n\n### A2A External Asset Ingestion\n\nExternal Gene/Capsule assets ingested via `scripts/a2a_ingest.js` are staged in an isolated candidate zone. Promotion to local stores (`scripts/a2a_promote.js`) requires:\n\n1. Explicit `--validated` flag (operator must verify the asset first).\n2. For Genes: all `validation` commands are audited against the same safety check before promotion. Unsafe commands cause the promotion to be rejected.\n3. Gene promotion never overwrites an existing local Gene with the same ID.\n\n### `sessions_spawn` Output\n\nThe `sessions_spawn(...)` strings in `index.js` and `evolve.js` are **text output to stdout**, not direct function calls. Whether they are interpreted depends on the host runtime (e.g., OpenClaw platform). The evolver itself does not invoke `sessions_spawn` as executable code.\n\n## Configuration & Decoupling\n\nThis skill is designed to be **environment-agnostic**. It uses standard OpenClaw tools by default.\n\n### Local Overrides (Injection)\nYou can inject local preferences (e.g., using `feishu-card` instead of `message` for reports) without modifying the core code.\n\n**Method 1: Environment Variables**\nSet `EVOLVE_REPORT_TOOL` in your `.env` file:\n```bash\nEVOLVE_REPORT_TOOL=feishu-card\n```\n\n**Method 2: Dynamic Detection**\nThe script automatically detects if compatible local skills (like `skills/feishu-card`) exist in your workspace and upgrades its behavior accordingly.\n\n## License\n\nMIT\n\n\n",
65 "arguments": null,
66 "icons": null,
67 "meta": null
68 },
69 {
70 "name": "README.zh-CN.md",
71 "title": null,
72 "description": "# \ud83e\uddec Capability Evolver\uff08\u80fd\u529b\u8fdb\u5316\u5f15\u64ce\uff09\n\n[English Docs](README.md)\n\n**\u201c\u8fdb\u5316\u4e0d\u662f\u53ef\u9009\u9879\uff0c\u800c\u662f\u751f\u5b58\u6cd5\u5219\u3002\u201d**\n\n**Capability Evolver** \u662f\u4e00\u4e2a\u5143\u6280\u80fd\uff08Meta-Skill\uff09\uff0c\u8d4b\u4e88 OpenClaw \u667a\u80fd\u4f53\u81ea\u6211\u53cd\u7701\u7684\u80fd\u529b\u3002\u5b83\u53ef\u4ee5\u626b\u63cf\u81ea\u8eab\u7684\u8fd0\u884c\u65e5\u5fd7\uff0c\u8bc6\u522b\u6548\u7387\u4f4e\u4e0b\u6216\u62a5\u9519\u7684\u5730\u65b9\uff0c\u5e76\u81ea\u4e3b\u7f16\u5199\u4ee3\u7801\u8865\u4e01\u6765\u4f18\u5316\u81ea\u8eab\u6027\u80fd\u3002\n\n\u672c\u4ed3\u5e93\u5185\u7f6e **\u57fa\u56e0\u7ec4\u8fdb\u5316\u534f\u8bae\uff08Genome Evolution Protocol, GEP\uff09**\uff0c\u7528\u4e8e\u5c06\u6bcf\u6b21\u8fdb\u5316\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\uff0c\u964d\u4f4e\u540e\u7eed\u540c\u7c7b\u95ee\u9898\u7684\u63a8\u7406\u6210\u672c\u3002\n\n## \u6838\u5fc3\u7279\u6027\n\n- **\u81ea\u52a8\u65e5\u5fd7\u5206\u6790**\uff1a\u81ea\u52a8\u626b\u63cf `.jsonl` \u4f1a\u8bdd\u65e5\u5fd7\uff0c\u5bfb\u627e\u9519\u8bef\u6a21\u5f0f\u3002\n- **\u81ea\u6211\u4fee\u590d**\uff1a\u68c0\u6d4b\u8fd0\u884c\u65f6\u5d29\u6e83\u5e76\u7f16\u5199\u4fee\u590d\u8865\u4e01\u3002\n- **GEP \u534f\u8bae**\uff1a\u6807\u51c6\u5316\u8fdb\u5316\u6d41\u7a0b\u4e0e\u53ef\u590d\u7528\u8d44\u4ea7\uff0c\u652f\u6301\u53ef\u5ba1\u8ba1\u4e0e\u53ef\u5171\u4eab\u3002\n- **\u7a81\u53d8\u534f\u8bae\u4e0e\u4eba\u683c\u8fdb\u5316**\uff1a\u6bcf\u6b21\u8fdb\u5316\u5fc5\u987b\u663e\u5f0f\u58f0\u660e Mutation\uff0c\u5e76\u7ef4\u62a4\u53ef\u8fdb\u5316\u7684 PersonalityState\u3002\n- **\u53ef\u914d\u7f6e\u8fdb\u5316\u7b56\u7565**\uff1a\u901a\u8fc7 `EVOLVE_STRATEGY` \u73af\u5883\u53d8\u91cf\u9009\u62e9 `balanced`/`innovate`/`harden`/`repair-only` \u6a21\u5f0f\uff0c\u63a7\u5236\u4fee\u590d/\u4f18\u5316/\u521b\u65b0\u7684\u6bd4\u4f8b\u3002\n- **\u4fe1\u53f7\u53bb\u91cd**\uff1a\u81ea\u52a8\u68c0\u6d4b\u4fee\u590d\u5faa\u73af\uff0c\u9632\u6b62\u53cd\u590d\u4fee\u540c\u4e00\u4e2a\u95ee\u9898\u3002\n- **\u8fd0\u7ef4\u6a21\u5757** (`src/ops/`)\uff1a6 \u4e2a\u53ef\u79fb\u690d\u7684\u8fd0\u7ef4\u5de5\u5177\uff08\u751f\u547d\u5468\u671f\u7ba1\u7406\u3001\u6280\u80fd\u5065\u5eb7\u76d1\u63a7\u3001\u78c1\u76d8\u6e05\u7406\u3001Git \u81ea\u4fee\u590d\u7b49\uff09\uff0c\u96f6\u5e73\u53f0\u4f9d\u8d56\u3002\n- **\u6e90\u7801\u4fdd\u62a4**\uff1a\u9632\u6b62\u81ea\u6cbb\u4ee3\u7406\u8986\u5199\u6838\u5fc3\u8fdb\u5316\u5f15\u64ce\u6e90\u7801\u3002\n- **\u52a8\u6001\u96c6\u6210**\uff1a\u81ea\u52a8\u68c0\u6d4b\u5e76\u4f7f\u7528\u672c\u5730\u5de5\u5177\uff0c\u5982\u679c\u4e0d\u5b58\u5728\u5219\u56de\u9000\u5230\u901a\u7528\u6a21\u5f0f\u3002\n- **\u6301\u7eed\u5faa\u73af\u6a21\u5f0f**\uff1a\u6301\u7eed\u8fd0\u884c\u7684\u81ea\u6211\u8fdb\u5316\u5faa\u73af\u3002\n\n## \u4f7f\u7528\u65b9\u6cd5\n\n### \u6807\u51c6\u8fd0\u884c\uff08\u81ea\u52a8\u5316\uff09\n```bash\nnode index.js\n```\n\n### \u5ba1\u67e5\u6a21\u5f0f\uff08\u4eba\u5de5\u4ecb\u5165\uff09\n\u5728\u5e94\u7528\u66f4\u6539\u524d\u6682\u505c\uff0c\u7b49\u5f85\u4eba\u5de5\u786e\u8ba4\u3002\n```bash\nnode index.js --review\n```\n\n### \u6301\u7eed\u5faa\u73af\uff08\u5b88\u62a4\u8fdb\u7a0b\uff09\n\u65e0\u9650\u5faa\u73af\u8fd0\u884c\u3002\u9002\u5408\u4f5c\u4e3a\u540e\u53f0\u670d\u52a1\u3002\n```bash\nnode index.js --loop\n```\n\n### \u6307\u5b9a\u8fdb\u5316\u7b56\u7565\n```bash\nEVOLVE_STRATEGY=innovate node index.js --loop # \u6700\u5927\u5316\u521b\u65b0\nEVOLVE_STRATEGY=harden node index.js --loop # \u805a\u7126\u7a33\u5b9a\u6027\nEVOLVE_STRATEGY=repair-only node index.js --loop # \u7d27\u6025\u4fee\u590d\u6a21\u5f0f\n```\n\n| \u7b56\u7565 | \u521b\u65b0 | \u4f18\u5316 | \u4fee\u590d | \u9002\u7528\u573a\u666f |\n| :--- | :--- | :--- | :--- | :--- |\n| `balanced`\uff08\u9ed8\u8ba4\uff09 | 50% | 30% | 20% | \u65e5\u5e38\u8fd0\u884c\uff0c\u7a33\u6b65\u6210\u957f |\n| `innovate` | 80% | 15% | 5% | \u7cfb\u7edf\u7a33\u5b9a\uff0c\u5feb\u901f\u51fa\u65b0\u529f\u80fd |\n| `harden` | 20% | 40% | 40% | \u5927\u6539\u52a8\u540e\uff0c\u805a\u7126\u7a33\u56fa |\n| `repair-only` | 0% | 20% | 80% | \u7d27\u6025\u72b6\u6001\uff0c\u5168\u529b\u4fee\u590d |\n\n### \u8fd0\u7ef4\u7ba1\u7406\uff08\u751f\u547d\u5468\u671f\uff09\n```bash\nnode src/ops/lifecycle.js start # \u540e\u53f0\u542f\u52a8\u8fdb\u5316\u5faa\u73af\nnode src/ops/lifecycle.js stop # \u4f18\u96c5\u505c\u6b62\uff08SIGTERM -> SIGKILL\uff09\nnode src/ops/lifecycle.js status # \u67e5\u770b\u8fd0\u884c\u72b6\u6001\nnode src/ops/lifecycle.js check # \u5065\u5eb7\u68c0\u67e5 + \u505c\u6ede\u81ea\u52a8\u91cd\u542f\n```\n\n## \u5178\u578b\u4f7f\u7528\u573a\u666f\n\n- \u9700\u8981\u5ba1\u8ba1\u4e0e\u53ef\u8ffd\u8e2a\u7684\u63d0\u793a\u8bcd\u6f14\u8fdb\n- \u56e2\u961f\u534f\u4f5c\u7ef4\u62a4 Agent \u7684\u957f\u671f\u80fd\u529b\n- \u5e0c\u671b\u5c06\u4fee\u590d\u7ecf\u9a8c\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\n\n## \u53cd\u4f8b\n\n- \u4e00\u6b21\u6027\u811a\u672c\u6216\u6ca1\u6709\u65e5\u5fd7\u7684\u573a\u666f\n- \u9700\u8981\u5b8c\u5168\u81ea\u7531\u53d1\u6325\u7684\u6539\u52a8\n- \u65e0\u6cd5\u63a5\u53d7\u534f\u8bae\u7ea6\u675f\u7684\u7cfb\u7edf\n\n## GEP \u534f\u8bae\uff08\u53ef\u5ba1\u8ba1\u8fdb\u5316\uff09\n\n\u672c\u4ed3\u5e93\u5185\u7f6e\u57fa\u4e8e GEP \u7684\u201c\u534f\u8bae\u53d7\u9650\u63d0\u793a\u8bcd\u6a21\u5f0f\u201d\uff0c\u7528\u4e8e\u628a\u6bcf\u6b21\u8fdb\u5316\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\u3002\n\n- **\u7ed3\u6784\u5316\u8d44\u4ea7\u76ee\u5f55**\uff1a`assets/gep/`\n - `assets/gep/genes.json`\n - `assets/gep/capsules.json`\n - `assets/gep/events.jsonl`\n- **Selector \u9009\u62e9\u5668**\uff1a\u6839\u636e\u65e5\u5fd7\u63d0\u53d6 signals\uff0c\u4f18\u5148\u590d\u7528\u5df2\u6709 Gene/Capsule\uff0c\u5e76\u5728\u63d0\u793a\u8bcd\u4e2d\u8f93\u51fa\u53ef\u5ba1\u8ba1\u7684 Selector \u51b3\u7b56 JSON\u3002\n- **\u7ea6\u675f**\uff1a\u9664 \ud83e\uddec \u5916\uff0c\u7981\u6b62\u4f7f\u7528\u5176\u4ed6 emoji\u3002\n\n## \u914d\u7f6e\u4e0e\u89e3\u8026\n\n\u672c\u63d2\u4ef6\u80fd\u81ea\u52a8\u9002\u5e94\u4f60\u7684\u73af\u5883\u3002\n\n| \u73af\u5883\u53d8\u91cf | \u63cf\u8ff0 | \u9ed8\u8ba4\u503c |\n| :--- | :--- | :--- |\n| `EVOLVE_STRATEGY` | \u8fdb\u5316\u7b56\u7565\u9884\u8bbe | `balanced` |\n| `EVOLVE_REPORT_TOOL` | \u7528\u4e8e\u62a5\u544a\u7ed3\u679c\u7684\u5de5\u5177\u540d\u79f0 | `message` |\n| `MEMORY_DIR` | \u8bb0\u5fc6\u6587\u4ef6\u8def\u5f84 | `./memory` |\n| `OPENCLAW_WORKSPACE` | \u5de5\u4f5c\u533a\u6839\u8def\u5f84 | \u81ea\u52a8\u68c0\u6d4b |\n| `EVOLVER_LOOP_SCRIPT` | \u5faa\u73af\u542f\u52a8\u811a\u672c\u8def\u5f84 | \u81ea\u52a8\u68c0\u6d4b wrapper \u6216 core |\n\n## Public \u53d1\u5e03\n\n\u672c\u4ed3\u5e93\u4e3a\u516c\u5f00\u53d1\u884c\u7248\u672c\u3002\n\n- \u6784\u5efa\u516c\u5f00\u4ea7\u7269\uff1a`npm run build`\n- \u53d1\u5e03\u516c\u5f00\u4ea7\u7269\uff1a`npm run publish:public`\n- \u6f14\u7ec3\uff1a`DRY_RUN=true npm run publish:public`\n\n\u5fc5\u586b\u73af\u5883\u53d8\u91cf\uff1a\n\n- `PUBLIC_REMOTE`\uff08\u9ed8\u8ba4\uff1a`public`\uff09\n- `PUBLIC_REPO`\uff08\u4f8b\u5982 `autogame-17/evolver`\uff09\n- `PUBLIC_OUT_DIR`\uff08\u9ed8\u8ba4\uff1a`dist-public`\uff09\n- `PUBLIC_USE_BUILD_OUTPUT`\uff08\u9ed8\u8ba4\uff1a`true`\uff09\n\n\u53ef\u9009\u73af\u5883\u53d8\u91cf\uff1a\n\n- `SOURCE_BRANCH`\uff08\u9ed8\u8ba4\uff1a`main`\uff09\n- `PUBLIC_BRANCH`\uff08\u9ed8\u8ba4\uff1a`main`\uff09\n- `RELEASE_TAG`\uff08\u4f8b\u5982 `v1.0.41`\uff09\n- `RELEASE_TITLE`\uff08\u4f8b\u5982 `v1.0.41 - GEP protocol`\uff09\n- `RELEASE_NOTES` \u6216 `RELEASE_NOTES_FILE`\n- `GITHUB_TOKEN`\uff08\u6216 `GH_TOKEN` / `GITHUB_PAT`\uff0c\u7528\u4e8e\u521b\u5efa GitHub Release\uff09\n- `RELEASE_SKIP`\uff08`true` \u5219\u8df3\u8fc7\u521b\u5efa GitHub Release\uff1b\u9ed8\u8ba4\u4f1a\u521b\u5efa\uff09\n- `RELEASE_USE_GH`\uff08`true` \u5219\u4f7f\u7528 `gh` CLI\uff0c\u5426\u5219\u9ed8\u8ba4\u8d70 GitHub API\uff09\n- `PUBLIC_RELEASE_ONLY`\uff08`true` \u5219\u4ec5\u4e3a\u5df2\u5b58\u5728\u7684 tag \u521b\u5efa Release\uff1b\u4e0d\u53d1\u5e03\u4ee3\u7801\uff09\n\n## \u7248\u672c\u53f7\u89c4\u5219\uff08SemVer\uff09\n\nMAJOR.MINOR.PATCH\n\n\u2022 MAJOR\uff08\u4e3b\u7248\u672c\uff09\uff1a\u6709\u4e0d\u517c\u5bb9\u53d8\u66f4 \n\u2022 MINOR\uff08\u6b21\u7248\u672c\uff09\uff1a\u5411\u540e\u517c\u5bb9\u7684\u65b0\u529f\u80fd \n\u2022 PATCH\uff08\u4fee\u8ba2/\u8865\u4e01\uff09\uff1a\u5411\u540e\u517c\u5bb9\u7684\u95ee\u9898\u4fee\u590d\n\n## \u66f4\u65b0\u65e5\u5fd7\n\n### v1.10.1\n- **\u521b\u65b0\u51b7\u5374 (Innovation Cooldown)**\uff1a\u5728 `analyzeRecentHistory()` \u4e2d\u8ffd\u8e2a\u8fd1\u671f\u521b\u65b0\u76ee\u6807\uff0c\u5e76\u5728 GEP \u63d0\u793a\u8bcd\u4e2d\u6ce8\u5165 `Context [Innovation Cooldown]` \u6bb5\uff0c\u9632\u6b62 Hand Agent \u5728\u8fde\u7eed\u5468\u671f\u4e2d\u53cd\u590d\u5bf9\u540c\u4e00\u6280\u80fd/\u6a21\u5757\u8fdb\u884c\u521b\u65b0\u3002\n- **\u4fe1\u53f7\u589e\u5f3a**\uff1a`analyzeRecentHistory()` \u65b0\u589e `recentInnovationTargets` \u8fd4\u56de\u503c\uff08\u76ee\u6807\u8def\u5f84\u5230\u6700\u8fd1 10 \u8f6e\u51fa\u73b0\u6b21\u6570\u7684\u6620\u5c04\uff09\u3002\n\n### v1.10.0\n- **\u8fd0\u7ef4\u6a21\u5757** (`src/ops/`)\uff1a\u4ece\u73af\u5883\u76f8\u5173\u7684 wrapper \u4e2d\u63d0\u53d6 6 \u4e2a\u53ef\u79fb\u690d\u6a21\u5757\uff1a\n - `lifecycle.js` -- \u8fdb\u7a0b\u542f\u505c/\u91cd\u542f/\u72b6\u6001/\u5065\u5eb7\u68c0\u67e5\n - `skills_monitor.js` -- \u6280\u80fd\u5065\u5eb7\u5ba1\u8ba1 + \u81ea\u52a8\u4fee\u590d\uff08npm install\u3001SKILL.md \u751f\u6210\uff09\n - `cleanup.js` -- GEP \u4ea7\u7269\u78c1\u76d8\u6e05\u7406\n - `trigger.js` -- \u5524\u9192\u4fe1\u53f7\u673a\u5236\n - `commentary.js` -- \u4eba\u683c\u5316\u5468\u671f\u8bc4\u8bba\n - `self_repair.js` -- Git \u7d27\u6025\u4fee\u590d\uff08\u7ec8\u6b62 rebase\u3001\u6e05\u7406\u8fc7\u671f\u9501\u6587\u4ef6\uff09\n- **\u53ef\u914d\u7f6e\u8fdb\u5316\u7b56\u7565** (`EVOLVE_STRATEGY` \u73af\u5883\u53d8\u91cf)\uff1a\n - 4 \u4e2a\u9884\u8bbe\uff1a`balanced`\uff08\u9ed8\u8ba4 50/30/20\uff09\u3001`innovate`\uff0880/15/5\uff09\u3001`harden`\uff0820/40/40\uff09\u3001`repair-only`\uff080/20/80\uff09\n - \u7b56\u7565\u611f\u77e5\u7684\u4fe1\u53f7\u8fc7\u6ee4\uff0c\u5404\u9884\u8bbe\u6709\u72ec\u7acb\u7684\u4fee\u590d\u5faa\u73af\u9608\u503c\n - \u5411\u540e\u517c\u5bb9\uff1a`FORCE_INNOVATION=true` \u7b49\u4ef7\u4e8e `innovate`\n- **\u4fe1\u53f7\u53bb\u91cd**\uff1a\u5f53\u6700\u8fd1 8 \u8f6e\u4e2d\u4fee\u590d\u5360\u6bd4 >= 50% \u65f6\u5f3a\u5236\u521b\u65b0\uff08\u9608\u503c\u968f\u7b56\u7565\u53d8\u5316\uff09\n- **\u5de5\u5177\u4f7f\u7528\u5206\u6790**\uff1a\u68c0\u6d4b\u65e5\u5fd7\u4e2d\u7684\u9ad8\u9891\u5de5\u5177\u4f7f\u7528\u6a21\u5f0f\uff08\u7531 Hand Agent \u81ea\u52a8\u8fdb\u5316\u4ea7\u51fa\uff09\n- **\u6e90\u7801\u4fdd\u62a4**\uff08GEP Section IX\uff09\uff1a\u6838\u5fc3 .js \u6587\u4ef6\u5217\u4e3a\u4e0d\u53ef\u4fee\u6539\uff0c\u9632\u6b62 Hand Agent \u8986\u5199\n- **\u7981\u6b62\u521b\u65b0\u533a**\uff08GEP Section X\uff09\uff1a\u9632\u6b62\u521b\u5efa\u4e0e\u5df2\u6709\u57fa\u7840\u8bbe\u65bd\u91cd\u590d\u7684\u6280\u80fd\uff08\u8fdb\u7a0b\u7ba1\u7406\u3001\u5065\u5eb7\u76d1\u63a7\u3001\u5b9a\u65f6\u4efb\u52a1\u7b49\uff09\n- **\u5df2\u77e5\u95ee\u9898\u6e05\u5355**\uff08GEP Section VII.6\uff09\uff1a\u544a\u77e5 LLM \u8df3\u8fc7\u5df2\u4fee\u590d\u7684\u9519\u8bef\n- **\u9c81\u68d2\u6027\u63d0\u5347**\uff1aMemoryGraph \u6545\u969c\u65f6 `process.exit(2)` \u6539\u4e3a `throw Error()`\uff08\u5faa\u73af\u4e0d\u518d\u56e0\u77ac\u6001\u9519\u8bef\u5d29\u6e83\uff09\n- **Gene \u9650\u5236\u653e\u5bbd**\uff1arepair max_files 12->20\uff0cinnovate max_files 8->25\n- `paths.js` \u65b0\u589e `getWorkspaceRoot()`\u3001`getSkillsDir()`\u3001`getLogsDir()`\n\n### v1.9.2\n- \u4e2d\u95f4\u7248\u672c\uff0c\u5305\u542b\u7b56\u7565\u9884\u8bbe\u548c\u6e90\u7801\u4fdd\u62a4\u673a\u5236\u3002\n\n### v1.9.1\n- \u4fe1\u53f7\u53bb\u91cd\uff08\u4fee\u590d\u6bd4\u7387\u68c0\u67e5\uff09\n- \u5355\u4f8b\u9501\uff08PID \u9501\u6587\u4ef6\uff09\n- GEP \u63d0\u793a\u8bcd\u4e2d\u6ce8\u5165\u73af\u5883\u6307\u7eb9\n\n### v1.4.4\n- \u589e\u52a0 validation \u547d\u4ee4\u5b89\u5168\u68c0\u67e5\uff1aGene validation \u547d\u4ee4\u6267\u884c\u524d\u901a\u8fc7\u524d\u7f00\u767d\u540d\u5355\uff08node/npm/npx\uff09\u548c shell \u64cd\u4f5c\u7b26\u62e6\u622a\u8fdb\u884c\u95e8\u63a7\u3002\n- \u589e\u52a0 A2A Gene \u63d0\u5347\u5ba1\u67e5\uff1a\u5916\u90e8 Gene \u7684 validation \u547d\u4ee4\u4e0d\u5b89\u5168\u65f6\u62d2\u7edd\u63d0\u5347\u3002\n- \u589e\u52a0\u5b89\u5168\u6a21\u578b\u6587\u6863\u3002\n\n### v1.4.3\n- v1.4.3 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.4.2\n- \u589e\u52a0 loop \u95e8\u63a7\uff1a\u4e0a\u4e00\u8f6e\u672a\u5b8c\u6210 solidify \u65f6\uff0c\u4e0d\u542f\u52a8\u65b0\u4e00\u8f6e\uff08\u907f\u514d wrapper \u9020\u6210\u8d85\u5feb\u7a7a\u8f6c\uff09\u3002\n- \u4fee\u590d\u56fa\u5316\u72b6\u6001\u5199\u5165\u8986\u76d6\u95ee\u9898\uff1a\u5199\u5165 last_run \u65f6\u5408\u5e76\u4fdd\u7559 last_solidify\u3002\n\n### v1.4.1\n- \u589e\u52a0\u9ed8\u8ba4\u6267\u884c\u6865\u63a5\uff1a\u751f\u6210 GEP prompt \u540e\u8f93\u51fa `sessions_spawn(...)`\uff0c\u81ea\u52a8\u6d3e\u53d1\u6267\u884c\u578b\u5b50\u667a\u80fd\u4f53\u3002\n- \u5c06 prompt \u4f5c\u4e3a\u4ea4\u63a5\u5de5\u4ef6\u5199\u5165 `memory/`\uff0c\u4fbf\u4e8e\u7a33\u5b9a\u4ea4\u63a5\u4e0e\u5ba1\u8ba1\u56de\u653e\u3002\n\n### v1.4.0\n- \u589e\u52a0\u663e\u5f0f Mutation Protocol\uff08repair/optimize/innovate\uff09\uff0c\u6bcf\u8f6e\u8fdb\u5316\u5fc5\u987b\u751f\u6210 Mutation \u5bf9\u8c61\u5e76\u901a\u8fc7\u5b89\u5168\u7ea6\u675f\u95e8\u63a7\u3002\n- \u589e\u52a0 Personality Evolution\uff1a\u7ef4\u62a4 PersonalityState\uff0c\u5c0f\u5e45 PersonalityMutation\uff08\u5355\u6b21\u4e0d\u8d85\u8fc7 \u00b10.2\uff0c\u6700\u591a 2 \u4e2a\u53c2\u6570\uff09\uff0c\u5e76\u57fa\u4e8e\u6210\u529f\u7387\u505a\u81ea\u7136\u9009\u62e9\u6536\u655b\u3002\n- EvolutionEvent \u589e\u52a0 `mutation_id` \u4e0e `personality_state` \u5b57\u6bb5\uff1bMemory Graph \u540c\u6b65\u8bb0\u5f55 Mutation \u4e0e Personality \u7684\u56e0\u679c\u94fe\u8def\u3002\n- \u65b0\u589e `scripts/gep_personality_report.js`\uff0c\u7528\u4e8e\u7edf\u8ba1\u4e0d\u540c\u4eba\u683c\u914d\u7f6e\u4e0b\u7684\u6210\u529f\u7387\u5dee\u5f02\u4e0e\u6536\u655b\u8d8b\u52bf\u3002\n\n### v1.3.1\n- v1.3.1 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.3.0\n- v1.3.0 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.2.0\n- Memory Graph v2 \u4e0e A2A \u8fdb\u5316\u8d44\u4ea7\u4ea4\u6362\u96c6\u6210\u3002\n\n### v1.1.0\n- public \u6784\u5efa/\u53d1\u5e03\u6d41\u6c34\u7ebf\u3001\u63d0\u793a\u8bcd\u9884\u7b97\u63a7\u5236\u4e0e\u7ed3\u6784\u5316 GEP \u8d44\u4ea7\u6301\u4e45\u5316\u3002\n\n## \u5b89\u5168\u6a21\u578b\n\n\u672c\u8282\u63cf\u8ff0 Capability Evolver \u7684\u6267\u884c\u8fb9\u754c\u548c\u4fe1\u4efb\u6a21\u578b\u3002\n\n### \u5404\u7ec4\u4ef6\u6267\u884c\u884c\u4e3a\n\n| \u7ec4\u4ef6 | \u884c\u4e3a | \u662f\u5426\u6267\u884c Shell \u547d\u4ee4 |\n| :--- | :--- | :--- |\n| `src/evolve.js` | \u8bfb\u53d6\u65e5\u5fd7\u3001\u9009\u62e9 Gene\u3001\u6784\u5efa\u63d0\u793a\u8bcd\u3001\u5199\u5165\u5de5\u4ef6 | \u4ec5\u53ea\u8bfb git/\u8fdb\u7a0b\u67e5\u8be2 |\n| `src/gep/prompt.js` | \u7ec4\u88c5 GEP \u534f\u8bae\u63d0\u793a\u8bcd\u5b57\u7b26\u4e32 | \u5426\uff08\u7eaf\u6587\u672c\u751f\u6210\uff09 |\n| `src/gep/selector.js` | \u6309\u4fe1\u53f7\u5339\u914d\u5bf9 Gene/Capsule \u8bc4\u5206\u548c\u9009\u62e9 | \u5426\uff08\u7eaf\u903b\u8f91\uff09 |\n| `src/gep/solidify.js` | \u901a\u8fc7 Gene `validation` \u547d\u4ee4\u9a8c\u8bc1\u8865\u4e01 | \u662f\uff08\u89c1\u4e0b\u6587\uff09 |\n| `index.js`\uff08\u5faa\u73af\u6062\u590d\uff09 | \u5d29\u6e83\u65f6\u5411 stdout \u8f93\u51fa `sessions_spawn(...)` \u6587\u672c | \u5426\uff08\u7eaf\u6587\u672c\u8f93\u51fa\uff1b\u662f\u5426\u6267\u884c\u53d6\u51b3\u4e8e\u5bbf\u4e3b\u8fd0\u884c\u65f6\uff09 |\n\n### Gene Validation \u547d\u4ee4\u5b89\u5168\u673a\u5236\n\n`solidify.js` \u6267\u884c Gene \u7684 `validation` \u6570\u7ec4\u4e2d\u7684\u547d\u4ee4\u3002\u4e3a\u9632\u6b62\u4efb\u610f\u547d\u4ee4\u6267\u884c\uff0c\u6240\u6709 validation \u547d\u4ee4\u5728\u6267\u884c\u524d\u5fc5\u987b\u901a\u8fc7\u5b89\u5168\u68c0\u67e5\uff08`isValidationCommandAllowed`\uff09\uff1a\n\n1. **\u524d\u7f00\u767d\u540d\u5355**\uff1a\u4ec5\u5141\u8bb8\u4ee5 `node`\u3001`npm` \u6216 `npx` \u5f00\u5934\u7684\u547d\u4ee4\u3002\n2. **\u7981\u6b62\u547d\u4ee4\u66ff\u6362**\uff1a\u547d\u4ee4\u4e2d\u4efb\u4f55\u4f4d\u7f6e\u51fa\u73b0\u53cd\u5f15\u53f7\u6216 `$(...)` \u5747\u88ab\u62d2\u7edd\u3002\n3. **\u7981\u6b62 Shell \u64cd\u4f5c\u7b26**\uff1a\u53bb\u9664\u5f15\u53f7\u5185\u5bb9\u540e\uff0c`;`\u3001`&`\u3001`|`\u3001`>`\u3001`<` \u5747\u88ab\u62d2\u7edd\u3002\n4. **\u8d85\u65f6\u9650\u5236**\uff1a\u6bcf\u6761\u547d\u4ee4\u9650\u65f6 180 \u79d2\u3002\n5. **\u4f5c\u7528\u57df\u9650\u5b9a**\uff1a\u547d\u4ee4\u4ee5\u4ed3\u5e93\u6839\u76ee\u5f55\u4e3a\u5de5\u4f5c\u76ee\u5f55\u6267\u884c\u3002\n\n### A2A \u5916\u90e8\u8d44\u4ea7\u6444\u5165\n\n\u901a\u8fc7 `scripts/a2a_ingest.js` \u6444\u5165\u7684\u5916\u90e8 Gene/Capsule \u8d44\u4ea7\u88ab\u6682\u5b58\u5728\u9694\u79bb\u7684\u5019\u9009\u533a\u3002\u63d0\u5347\u5230\u672c\u5730\u5b58\u50a8\uff08`scripts/a2a_promote.js`\uff09\u9700\u8981\uff1a\n\n1. \u663e\u5f0f\u4f20\u5165 `--validated` \u6807\u5fd7\uff08\u64cd\u4f5c\u8005\u5fc5\u987b\u5148\u9a8c\u8bc1\u8d44\u4ea7\uff09\u3002\n2. \u5bf9 Gene\uff1a\u63d0\u5347\u524d\u5ba1\u67e5\u6240\u6709 `validation` \u547d\u4ee4\uff0c\u4e0d\u5b89\u5168\u7684\u547d\u4ee4\u4f1a\u5bfc\u81f4\u63d0\u5347\u88ab\u62d2\u7edd\u3002\n3. Gene \u63d0\u5347\u4e0d\u4f1a\u8986\u76d6\u672c\u5730\u5df2\u5b58\u5728\u7684\u540c ID Gene\u3002\n\n### `sessions_spawn` \u8f93\u51fa\n\n`index.js` \u548c `evolve.js` \u4e2d\u7684 `sessions_spawn(...)` \u5b57\u7b26\u4e32\u662f**\u8f93\u51fa\u5230 stdout \u7684\u7eaf\u6587\u672c**\uff0c\u800c\u975e\u76f4\u63a5\u51fd\u6570\u8c03\u7528\u3002\u662f\u5426\u88ab\u6267\u884c\u53d6\u51b3\u4e8e\u5bbf\u4e3b\u8fd0\u884c\u65f6\uff08\u5982 OpenClaw \u5e73\u53f0\uff09\u3002\u8fdb\u5316\u5f15\u64ce\u672c\u8eab\u4e0d\u5c06 `sessions_spawn` \u4f5c\u4e3a\u53ef\u6267\u884c\u4ee3\u7801\u8c03\u7528\u3002\n\n### \u5176\u4ed6\u5b89\u5168\u7ea6\u675f\n\n1. **\u5355\u8fdb\u7a0b\u9501**\uff1a\u8fdb\u5316\u5f15\u64ce\u7981\u6b62\u751f\u6210\u5b50\u8fdb\u5316\u8fdb\u7a0b\uff08\u9632\u6b62 Fork \u70b8\u5f39\uff09\u3002\n2. **\u7a33\u5b9a\u6027\u4f18\u5148**\uff1a\u5982\u679c\u8fd1\u671f\u9519\u8bef\u7387\u8f83\u9ad8\uff0c\u5f3a\u5236\u8fdb\u5165\u4fee\u590d\u6a21\u5f0f\uff0c\u6682\u505c\u521b\u65b0\u529f\u80fd\u3002\n3. **\u73af\u5883\u68c0\u6d4b**\uff1a\u5916\u90e8\u96c6\u6210\uff08\u5982 Git \u540c\u6b65\uff09\u4ec5\u5728\u68c0\u6d4b\u5230\u76f8\u5e94\u63d2\u4ef6\u5b58\u5728\u65f6\u624d\u4f1a\u542f\u7528\u3002\n\n## \u8bb8\u53ef\u8bc1\nMIT\n",
73 "arguments": null,
74 "icons": null,
75 "meta": null
76 }
77 ],
78 "resources": [
79 {
80 "name": "capsules.json",
81 "title": null,
82 "uri": "skill://assets/gep/capsules.json",
83 "description": "{\n \"version\": 1,\n \"capsules\": [\n {\n \"type\": \"Capsule\",\n \"schema_version\": \"1.5.0\",\n \"id\": \"capsule_1770477654236\",\n \"trigger\": [\n \"log_error\",\n \"errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }\",\n \"user_missing\",\n \"windows_shell_incompatible\",\n \"perf_bottleneck\"\n ],\n \"gene\": \"gene_gep_repair_from_errors\",\n \"summary\": \"\u56fa\u5316\uff1agene_gep_repair_from_errors \u547d\u4e2d\u4fe1\u53f7 log_error, errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }, user_missing, windows_shell_incompatible, perf_bottleneck\uff0c\u53d8\u66f4 1 \u6587\u4ef6 / 2 \u884c\u3002\",\n \"confidence\": 0.85,\n \"blast_radius\": {\n \"files\": 1,\n \"lines\": 2\n },\n \"outcome\": {\n \"status\": \"success\",\n \"score\": 0.85\n },\n \"success_streak\": 1,\n \"env_fingerprint\": {\n \"node_version\": \"v22.22.0\",\n \"platform\": \"linux\",\n \"arch\": \"x64\",\n \"os_release\": \"6.1.0-42-cloud-amd64\",\n \"evolver_version\": \"1.7.0\",\n \"cwd\": \"/home/crishaocredits/.openclaw/workspace\",\n \"captured_at\": \"2026-02-07T15:20:54.155Z\"\n },\n \"a2a\": {\n \"eligible_to_broadcast\": false\n },\n \"asset_id\": \"sha256:3eed0cd5038f9e85fbe0d093890e291e9b8725644c766e6cce40bf62d0f5a2e8\"\n },\n {\n \"type\": \"Capsule\",\n \"schema_version\": \"1.5.0\",\n \"id\": \"capsule_1770478341769\",\n \"trigger\": [\n \"log_error\",\n \"errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }\",\n \"user_missing\",\n \"windows_shell_incompatible\",\n \"perf_bottleneck\"\n ],\n \"gene\": \"gene_gep_repair_from_errors\",\n \"summary\": \"\u56fa\u5316\uff1agene_gep_repair_from_errors \u547d\u4e2d\u4fe1\u53f7 log_error, errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }, user_missing, windows_shell_incompatible, perf_bottleneck\uff0c\u53d8\u66f4 2 \u6587\u4ef6 / 44 \u884c\u3002\",\n \"confidence\": 0.85,\n \"blast_radius\": {\n \"files\": 2,\n \"lines\": 44\n },\n \"outcome\": {\n \"status\": \"success\",\n \"score\": 0.85\n },\n \"success_streak\": 1,\n \"env_fingerprint\": {\n \"node_version\": \"v22.22.0\",\n \"platform\": \"linux\",\n \"arch\": \"x64\",\n \"os_release\": \"6.1.0-42-cloud-amd64\",\n \"evolver_version\": \"1.7.0\",\n \"cwd\": \"/home/crishaocredits/.openclaw/workspace\",\n \"captured_at\": \"2026-02-07T15:32:21.678Z\"\n },\n \"a2a\": {\n \"eligible_to_broadcast\": false\n },\n \"asset_id\": \"sha256:20d971a3c4cb2b75f9c045376d1aa003361c12a6b89a4b47b7e81dbd4f4d8fe8\"\n }\n ]\n}\n",
84 "mimeType": null,
85 "size": null,
86 "icons": null,
87 "annotations": null,
88 "meta": null
89 },
90 {
91 "name": "genes.json",
92 "title": null,
93 "uri": "skill://assets/gep/genes.json",
94 "description": "{\n \"version\": 1,\n \"genes\": [\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_repair_from_errors\",\n \"category\": \"repair\",\n \"signals_match\": [\n \"error\",\n \"exception\",\n \"failed\",\n \"unstable\"\n ],\n \"preconditions\": [\n \"signals contains error-related indicators\"\n ],\n \"strategy\": [\n \"Extract structured signals from logs and user instructions\",\n \"Select an existing Gene by signals match (no improvisation)\",\n \"Estimate blast radius (files, lines) before editing\",\n \"Apply smallest reversible patch\",\n \"Validate using declared validation steps; rollback on failure\",\n \"Solidify knowledge: append EvolutionEvent, update Gene/Capsule store\"\n ],\n \"constraints\": {\n \"max_files\": 20,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/solidify'); console.log('ok')\\\"\",\n \"node -e \\\"require('./src/gep/selector'); require('./src/gep/memoryGraph'); console.log('ok')\\\"\"\n ]\n },\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_optimize_prompt_and_assets\",\n \"category\": \"optimize\",\n \"signals_match\": [\n \"protocol\",\n \"gep\",\n \"prompt\",\n \"audit\",\n \"reusable\"\n ],\n \"preconditions\": [\n \"need stricter, auditable evolution protocol outputs\"\n ],\n \"strategy\": [\n \"Extract signals and determine selection rationale via Selector JSON\",\n \"Prefer reusing existing Gene/Capsule; only create if no match exists\",\n \"Refactor prompt assembly to embed assets (genes, capsules, parent event)\",\n \"Reduce noise and ambiguity; enforce strict output schema\",\n \"Validate by running node index.js run and ensuring no runtime errors\",\n \"Solidify: record EvolutionEvent, update Gene definitions, create Capsule on success\"\n ],\n \"constraints\": {\n \"max_files\": 20,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/prompt'); console.log('ok')\\\"\"\n ]\n },\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_innovate_from_opportunity\",\n \"category\": \"innovate\",\n \"signals_match\": [\n \"user_feature_request\",\n \"user_improvement_suggestion\",\n \"perf_bottleneck\",\n \"capability_gap\",\n \"stable_success_plateau\",\n \"external_opportunity\"\n ],\n \"preconditions\": [\n \"at least one opportunity signal is present\",\n \"no active log_error signals (stability first)\"\n ],\n \"strategy\": [\n \"Extract opportunity signals and identify the specific user need or system gap\",\n \"Search existing Genes and Capsules for partial matches (avoid reinventing)\",\n \"Design a minimal, testable implementation plan (prefer small increments)\",\n \"Estimate blast radius; innovate changes may touch more files but must stay within constraints\",\n \"Implement the change with clear validation criteria\",\n \"Validate using declared validation steps; rollback on failure\",\n \"Solidify: record EvolutionEvent with intent=innovate, create new Gene if pattern is novel, create Capsule on success\"\n ],\n \"constraints\": {\n \"max_files\": 25,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\",\n \"assets/gep/events.jsonl\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/solidify'); console.log('ok')\\\"\"\n ]\n }\n ]\n}\n\n",
95 "mimeType": null,
96 "size": null,
97 "icons": null,
98 "annotations": null,
99 "meta": null
100 },
101 {
102 "name": "package.json",
103 "title": null,
104 "uri": "skill://package.json",
105 "description": "{\n \"name\": \"evolver\",\n \"version\": \"1.10.1\",\n \"description\": \"A self-evolution engine for AI agents. Features automated log analysis and protocol-constrained evolution with auditable assets.\",\n \"main\": \"index.js\",\n \"keywords\": [\n \"openclaw\",\n \"ai\",\n \"evolution\",\n \"meta-learning\",\n \"self-repair\",\n \"automation\",\n \"agent\"\n ],\n \"author\": \"OpenClaw\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"start\": \"node index.js\",\n \"run\": \"node index.js run\",\n \"solidify\": \"node index.js solidify\",\n \"a2a:export\": \"node scripts/a2a_export.js\",\n \"a2a:ingest\": \"node scripts/a2a_ingest.js\",\n \"a2a:promote\": \"node scripts/a2a_promote.js\"\n },\n \"dependencies\": {}\n}\n",
106 "mimeType": null,
107 "size": null,
108 "icons": null,
109 "annotations": null,
110 "meta": null
111 },
112 {
113 "name": "_meta.json",
114 "title": null,
115 "uri": "skill://_meta.json",
116 "description": "{\n \"owner\": \"autogame-17\",\n \"slug\": \"evolver\",\n \"displayName\": \"Evolver\",\n \"latest\": {\n \"version\": \"1.10.1\",\n \"publishedAt\": 1770769923939,\n \"commit\": \"https://github.com/openclaw/skills/commit/d42b0aecff30ddc7c42d3e91d0bcf59d148cdb65\"\n },\n \"history\": [\n {\n \"version\": \"1.9.2\",\n \"publishedAt\": 1770698325560,\n \"commit\": \"https://github.com/openclaw/skills/commit/41679826b2b9930ba6cf8abd0d5e05a8a0c4aed7\"\n },\n {\n \"version\": \"1.8.6\",\n \"publishedAt\": 1770650521310,\n \"commit\": \"https://github.com/openclaw/skills/commit/b70f9f526141cf74a00da1b9ee4e9245acc75f18\"\n },\n {\n \"version\": \"1.8.4\",\n \"publishedAt\": 1770641202797,\n \"commit\": \"https://github.com/openclaw/skills/commit/93c3a0f0e09d2fd71dfc89a1ed2110175611af12\"\n },\n {\n \"version\": \"1.8.2\",\n \"publishedAt\": 1770623720606,\n \"commit\": \"https://github.com/openclaw/skills/commit/305563055d4c55e752902ea00c40adcb82b3abc3\"\n },\n {\n \"version\": \"1.8.1\",\n \"publishedAt\": 1770623279854,\n \"commit\": \"https://github.com/openclaw/skills/commit/f70c2eb1737ec24b1c3f8d0c152ddf8a8c3784f5\"\n },\n {\n \"version\": \"1.7.3\",\n \"publishedAt\": 1770562946750,\n \"commit\": \"https://github.com/openclaw/skills/commit/d26e6523a4c709713a1a544fd717e4bfbf9a593c\"\n },\n {\n \"version\": \"1.7.1\",\n \"publishedAt\": 1770562348370,\n \"commit\": \"https://github.com/openclaw/skills/commit/13cc46daacdaf1bc0c17616c49b39da2a2f98302\"\n },\n {\n \"version\": \"1.6.1\",\n \"publishedAt\": 1770471394691,\n \"commit\": \"https://github.com/openclaw/skills/commit/27f006faafe85a52f50ac3bbd4155ff972eb774c\"\n },\n {\n \"version\": \"1.4.4\",\n \"publishedAt\": 1770382881342,\n \"commit\": \"https://github.com/openclaw/skills/commit/e3fc8ff3c0fc6cc659a06114e6ffc7b342275b15\"\n },\n {\n \"version\": \"1.4.2\",\n \"publishedAt\": 1770343663622,\n \"commit\": \"https://github.com/clawdbot/skills/commit/7be8e49fcfa44e1637dae447684057a5142a4ceb\"\n },\n {\n \"version\": \"1.2.0\",\n \"publishedAt\": 1770318833377,\n \"commit\": \"https://github.com/clawdbot/skills/commit/2baf3cdb3d634c4aedef905cc7f5ba1c93679c5c\"\n },\n {\n \"version\": \"1.1.0\",\n \"publishedAt\": 1770128825586,\n \"commit\": \"https://github.com/clawdbot/skills/commit/816e6b731b31d828abf4926c17df20a7720ffae1\"\n }\n ]\n}\n",
117 "mimeType": null,
118 "size": null,
119 "icons": null,
120 "annotations": null,
121 "meta": null
122 }
123 ],
124 "resource_templates": [],
125 "tools": [
126 {
127 "name": "publish_public.js",
128 "title": null,
129 "description": "Script: publish_public.js. Code:\nconst { execSync, spawnSync } = require('child_process');\nconst fs = require('fs');\nconst https = require('https');\nconst os = require('os');\nconst path = require('path');\n\nfunction run(cmd, opts = {}) {\n const { dryRun = false } = opts;\n if (dryRun) {\n process.stdout.write(`[dry-run] ${cmd}\\n`);\n return '';\n }\n return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();\n}\n\nfunction hasCommand(cmd) {\n try {\n if (process.platform === 'win32') {\n const res = spawnSync('where', [cmd], { stdio: 'ignore' });\n return res.status === 0;\n }\n const res = spawnSync('which', [cmd], { stdio: 'ignore' });\n return res.status === 0;\n } catch (e) {\n return false;\n }\n}\n\nfunction resolveGhExecutable() {\n if (hasCommand('gh')) return 'gh';\n const candidates = [\n 'C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe',\n 'C:\\\\Program Files (x86)\\\\GitHub CLI\\\\gh.exe',\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p)) return p;\n } catch (e) {\n // ignore\n }\n }\n return null;\n}\n\nfunction resolveClawhubExecutable() {\n // On Windows, Node spawn/spawnSync does not always resolve PATHEXT the same way as shells.\n // Prefer the explicit .cmd shim when available to avoid false \"not logged in\" detection.\n if (process.platform === 'win32') {\n if (hasCommand('clawhub.cmd')) return 'clawhub.cmd';\n if (hasCommand('clawhub')) return 'clawhub';\n } else {\n if (hasCommand('clawhub')) return 'clawhub';\n }\n // Common npm global bin location on Windows.\n const candidates = [\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.cmd',\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.exe',\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.ps1',\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p)) return p;\n } catch (e) {\n // ignore\n }\n }\n return null;\n}\n\nfunction canUseClawhub() {\n const exe = resolveClawhubExecutable();\n if (!exe) return { ok: false, reason: 'clawhub CLI not found (install: npm i -g clawhub)' };\n return { ok: true, exe };\n}\n\nfunction isClawhubLoggedIn() {\n const exe = resolveClawhubExecutable();\n if (!exe) return false;\n try {\n const res = spawnClawhub(exe, ['whoami'], { stdio: 'ignore' });\n return res.status === 0;\n } catch (e) {\n return false;\n }\n}\n\nfunction spawnClawhub(exe, args, options) {\n // On Windows, directly spawning a .cmd can be flaky; using cmd.exe preserves argument parsing.\n // (Using shell:true can break clap/commander style option parsing for some CLIs.)\n const opts = options || {};\n if (process.platform === 'win32' && typeof exe === 'string') {\n const lower = exe.toLowerCase();\n if (lower.endsWith('.cmd')) {\n return spawnSync('cmd.exe', ['/d', '/s', '/c', exe, ...(args || [])], opts);\n }\n }\n return spawnSync(exe, args || [], opts);\n}\n\nfunction publishToClawhub({ skillDir, slug, name, version, changelog, tags, dryRun }) {\n const ok = canUseClawhub();\n if (!ok.ok) throw new Error(ok.reason);\n\n // Idempotency: if this version already exists on ClawHub, skip publishing.\n try {\n const inspect = spawnClawhub(ok.exe, ['inspect', slug, '--version', version], { stdio: 'ignore' });\n if (inspect.status === 0) {\n process.stdout.write(`ClawHub already has ${slug}@${version}. Skipping.\\n`);\n return;\n }\n } catch (e) {\n // ignore inspect failures; publish will surface errors if needed\n }\n\n if (!dryRun && !isClawhubLoggedIn()) {\n throw new Error('Not logged in to ClawHub. Run: clawhub login');\n }\n\n const args = ['publish', skillDir, '--slug', slug, '--name', name, '--version', version];\n if (changelog) args.push('--changelog', changelog);\n if (tags) args.push('--tags', tags);\n\n if (dryRun) {\n process.stdout.write(`[dry-run] ${ok.exe} ${args.map(a => (/\\s/.test(a) ? `\"${a}\"` : a)).join(' ')}\\n`);\n return;\n }\n\n // Capture output to handle \"version already exists\" idempotently.\n const res = spawnClawhub(ok.exe, args, { encoding: 'utf8' });\n const out = `${res.stdout || ''}\\n${res.stderr || ''}`.trim();\n\n if (res.status === 0) {\n if (out) process.stdout.write(out + '\\n');\n return;\n }\n\n // Some clawhub deployments do not support reliable \"inspect\" by slug.\n // Treat \"Version already exists\" as success to make publishing idempotent.\n if (/version already exists/i.test(out)) {\n process.stdout.write(`ClawHub already has ${slug}@${version}. Skipping.\\n`);\n return;\n }\n\n if (out) process.stderr.write(out + '\\n');\n throw new Error(`clawhub publish failed for slug ${slug}`);\n}\n\nfunction requireEnv(name, value) {\n if (!value) {\n throw new Error(`Missing required env var: ${name}`);\n }\n}\n\nfunction ensureClean(dryRun) {\n const status = run('git status --porcelain', { dryRun });\n if (!dryRun && status) {\n throw new Error('Working tree is not clean. Commit or stash before publishing.');\n }\n}\n\nfunction ensureBranch(expected, dryRun) {\n const current = run('git rev-parse --abbrev-ref HEAD', { dryRun }) || expected;\n if (!dryRun && current !== expected) {\n throw new Error(`Current branch is ${current}. Expected ${expected}.`);\n }\n}\n\nfunction ensureRemote(remote, dryRun) {\n try {\n run(`git remote get-url ${remote}`, { dryRun });\n } catch (e) {\n throw new Error(`Remote \"${remote}\" not found. Add it manually before running this script.`);\n }\n}\n\nfunction ensureTagAvailable(tag, dryRun) {\n if (!tag) return;\n const exists = run(`git tag --list ${tag}`, { dryRun });\n if (!dryRun && exists) {\n throw new Error(`Tag ${tag} already exists.`);\n }\n}\n\nfunction ensureDir(dir, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction rmDir(dir, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(dir)) return;\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\nfunction copyDir(src, dest, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(src)) throw new Error(`Missing build output dir: ${src}`);\n ensureDir(dest, dryRun);\n const entries = fs.readdirSync(src, { withFileTypes: true });\n for (const ent of entries) {\n const s = path.join(src, ent.name);\n const d = path.join(dest, ent.name);\n if (ent.isDirectory()) copyDir(s, d, dryRun);\n else if (ent.isFile()) {\n ensureDir(path.dirname(d), dryRun);\n fs.copyFileSync(s, d);\n }\n }\n}\n\nfunction createReleaseWithGh({ repo, tag, title, notes, notesFile, dryRun }) {\n if (!repo || !tag) return;\n const ghExe = resolveGhExecutable();\n if (!ghExe) {\n throw new Error('gh CLI not found. Install GitHub CLI or provide a GitHub token for API-based release creation.');\n }\n const args = ['release', 'create', tag, '--repo', repo];\n if (title) args.push('-t', title);\n if (notesFile) args.push('-F', notesFile);\n else if (notes) args.push('-n', notes);\n else args.push('-n', 'Release created by publish script.');\n\n if (dryRun) {\n process.stdout.write(`[dry-run] ${ghExe} ${args.join(' ')}\\n`);\n return;\n }\n\n const res = spawnSync(ghExe, args, { stdio: 'inherit' });\n if (res.status !== 0) {\n throw new Error('gh release create failed');\n }\n}\n\nfunction canUseGhForRelease() {\n const ghExe = resolveGhExecutable();\n if (!ghExe) return { ok: false, reason: 'gh CLI not found' };\n try {\n // Non-interactive check: returns 0 when authenticated.\n const res = spawnSync(ghExe, ['auth', 'status', '-h', 'github.com'], { stdio: 'ignore' });\n if (res.status === 0) return { ok: true };\n return { ok: false, reason: 'gh not authenticated (run: gh auth login)' };\n } catch (e) {\n return { ok: false, reason: 'failed to check gh auth status' };\n }\n}\n\nfunction getGithubToken() {\n return process.env.GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_PAT || '';\n}\n\nfunction readReleaseNotes(notes, notesFile) {\n if (notesFile) {\n try {\n return fs.readFileSync(notesFile, 'utf8');\n } catch (e) {\n throw new Error(`Failed to read RELEASE_NOTES_FILE: ${notesFile}`);\n }\n }\n if (notes) return String(notes);\n return '';\n}\n\nfunction githubRequestJson({ method, repo, apiPath, token, body, dryRun }) {\n if (dryRun) {\n process.stdout.write(`[dry-run] GitHub API ${method} ${repo} ${apiPath}\\n`);\n return Promise.resolve({ status: 200, json: null });\n }\n\n const data = body ? Buffer.from(JSON.stringify(body)) : null;\n const opts = {\n method,\n hostname: 'api.github.com',\n path: `/repos/${repo}${apiPath}`,\n headers: {\n 'User-Agent': 'evolver-publish-script',\n Accept: 'application/vnd.github+json',\n ...(token ? { Authorization: `token ${token}` } : {}),\n ...(data ? { 'Content-Type': 'application/json', 'Content-Length': String(data.length) } : {}),\n },\n };\n\n return new Promise((resolve, reject) => {\n const req = https.request(opts, res => {\n let raw = '';\n res.setEncoding('utf8');\n res.on('data', chunk => (raw += chunk));\n res.on('end', () => {\n let json = null;\n try {\n json = raw ? JSON.parse(raw) : null;\n } catch (e) {\n json = null;\n }\n resolve({ status: res.statusCode || 0, json, raw });\n });\n });\n req.on('error', reject);\n if (data) req.write(data);\n req.end();\n });\n}\n\nasync function ensureReleaseWithApi({ repo, tag, title, notes, notesFile, dryRun }) {\n if (!repo || !tag) return;\n\n const token = getGithubToken();\n if (!dryRun) {\n requireEnv('GITHUB_TOKEN (or GH_TOKEN/GITHUB_PAT)', token);\n }\n\n // If release already exists, skip.\n const existing = await githubRequestJson({\n method: 'GET',\n repo,\n apiPath: `/releases/tags/${encodeURIComponent(tag)}`,\n token,\n dryRun,\n });\n\n if (!dryRun && existing.status === 200) {\n process.stdout.write(`Release already exists for tag ${tag}. Skipping.\\n`);\n return;\n }\n\n const bodyText = readReleaseNotes(notes, notesFile) || 'Release created by publish script.';\n const payload = {\n tag_name: tag,\n name: title || tag,\n body: bodyText,\n draft: false,\n prerelease: false,\n };\n\n const created = await githubRequestJson({\n method: 'POST',\n repo,\n apiPath: '/releases',\n token,\n body: payload,\n dryRun,\n });\n\n if (!dryRun && (created.status < 200 || created.status >= 300)) {\n const msg = (created.json && created.json.message) || created.raw || 'Unknown error';\n throw new Error(`Failed to create GitHub Release (${created.status}): ${msg}`);\n }\n\n process.stdout.write(`Created GitHub Release for tag ${tag}\\n`);\n}\n\nfunction main() {\n const dryRun = String(process.env.DRY_RUN || '').toLowerCase() === 'true';\n\n const sourceBranch = process.env.SOURCE_BRANCH || 'main';\n const publicRemote = process.env.PUBLIC_REMOTE || 'public';\n const publicBranch = process.env.PUBLIC_BRANCH || 'main';\n const publicRepo = process.env.PUBLIC_REPO || '';\n const outDir = process.env.PUBLIC_OUT_DIR || 'dist-public';\n const useBuildOutput = String(process.env.PUBLIC_USE_BUILD_OUTPUT || 'true').toLowerCase() === 'true';\n const releaseOnly = String(process.env.PUBLIC_RELEASE_ONLY || '').toLowerCase() === 'true';\n\n const clawhubSkip = String(process.env.CLAWHUB_SKIP || '').toLowerCase() === 'true';\n const clawhubPublish = String(process.env.CLAWHUB_PUBLISH || '').toLowerCase() === 'false' ? false : !clawhubSkip;\n // Workaround for registry redirect/auth issues: default to the www endpoint.\n const clawhubRegistry = process.env.CLAWHUB_REGISTRY || 'https://www.clawhub.ai';\n\n // If publishing build output, require a repo URL or GH repo slug for cloning.\n if (useBuildOutput) {\n requireEnv('PUBLIC_REPO', publicRepo);\n }\n\n let releaseTag = process.env.RELEASE_TAG || '';\n let releaseTitle = process.env.RELEASE_TITLE || '';\n const releaseNotes = process.env.RELEASE_NOTES || '';\n const releaseNotesFile = process.env.RELEASE_NOTES_FILE || '';\n const releaseSkip = String(process.env.RELEASE_SKIP || '').toLowerCase() === 'true';\n // Default behavior: create release unless explicitly skipped.\n // Backward compatibility: RELEASE_CREATE=true forces creation.\n // Note: RELEASE_CREATE=false is ignored; use RELEASE_SKIP=true instead.\n const releaseCreate = String(process.env.RELEASE_CREATE || '').toLowerCase() === 'true' ? true : !releaseSkip;\n const releaseUseGh = String(process.env.RELEASE_USE_GH || '').toLowerCase() === 'true';\n\n // If not provided, infer from build output package.json version.\n if (!releaseTag && useBuildOutput) {\n try {\n const builtPkg = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), outDir, 'package.json'), 'utf8'));\n if (builtPkg && builtPkg.version) releaseTag = `v${builtPkg.version}`;\n if (!releaseTitle && releaseTag) releaseTitle = releaseTag;\n } catch (e) {}\n }\n\n const releaseVersion = String(releaseTag || '').startsWith('v') ? String(releaseTag).slice(1) : '';\n\n // Fail fast on missing release prerequisites to avoid half-publishing.\n // Strategy:\n // - If RELEASE_USE_GH=true: require gh + auth\n // - Else: prefer gh+auth; fallback to API token; else fail\n let releaseMode = 'none';\n if (releaseCreate && releaseTag) {\n if (releaseUseGh) {\n const ghOk = canUseGhForRelease();\n if (!dryRun && !ghOk.ok) {\n throw new Error(`Cannot create release via gh: ${ghOk.reason}`);\n }\n releaseMode = 'gh';\n } else {\n const ghOk = canUseGhForRelease();\n if (ghOk.ok) {\n releaseMode = 'gh';\n } else {\n const token = getGithubToken();\n if (!dryRun && !token) {\n throw new Error(\n 'Cannot create GitHub Release: neither gh (installed+authenticated) nor GITHUB_TOKEN (or GH_TOKEN/GITHUB_PAT) is available.'\n );\n }\n releaseMode = 'api';\n }\n }\n }\n\n // In release-only mode we do not push code or tags, only create a GitHub Release for an existing tag.\n if (!releaseOnly) {\n ensureClean(dryRun);\n ensureBranch(sourceBranch, dryRun);\n ensureTagAvailable(releaseTag, dryRun);\n } else {\n requireEnv('RELEASE_TAG', releaseTag);\n }\n\n if (!releaseOnly) {\n if (!useBuildOutput) {\n ensureRemote(publicRemote, dryRun);\n run(`git push ${publicRemote} ${sourceBranch}:${publicBranch}`, { dryRun });\n } else {\n const tmpBase = path.join(os.tmpdir(), 'evolver-public-publish');\n const tmpRepoDir = path.join(tmpBase, `repo_${Date.now()}`);\n const buildAbs = path.resolve(process.cwd(), outDir);\n\n rmDir(tmpRepoDir, dryRun);\n ensureDir(tmpRepoDir, dryRun);\n\n run(`git clone --depth 1 https://github.com/${publicRepo}.git \"${tmpRepoDir}\"`, { dryRun });\n run(`git -C \"${tmpRepoDir}\" checkout -B ${publicBranch}`, { dryRun });\n\n // Replace repo contents with build output (except .git)\n if (!dryRun) {\n const entries = fs.readdirSync(tmpRepoDir, { withFileTypes: true });\n for (const ent of entries) {\n if (ent.name === '.git') continue;\n fs.rmSync(path.join(tmpRepoDir, ent.name), { recursive: true, force: true });\n }\n }\n copyDir(buildAbs, tmpRepoDir, dryRun);\n\n run(`git -C \"${tmpRepoDir}\" add -A`, { dryRun });\n const msg = releaseTag ? `Release ${releaseTag}` : `Publish build output`;\n\n // If build output is identical to current public branch, skip commit/push.\n const pending = run(`git -C \"${tmpRepoDir}\" status --porcelain`, { dryRun });\n if (!dryRun && !pending) {\n process.stdout.write('Public repo already matches build output. Skipping commit/push.\\n');\n } else {\n // Avoid relying on global git config (CI environments often lack user.name/user.email).\n run(\n `git -C \"${tmpRepoDir}\" -c user.name=\"evolver-publish\" -c user.email=\"evolver-publish@local\" commit -m \"${msg.replace(\n /\"/g,\n '\\\\\"'\n )}\"`,\n { dryRun }\n );\n run(`git -C \"${tmpRepoDir}\" push origin ${publicBranch}`, { dryRun });\n }\n\n if (releaseTag) {\n const tagMsg = releaseTitle || `Release ${releaseTag}`;\n // If tag already exists in the public repo, do not recreate it.\n try {\n run(`git -C \"${tmpRepoDir}\" fetch --tags`, { dryRun });\n const exists = run(`git -C \"${tmpRepoDir}\" tag --list ${releaseTag}`, { dryRun });\n if (!dryRun && exists) {\n process.stdout.write(`Tag ${releaseTag} already exists in public repo. Skipping tag creation.\\n`);\n } else {\n run(`git -C \"${tmpRepoDir}\" tag -a ${releaseTag} -m \"${tagMsg.replace(/\"/g, '\\\\\"')}\"`, { dryRun });\n run(`git -C \"${tmpRepoDir}\" push origin ${releaseTag}`, { dryRun });\n }\n } catch (e) {\n // If tag operations fail, rethrow to avoid publishing a release without a tag.\n throw e;\n }\n }\n }\n\n if (releaseTag) {\n if (!useBuildOutput) {\n const msg = releaseTitle || `Release ${releaseTag}`;\n run(`git tag -a ${releaseTag} -m \"${msg.replace(/\"/g, '\\\\\"')}\"`, { dryRun });\n run(`git push ${publicRemote} ${releaseTag}`, { dryRun });\n }\n }\n }\n\n if (releaseCreate) {\n if (releaseMode === 'gh') {\n createReleaseWithGh({\n repo: publicRepo,\n tag: releaseTag,\n title: releaseTitle,\n notes: releaseNotes,\n notesFile: releaseNotesFile,\n dryRun,\n });\n } else if (releaseMode === 'api') {\n return ensureReleaseWithApi({\n repo: publicRepo,\n tag: releaseTag,\n title: releaseTitle,\n notes: releaseNotes,\n notesFile: releaseNotesFile,\n dryRun,\n });\n }\n }\n\n // Publish to ClawHub after GitHub release succeeds (default enabled).\n if (clawhubPublish && releaseVersion) {\n process.env.CLAWHUB_REGISTRY = clawhubRegistry;\n\n const skillDir = useBuildOutput ? path.resolve(process.cwd(), outDir) : process.cwd();\n const changelog = releaseTitle ? `GitHub Release ${releaseTitle}` : `GitHub Release ${releaseTag}`;\n\n publishToClawhub({\n skillDir,\n slug: 'evolver',\n name: 'Evolver',\n version: releaseVersion,\n changelog,\n tags: 'latest',\n dryRun,\n });\n\n publishToClawhub({\n skillDir,\n slug: 'capability-evolver',\n name: 'Capability Evolver',\n version: releaseVersion,\n changelog,\n tags: 'latest',\n dryRun,\n });\n }\n}\n\ntry {\n const maybePromise = main();\n if (maybePromise && typeof maybePromise.then === 'function') {\n maybePromise.catch(e => {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n });\n }\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
130 "inputSchema": {},
131 "outputSchema": null,
132 "icons": null,
133 "annotations": null,
134 "meta": null,
135 "execution": null
136 },
137 {
138 "name": "human_report.js",
139 "title": null,
140 "description": "Script: human_report.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst IN_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_human_summary.md');\n\nfunction generateHumanReport() {\n if (!fs.existsSync(IN_FILE)) return console.error(\"No input file\");\n\n const content = fs.readFileSync(IN_FILE, 'utf8');\n const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);\n\n const categories = {\n 'Security & Stability': [],\n 'Performance & Optimization': [],\n 'Tooling & Features': [],\n 'Documentation & Process': []\n };\n\n const componentMap = {}; // Component -> Change List\n\n entries.forEach(entry => {\n // Extract basic info\n const lines = entry.split('\\n');\n const header = lines[0]; // ### Title (Date)\n const body = lines.slice(1).join('\\n');\n \n const dateMatch = header.match(/\\((.*?)\\)/);\n const dateStr = dateMatch ? dateMatch[1] : '';\n const time = dateStr.split(' ')[1] || ''; // HH:mm:ss\n\n // Classify\n let category = 'Tooling & Features';\n let component = 'System';\n let summary = '';\n\n const lowerBody = body.toLowerCase();\n\n // Detect Component\n if (lowerBody.includes('feishu-card')) component = 'feishu-card';\n else if (lowerBody.includes('feishu-sticker')) component = 'feishu-sticker';\n else if (lowerBody.includes('git-sync')) component = 'git-sync';\n else if (lowerBody.includes('capability-evolver') || lowerBody.includes('evolve.js')) component = 'capability-evolver';\n else if (lowerBody.includes('interaction-logger')) component = 'interaction-logger';\n else if (lowerBody.includes('chat-to-image')) component = 'chat-to-image';\n else if (lowerBody.includes('safe_publish')) component = 'capability-evolver';\n\n // Detect Category\n if (lowerBody.includes('security') || lowerBody.includes('permission') || lowerBody.includes('auth') || lowerBody.includes('harden')) {\n category = 'Security & Stability';\n } else if (lowerBody.includes('optimiz') || lowerBody.includes('performance') || lowerBody.includes('memory') || lowerBody.includes('fast')) {\n category = 'Performance & Optimization';\n } else if (lowerBody.includes('doc') || lowerBody.includes('readme')) {\n category = 'Documentation & Process';\n }\n\n // Extract Human Summary (First meaningful line that isn't Status/Action/Date)\n const summaryLines = lines.filter(l => \n !l.startsWith('###') && \n !l.startsWith('Status:') && \n !l.startsWith('Action:') &&\n l.trim().length > 10\n );\n \n if (summaryLines.length > 0) {\n // Clean up the line\n summary = summaryLines[0]\n .replace(/^-\\s*/, '') // Remove bullets\n .replace(/\\*\\*/g, '') // Remove bold\n .replace(/`/, '')\n .trim();\n \n // Deduplicate\n const key = `${component}:${summary.substring(0, 20)}`;\n const exists = categories[category].some(i => i.key === key);\n \n if (!exists && !summary.includes(\"Stability Scan OK\") && !summary.includes(\"Workspace Sync\")) {\n categories[category].push({ time, component, summary, key });\n \n if (!componentMap[component]) componentMap[component] = [];\n componentMap[component].push(summary);\n }\n }\n });\n\n // --- Generate Markdown ---\n const today = new Date().toISOString().slice(0, 10);\n let md = `# Evolution Summary: The Day in Review (${today})\\n\\n`;\n md += `> Overview: Grouped summary of changes extracted from evolution history.\\n\\n`;\n\n // Section 1: By Theme (Evolution Direction)\n md += `## 1. Evolution Direction\\n`;\n \n for (const [cat, items] of Object.entries(categories)) {\n if (items.length === 0) continue;\n md += `### ${cat}\\n`;\n // Group by component within theme\n const compGroup = {};\n items.forEach(i => {\n if (!compGroup[i.component]) compGroup[i.component] = [];\n compGroup[i.component].push(i.summary);\n });\n \n for (const [comp, sums] of Object.entries(compGroup)) {\n // Unique summaries only\n const uniqueSums = [...new Set(sums)];\n uniqueSums.forEach(s => {\n md += `- **${comp}**: ${s}\\n`;\n });\n }\n md += `\\n`;\n }\n\n // Section 2: By Timeline (High Level)\n md += `## 2. Timeline of Critical Events\\n`;\n // Flatten and sort all items by time\n const allItems = [];\n Object.values(categories).forEach(list => allItems.push(...list));\n allItems.sort((a, b) => a.time.localeCompare(b.time));\n \n // Filter for \"Critical\" keywords\n const criticalItems = allItems.filter(i => \n i.summary.toLowerCase().includes('fix') || \n i.summary.toLowerCase().includes('patch') ||\n i.summary.toLowerCase().includes('create') ||\n i.summary.toLowerCase().includes('optimiz')\n );\n\n criticalItems.forEach(i => {\n md += `- \\`${i.time}\\` (${i.component}): ${i.summary}\\n`;\n });\n\n // Section 3: Package Adjustments\n md += `\\n## 3. Package & Documentation Adjustments\\n`;\n const comps = Object.keys(componentMap).sort();\n comps.forEach(comp => {\n const count = new Set(componentMap[comp]).size;\n md += `- **${comp}**: Received ${count} significant updates.\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(\"Human report generated.\");\n}\n\ngenerateHumanReport();\n\n",
141 "inputSchema": {},
142 "outputSchema": null,
143 "icons": null,
144 "annotations": null,
145 "meta": null,
146 "execution": null
147 },
148 {
149 "name": "gep_personality_report.js",
150 "title": null,
151 "description": "Script: gep_personality_report.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getRepoRoot, getMemoryDir, getGepAssetsDir } = require('../src/gep/paths');\nconst { normalizePersonalityState, personalityKey, defaultPersonalityState } = require('../src/gep/personality');\n\nfunction readJsonIfExists(p, fallback) {\n try {\n if (!fs.existsSync(p)) return fallback;\n const raw = fs.readFileSync(p, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction readJsonlIfExists(p, limitLines = 5000) {\n try {\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n const recent = lines.slice(Math.max(0, lines.length - limitLines));\n return recent\n .map(l => {\n try {\n return JSON.parse(l);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction pct(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return '0.0%';\n return `${(n * 100).toFixed(1)}%`;\n}\n\nfunction pad(s, n) {\n const str = String(s == null ? '' : s);\n if (str.length >= n) return str.slice(0, n);\n return str + ' '.repeat(n - str.length);\n}\n\nfunction scoreFromCounts(success, fail, avgScore) {\n const succ = Number(success) || 0;\n const fl = Number(fail) || 0;\n const total = succ + fl;\n const p = (succ + 1) / (total + 2); // Laplace smoothing\n const sampleWeight = Math.min(1, total / 8);\n const q = avgScore == null ? 0.5 : clamp01(avgScore);\n return p * 0.75 + q * 0.25 * sampleWeight;\n}\n\nfunction aggregateFromEvents(events) {\n const map = new Map();\n for (const ev of Array.isArray(events) ? events : []) {\n if (!ev || ev.type !== 'EvolutionEvent') continue;\n const ps = ev.personality_state && typeof ev.personality_state === 'object' ? ev.personality_state : null;\n if (!ps) continue;\n const key = personalityKey(normalizePersonalityState(ps));\n const cur = map.get(key) || {\n key,\n success: 0,\n fail: 0,\n n: 0,\n avg_score: 0.5,\n last_event_id: null,\n last_at: null,\n mutation: { repair: 0, optimize: 0, innovate: 0 },\n mutation_success: { repair: 0, optimize: 0, innovate: 0 },\n };\n const st = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (st === 'success') cur.success += 1;\n else if (st === 'failed') cur.fail += 1;\n\n const sc = ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? clamp01(Number(ev.outcome.score)) : null;\n if (sc != null) {\n cur.n += 1;\n cur.avg_score = cur.avg_score + (sc - cur.avg_score) / cur.n;\n }\n\n const cat = ev.intent ? String(ev.intent) : null;\n if (cat && cur.mutation[cat] != null) {\n cur.mutation[cat] += 1;\n if (st === 'success') cur.mutation_success[cat] += 1;\n }\n\n cur.last_event_id = ev.id || cur.last_event_id;\n const at = ev.meta && ev.meta.at ? String(ev.meta.at) : null;\n cur.last_at = at || cur.last_at;\n map.set(key, cur);\n }\n return Array.from(map.values());\n}\n\nfunction main() {\n const repoRoot = getRepoRoot();\n const memoryDir = getMemoryDir();\n const assetsDir = getGepAssetsDir();\n\n const personalityPath = path.join(memoryDir, 'personality_state.json');\n const model = readJsonIfExists(personalityPath, null);\n const current = model && model.current ? normalizePersonalityState(model.current) : defaultPersonalityState();\n const currentKey = personalityKey(current);\n\n const eventsPath = path.join(assetsDir, 'events.jsonl');\n const events = readJsonlIfExists(eventsPath, 10000);\n const evs = events.filter(e => e && e.type === 'EvolutionEvent');\n const agg = aggregateFromEvents(evs);\n\n // Prefer model.stats if present, but still show event-derived aggregation (ground truth).\n const stats = model && model.stats && typeof model.stats === 'object' ? model.stats : {};\n const statRows = Object.entries(stats).map(([key, e]) => {\n const entry = e && typeof e === 'object' ? e : {};\n const success = Number(entry.success) || 0;\n const fail = Number(entry.fail) || 0;\n const total = success + fail;\n const avg = Number.isFinite(Number(entry.avg_score)) ? clamp01(Number(entry.avg_score)) : null;\n const score = scoreFromCounts(success, fail, avg);\n return { key, success, fail, total, avg_score: avg, score, updated_at: entry.updated_at || null, source: 'model' };\n });\n\n const evRows = agg.map(e => {\n const success = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = success + fail;\n const avg = Number.isFinite(Number(e.avg_score)) ? clamp01(Number(e.avg_score)) : null;\n const score = scoreFromCounts(success, fail, avg);\n return { key: e.key, success, fail, total, avg_score: avg, score, updated_at: e.last_at || null, source: 'events', _ev: e };\n });\n\n // Merge rows by key (events take precedence for total/success/fail; model provides updated_at if events missing).\n const byKey = new Map();\n for (const r of [...statRows, ...evRows]) {\n const prev = byKey.get(r.key);\n if (!prev) {\n byKey.set(r.key, r);\n continue;\n }\n // Prefer events for counts and avg_score\n if (r.source === 'events') byKey.set(r.key, { ...prev, ...r });\n else byKey.set(r.key, { ...r, ...prev });\n }\n\n const merged = Array.from(byKey.values()).sort((a, b) => b.score - a.score);\n\n process.stdout.write(`Repo: ${repoRoot}\\n`);\n process.stdout.write(`MemoryDir: ${memoryDir}\\n`);\n process.stdout.write(`AssetsDir: ${assetsDir}\\n\\n`);\n\n process.stdout.write(`[Current Personality]\\n`);\n process.stdout.write(`${currentKey}\\n`);\n process.stdout.write(`${JSON.stringify(current, null, 2)}\\n\\n`);\n\n process.stdout.write(`[Personality Stats] (ranked by score)\\n`);\n if (merged.length === 0) {\n process.stdout.write('(no stats yet; run a few cycles and solidify)\\n');\n return;\n }\n\n const header =\n pad('rank', 5) +\n pad('total', 8) +\n pad('succ', 8) +\n pad('fail', 8) +\n pad('succ_rate', 11) +\n pad('avg', 7) +\n pad('score', 8) +\n 'key';\n process.stdout.write(header + '\\n');\n process.stdout.write('-'.repeat(Math.min(140, header.length + 40)) + '\\n');\n\n const topN = Math.min(25, merged.length);\n for (let i = 0; i < topN; i++) {\n const r = merged[i];\n const succ = Number(r.success) || 0;\n const fail = Number(r.fail) || 0;\n const total = Number(r.total) || succ + fail;\n const succRate = total > 0 ? succ / total : 0;\n const avg = r.avg_score == null ? '-' : Number(r.avg_score).toFixed(2);\n const line =\n pad(String(i + 1), 5) +\n pad(String(total), 8) +\n pad(String(succ), 8) +\n pad(String(fail), 8) +\n pad(pct(succRate), 11) +\n pad(String(avg), 7) +\n pad(Number(r.score).toFixed(3), 8) +\n String(r.key);\n process.stdout.write(line + '\\n');\n\n if (r._ev) {\n const ev = r._ev;\n const ms = ev.mutation || {};\n const mSucc = ev.mutation_success || {};\n const parts = [];\n for (const cat of ['repair', 'optimize', 'innovate']) {\n const n = Number(ms[cat]) || 0;\n if (n <= 0) continue;\n const s = Number(mSucc[cat]) || 0;\n parts.push(`${cat}:${s}/${n}`);\n }\n if (parts.length) process.stdout.write(` mutation_success: ${parts.join(' | ')}\\n`);\n }\n }\n\n process.stdout.write('\\n');\n process.stdout.write(`[Notes]\\n`);\n process.stdout.write(`- score is a smoothed composite of success_rate + avg_score (sample-weighted)\\n`);\n process.stdout.write(`- current_key appears in the ranking once enough data accumulates\\n`);\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write((e && e.message) || String(e));\n process.stderr.write('\\n');\n process.exit(1);\n}\n\n",
152 "inputSchema": {},
153 "outputSchema": null,
154 "icons": null,
155 "annotations": null,
156 "meta": null,
157 "execution": null
158 },
159 {
160 "name": "a2a_ingest.js",
161 "title": null,
162 "description": "Script: a2a_ingest.js. Code:\nvar fs = require('fs');\nvar assetStore = require('../src/gep/assetStore');\nvar a2a = require('../src/gep/a2a');\nvar memGraph = require('../src/gep/memoryGraph');\nvar contentHash = require('../src/gep/contentHash');\nvar a2aProto = require('../src/gep/a2aProtocol');\n\nfunction readStdin() {\n try { return fs.readFileSync(0, 'utf8'); } catch (e) { return ''; }\n}\n\nfunction parseSignalsFromEnv() {\n var raw = process.env.A2A_SIGNALS || '';\n if (!raw) return [];\n try {\n var maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) return maybe.map(String).filter(Boolean);\n } catch (e) {}\n return String(raw).split(',').map(function (s) { return s.trim(); }).filter(Boolean);\n}\n\nfunction main() {\n var args = process.argv.slice(2);\n var inputPath = '';\n for (var i = 0; i < args.length; i++) {\n if (args[i] && !args[i].startsWith('--')) { inputPath = args[i]; break; }\n }\n var source = process.env.A2A_SOURCE || 'external';\n var factor = Number.isFinite(Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR))\n ? Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR) : 0.6;\n\n var text = inputPath ? a2a.readTextIfExists(inputPath) : readStdin();\n var parsed = a2a.parseA2AInput(text);\n var signals = parseSignalsFromEnv();\n\n var accepted = 0;\n var rejected = 0;\n var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';\n\n for (var j = 0; j < parsed.length; j++) {\n var obj = parsed[j];\n if (!a2a.isAllowedA2AAsset(obj)) continue;\n\n if (obj.asset_id && typeof obj.asset_id === 'string') {\n if (!contentHash.verifyAssetId(obj)) {\n rejected += 1;\n if (emitDecisions) {\n try {\n var dm = a2aProto.buildDecision({ assetId: obj.asset_id, localId: obj.id, decision: 'reject', reason: 'asset_id integrity check failed' });\n a2aProto.getTransport().send(dm);\n } catch (e) {}\n }\n continue;\n }\n }\n\n var staged = a2a.lowerConfidence(obj, { source: source, factor: factor });\n if (!staged) continue;\n\n assetStore.appendExternalCandidateJsonl(staged);\n try { memGraph.recordExternalCandidate({ asset: staged, source: source, signals: signals }); } catch (e) {}\n\n if (emitDecisions) {\n try {\n var dm2 = a2aProto.buildDecision({ assetId: staged.asset_id, localId: staged.id, decision: 'quarantine', reason: 'staged as external candidate' });\n a2aProto.getTransport().send(dm2);\n } catch (e) {}\n }\n\n accepted += 1;\n }\n\n process.stdout.write('accepted=' + accepted + ' rejected=' + rejected + '\\n');\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
163 "inputSchema": {},
164 "outputSchema": null,
165 "icons": null,
166 "annotations": null,
167 "meta": null,
168 "execution": null
169 },
170 {
171 "name": "a2a_export.js",
172 "title": null,
173 "description": "Script: a2a_export.js. Code:\nconst { loadGenes, loadCapsules, readAllEvents } = require('../src/gep/assetStore');\nconst { exportEligibleCapsules } = require('../src/gep/a2a');\nconst { buildPublish, buildHello, getTransport } = require('../src/gep/a2aProtocol');\n\nfunction main() {\n var args = process.argv.slice(2);\n var asJson = args.includes('--json');\n var asProtocol = args.includes('--protocol');\n var withHello = args.includes('--hello');\n var persist = args.includes('--persist');\n\n var capsules = loadCapsules();\n var events = readAllEvents();\n var eligible = exportEligibleCapsules({ capsules: capsules, events: events });\n\n if (withHello || asProtocol) {\n var genes = loadGenes();\n var hello = buildHello({ geneCount: genes.length, capsuleCount: capsules.length });\n process.stdout.write(JSON.stringify(hello) + '\\n');\n if (persist) { try { getTransport().send(hello); } catch (e) {} }\n }\n\n if (asProtocol) {\n for (var i = 0; i < eligible.length; i++) {\n var msg = buildPublish({ asset: eligible[i] });\n process.stdout.write(JSON.stringify(msg) + '\\n');\n if (persist) { try { getTransport().send(msg); } catch (e) {} }\n }\n return;\n }\n\n if (asJson) {\n process.stdout.write(JSON.stringify(eligible, null, 2) + '\\n');\n return;\n }\n\n for (var j = 0; j < eligible.length; j++) {\n process.stdout.write(JSON.stringify(eligible[j]) + '\\n');\n }\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
174 "inputSchema": {},
175 "outputSchema": null,
176 "icons": null,
177 "annotations": null,
178 "meta": null,
179 "execution": null
180 },
181 {
182 "name": "a2a_promote.js",
183 "title": null,
184 "description": "Script: a2a_promote.js. Code:\nvar assetStore = require('../src/gep/assetStore');\nvar solidifyMod = require('../src/gep/solidify');\nvar contentHash = require('../src/gep/contentHash');\nvar a2aProto = require('../src/gep/a2aProtocol');\n\nfunction parseArgs(argv) {\n var out = { flags: new Set(), kv: new Map(), positionals: [] };\n for (var i = 0; i < argv.length; i++) {\n var a = argv[i];\n if (!a) continue;\n if (a.startsWith('--')) {\n var eq = a.indexOf('=');\n if (eq > -1) { out.kv.set(a.slice(2, eq), a.slice(eq + 1)); }\n else {\n var key = a.slice(2);\n var next = argv[i + 1];\n if (next && !String(next).startsWith('--')) { out.kv.set(key, next); i++; }\n else { out.flags.add(key); }\n }\n } else { out.positionals.push(a); }\n }\n return out;\n}\n\nfunction main() {\n var args = parseArgs(process.argv.slice(2));\n var id = String(args.kv.get('id') || '').trim();\n var typeRaw = String(args.kv.get('type') || '').trim().toLowerCase();\n var validated = args.flags.has('validated') || String(args.kv.get('validated') || '') === 'true';\n var limit = Number.isFinite(Number(args.kv.get('limit'))) ? Number(args.kv.get('limit')) : 500;\n\n if (!id || !typeRaw) throw new Error('Usage: node scripts/a2a_promote.js --type capsule|gene --id <id> --validated');\n if (!validated) throw new Error('Refusing to promote without --validated (local verification must be done first).');\n\n var type = typeRaw === 'capsule' ? 'Capsule' : typeRaw === 'gene' ? 'Gene' : '';\n if (!type) throw new Error('Invalid --type. Use capsule or gene.');\n\n var external = assetStore.readRecentExternalCandidates(limit);\n var candidate = null;\n for (var i = 0; i < external.length; i++) {\n if (external[i] && external[i].type === type && String(external[i].id) === id) { candidate = external[i]; break; }\n }\n if (!candidate) throw new Error('Candidate not found in external zone: type=' + type + ' id=' + id);\n\n if (type === 'Gene') {\n var validation = Array.isArray(candidate.validation) ? candidate.validation : [];\n for (var j = 0; j < validation.length; j++) {\n var c = String(validation[j] || '').trim();\n if (!c) continue;\n if (!solidifyMod.isValidationCommandAllowed(c)) {\n throw new Error('Refusing to promote Gene ' + id + ': validation command rejected by safety check: \"' + c + '\". Only node/npm/npx commands without shell operators are allowed.');\n }\n }\n }\n\n var promoted = JSON.parse(JSON.stringify(candidate));\n if (!promoted.a2a || typeof promoted.a2a !== 'object') promoted.a2a = {};\n promoted.a2a.status = 'promoted';\n promoted.a2a.promoted_at = new Date().toISOString();\n if (!promoted.schema_version) promoted.schema_version = contentHash.SCHEMA_VERSION;\n promoted.asset_id = contentHash.computeAssetId(promoted);\n\n var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';\n\n if (type === 'Capsule') {\n assetStore.appendCapsule(promoted);\n if (emitDecisions) {\n try {\n var dm = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'capsule promoted after validation' });\n a2aProto.getTransport().send(dm);\n } catch (e) {}\n }\n process.stdout.write('promoted_capsule=' + id + '\\n');\n return;\n }\n\n var localGenes = assetStore.loadGenes();\n var exists = false;\n for (var k = 0; k < localGenes.length; k++) {\n if (localGenes[k] && localGenes[k].type === 'Gene' && String(localGenes[k].id) === id) { exists = true; break; }\n }\n if (exists) {\n if (emitDecisions) {\n try {\n var dm2 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'reject', reason: 'local gene with same ID already exists' });\n a2aProto.getTransport().send(dm2);\n } catch (e) {}\n }\n process.stdout.write('conflict_keep_local_gene=' + id + '\\n');\n return;\n }\n\n assetStore.upsertGene(promoted);\n if (emitDecisions) {\n try {\n var dm3 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'gene promoted after safety audit' });\n a2aProto.getTransport().send(dm3);\n } catch (e) {}\n }\n process.stdout.write('promoted_gene=' + id + '\\n');\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
185 "inputSchema": {},
186 "outputSchema": null,
187 "icons": null,
188 "annotations": null,
189 "meta": null,
190 "execution": null
191 },
192 {
193 "name": "build_public.js",
194 "title": null,
195 "description": "Script: build_public.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, 'utf8'));\n}\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction rmDir(dir) {\n if (!fs.existsSync(dir)) return;\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\nfunction normalizePosix(p) {\n return p.split(path.sep).join('/');\n}\n\nfunction isUnder(child, parent) {\n const rel = path.relative(parent, child);\n return !!rel && !rel.startsWith('..') && !path.isAbsolute(rel);\n}\n\nfunction listFilesRec(dir) {\n const out = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const ent of entries) {\n const p = path.join(dir, ent.name);\n if (ent.isDirectory()) out.push(...listFilesRec(p));\n else if (ent.isFile()) out.push(p);\n }\n return out;\n}\n\nfunction globToRegex(glob) {\n // Supports \"*\" within a single segment and \"**\" for any depth.\n const norm = normalizePosix(glob);\n const parts = norm.split('/').filter(p => p.length > 0);\n const out = [];\n\n for (const part of parts) {\n if (part === '**') {\n // any number of path segments\n out.push('(?:.*)');\n continue;\n }\n // Escape regex special chars, then expand \"*\" wildcards within segment.\n const esc = part.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*');\n out.push(esc);\n }\n\n const re = out.join('\\\\/');\n return new RegExp(`^${re}$`);\n}\n\nfunction matchesAnyGlobs(relPath, globs) {\n const p = normalizePosix(relPath);\n for (const g of globs || []) {\n const re = globToRegex(g);\n if (re.test(p)) return true;\n }\n return false;\n}\n\nfunction copyFile(srcAbs, destAbs) {\n ensureDir(path.dirname(destAbs));\n fs.copyFileSync(srcAbs, destAbs);\n}\n\nfunction copyEntry(spec, outDirAbs) {\n const copied = [];\n\n // Directory glob\n if (spec.includes('*')) {\n const all = listFilesRec(REPO_ROOT);\n const includeRe = globToRegex(spec);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(REPO_ROOT, abs));\n if (!includeRe.test(rel)) continue;\n const destAbs = path.join(outDirAbs, rel);\n copyFile(abs, destAbs);\n copied.push(rel);\n }\n return copied;\n }\n\n const srcAbs = path.join(REPO_ROOT, spec);\n if (!fs.existsSync(srcAbs)) return [];\n\n const st = fs.statSync(srcAbs);\n if (st.isFile()) {\n const rel = normalizePosix(spec);\n copyFile(srcAbs, path.join(outDirAbs, rel));\n copied.push(rel);\n return copied;\n }\n if (st.isDirectory()) {\n const files = listFilesRec(srcAbs);\n for (const abs of files) {\n const rel = normalizePosix(path.relative(REPO_ROOT, abs));\n copyFile(abs, path.join(outDirAbs, rel));\n copied.push(rel);\n }\n }\n return copied;\n}\n\nfunction applyRewrite(outDirAbs, rewrite) {\n const rules = rewrite || {};\n for (const [relFile, cfg] of Object.entries(rules)) {\n const target = path.join(outDirAbs, relFile);\n if (!fs.existsSync(target)) continue;\n let content = fs.readFileSync(target, 'utf8');\n const reps = (cfg && cfg.replace) || [];\n for (const r of reps) {\n const from = String(r.from || '');\n const to = String(r.to || '');\n if (!from) continue;\n content = content.split(from).join(to);\n }\n fs.writeFileSync(target, content, 'utf8');\n }\n}\n\nfunction rewritePackageJson(outDirAbs) {\n const p = path.join(outDirAbs, 'package.json');\n if (!fs.existsSync(p)) return;\n try {\n const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));\n pkg.scripts = {\n start: 'node index.js',\n run: 'node index.js run',\n solidify: 'node index.js solidify',\n 'a2a:export': 'node scripts/a2a_export.js',\n 'a2a:ingest': 'node scripts/a2a_ingest.js',\n 'a2a:promote': 'node scripts/a2a_promote.js',\n };\n fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\\n', 'utf8');\n } catch (e) {\n // ignore\n }\n}\n\nfunction parseSemver(v) {\n const m = String(v || '').trim().match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!m) return null;\n return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };\n}\n\nfunction formatSemver(x) {\n return `${x.major}.${x.minor}.${x.patch}`;\n}\n\nfunction bumpSemver(base, bump) {\n const v = parseSemver(base);\n if (!v) return null;\n if (bump === 'major') return `${v.major + 1}.0.0`;\n if (bump === 'minor') return `${v.major}.${v.minor + 1}.0`;\n if (bump === 'patch') return `${v.major}.${v.minor}.${v.patch + 1}`;\n return formatSemver(v);\n}\n\nfunction git(cmd) {\n return execSync(cmd, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n}\n\nfunction getBaseReleaseCommit() {\n // Prefer last \"prepare vX.Y.Z\" commit; fallback to HEAD~50 range later.\n try {\n const hash = git('git log -n 1 --pretty=%H --grep=\"chore(release): prepare v\"');\n return hash || null;\n } catch (e) {\n return null;\n }\n}\n\nfunction getCommitSubjectsSince(baseCommit) {\n try {\n if (!baseCommit) {\n const out = git('git log -n 30 --pretty=%s');\n return out ? out.split('\\n').filter(Boolean) : [];\n }\n const out = git(`git log ${baseCommit}..HEAD --pretty=%s`);\n return out ? out.split('\\n').filter(Boolean) : [];\n } catch (e) {\n return [];\n }\n}\n\nfunction inferBumpFromSubjects(subjects) {\n const subs = (subjects || []).map(s => String(s));\n const hasBreaking = subs.some(s => /\\bBREAKING CHANGE\\b/i.test(s) || /^[a-z]+(\\(.+\\))?!:/.test(s));\n if (hasBreaking) return { bump: 'major', reason: 'breaking change marker in commit subject' };\n\n const hasFeat = subs.some(s => /^feat(\\(.+\\))?:/i.test(s));\n if (hasFeat) return { bump: 'minor', reason: 'feature commit detected (feat:)' };\n\n const hasFix = subs.some(s => /^(fix|perf)(\\(.+\\))?:/i.test(s));\n if (hasFix) return { bump: 'patch', reason: 'fix/perf commit detected' };\n\n if (subs.length === 0) return { bump: 'none', reason: 'no commits since base release commit' };\n return { bump: 'patch', reason: 'default to patch for non-breaking changes' };\n}\n\nfunction suggestVersion() {\n const pkgPath = path.join(REPO_ROOT, 'package.json');\n let baseVersion = null;\n try {\n baseVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;\n } catch (e) {}\n\n const baseCommit = getBaseReleaseCommit();\n const subjects = getCommitSubjectsSince(baseCommit);\n const decision = inferBumpFromSubjects(subjects);\n\n let suggested = null;\n if (decision.bump === 'none') suggested = baseVersion;\n else suggested = bumpSemver(baseVersion, decision.bump);\n\n return { baseVersion, baseCommit, subjects, decision, suggestedVersion: suggested };\n}\n\nfunction writePrivateSemverNote(note) {\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n fs.writeFileSync(path.join(privateDir, 'semver_suggestion.json'), JSON.stringify(note, null, 2) + '\\n', 'utf8');\n}\n\nfunction writePrivateSemverPrompt(note) {\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n const subjects = Array.isArray(note.subjects) ? note.subjects : [];\n const semverRule = [\n 'MAJOR.MINOR.PATCH',\n '- MAJOR: incompatible changes',\n '- MINOR: backward-compatible features',\n '- PATCH: backward-compatible bug fixes',\n ].join('\\n');\n\n const prompt = [\n 'You are a release versioning assistant.',\n 'Decide the next version bump using SemVer rules below.',\n '',\n semverRule,\n '',\n `Base version: ${note.baseVersion || '(unknown)'}`,\n `Base commit: ${note.baseCommit || '(unknown)'}`,\n '',\n 'Recent commit subjects (newest first):',\n ...subjects.map(s => `- ${s}`),\n '',\n 'Output JSON only:',\n '{ \"bump\": \"major|minor|patch|none\", \"suggestedVersion\": \"x.y.z\", \"reason\": [\"...\"] }',\n ].join('\\n');\n\n fs.writeFileSync(path.join(privateDir, 'semver_prompt.md'), prompt + '\\n', 'utf8');\n}\n\nfunction writeDistVersion(outDirAbs, version) {\n if (!version) return;\n const p = path.join(outDirAbs, 'package.json');\n if (!fs.existsSync(p)) return;\n try {\n const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));\n pkg.version = version;\n fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\\n', 'utf8');\n } catch (e) {}\n}\n\nfunction pruneExcluded(outDirAbs, excludeGlobs) {\n const all = listFilesRec(outDirAbs);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(outDirAbs, abs));\n if (matchesAnyGlobs(rel, excludeGlobs)) {\n fs.rmSync(abs, { force: true });\n }\n }\n}\n\nfunction validateNoPrivatePaths(outDirAbs) {\n // Basic safeguard: forbid docs/ and memory/ in output.\n const forbiddenPrefixes = ['docs/', 'memory/'];\n const all = listFilesRec(outDirAbs);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(outDirAbs, abs));\n for (const pref of forbiddenPrefixes) {\n if (rel.startsWith(pref)) {\n throw new Error(`Build validation failed: forbidden path in output: ${rel}`);\n }\n }\n }\n}\n\nfunction main() {\n const manifestPath = path.join(REPO_ROOT, 'public.manifest.json');\n const manifest = readJson(manifestPath);\n const outDir = String(manifest.outDir || 'dist-public');\n const outDirAbs = path.join(REPO_ROOT, outDir);\n\n // SemVer suggestion (private). This does not modify the source repo version.\n const semver = suggestVersion();\n writePrivateSemverNote(semver);\n writePrivateSemverPrompt(semver);\n\n rmDir(outDirAbs);\n ensureDir(outDirAbs);\n\n const include = manifest.include || [];\n const exclude = manifest.exclude || [];\n\n const copied = [];\n for (const spec of include) {\n copied.push(...copyEntry(spec, outDirAbs));\n }\n\n pruneExcluded(outDirAbs, exclude);\n applyRewrite(outDirAbs, manifest.rewrite);\n rewritePackageJson(outDirAbs);\n\n // Prefer explicit version; otherwise use suggested version.\n const releaseVersion = process.env.RELEASE_VERSION || semver.suggestedVersion;\n if (releaseVersion) writeDistVersion(outDirAbs, releaseVersion);\n\n validateNoPrivatePaths(outDirAbs);\n\n // Write build manifest for private verification (do not include in dist-public/).\n const buildInfo = {\n built_at: new Date().toISOString(),\n outDir,\n files: copied.sort(),\n };\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n fs.writeFileSync(path.join(privateDir, 'public_build_info.json'), JSON.stringify(buildInfo, null, 2) + '\\n', 'utf8');\n\n process.stdout.write(`Built public output at ${outDir}\\n`);\n if (semver && semver.suggestedVersion) {\n process.stdout.write(`Suggested version: ${semver.suggestedVersion}\\n`);\n process.stdout.write(`SemVer decision: ${semver.decision ? semver.decision.bump : 'unknown'}\\n`);\n }\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
196 "inputSchema": {},
197 "outputSchema": null,
198 "icons": null,
199 "annotations": null,
200 "meta": null,
201 "execution": null
202 },
203 {
204 "name": "gep_append_event.js",
205 "title": null,
206 "description": "Script: gep_append_event.js. Code:\nconst fs = require('fs');\nconst { appendEventJsonl } = require('../src/gep/assetStore');\n\nfunction readStdin() {\n try {\n return fs.readFileSync(0, 'utf8');\n } catch {\n return '';\n }\n}\n\nfunction readTextIfExists(p) {\n try {\n if (!p) return '';\n if (!fs.existsSync(p)) return '';\n return fs.readFileSync(p, 'utf8');\n } catch {\n return '';\n }\n}\n\nfunction parseInput(text) {\n const raw = String(text || '').trim();\n if (!raw) return [];\n\n // Accept JSON array or single JSON.\n try {\n const maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) return maybe;\n if (maybe && typeof maybe === 'object') return [maybe];\n } catch (e) {}\n\n // Fallback: JSONL.\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n const out = [];\n for (const line of lines) {\n try {\n const obj = JSON.parse(line);\n out.push(obj);\n } catch (e) {}\n }\n return out;\n}\n\nfunction isValidEvolutionEvent(ev) {\n if (!ev || ev.type !== 'EvolutionEvent') return false;\n if (!ev.id || typeof ev.id !== 'string') return false;\n // parent may be null or string\n if (!(ev.parent === null || typeof ev.parent === 'string')) return false;\n if (!ev.intent || typeof ev.intent !== 'string') return false;\n if (!Array.isArray(ev.signals)) return false;\n if (!Array.isArray(ev.genes_used)) return false;\n // GEP v1.4: mutation + personality are mandatory evolution dimensions\n if (!ev.mutation_id || typeof ev.mutation_id !== 'string') return false;\n if (!ev.personality_state || typeof ev.personality_state !== 'object') return false;\n if (ev.personality_state.type !== 'PersonalityState') return false;\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n const v = Number(ev.personality_state[k]);\n if (!Number.isFinite(v) || v < 0 || v > 1) return false;\n }\n if (!ev.blast_radius || typeof ev.blast_radius !== 'object') return false;\n if (!Number.isFinite(Number(ev.blast_radius.files))) return false;\n if (!Number.isFinite(Number(ev.blast_radius.lines))) return false;\n if (!ev.outcome || typeof ev.outcome !== 'object') return false;\n if (!ev.outcome.status || typeof ev.outcome.status !== 'string') return false;\n const score = Number(ev.outcome.score);\n if (!Number.isFinite(score) || score < 0 || score > 1) return false;\n\n // capsule_id is optional, but if present must be string or null.\n if (!('capsule_id' in ev)) return true;\n return ev.capsule_id === null || typeof ev.capsule_id === 'string';\n}\n\nfunction main() {\n const args = process.argv.slice(2);\n const inputPath = args.find(a => a && !a.startsWith('--')) || '';\n const text = inputPath ? readTextIfExists(inputPath) : readStdin();\n const items = parseInput(text);\n\n let appended = 0;\n for (const it of items) {\n if (!isValidEvolutionEvent(it)) continue;\n appendEventJsonl(it);\n appended += 1;\n }\n\n process.stdout.write(`appended=${appended}\\n`);\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e && e.message ? e.message : String(e)}\\n`);\n process.exit(1);\n}\n\n",
207 "inputSchema": {},
208 "outputSchema": null,
209 "icons": null,
210 "annotations": null,
211 "meta": null,
212 "execution": null
213 },
214 {
215 "name": "recover_loop.js",
216 "title": null,
217 "description": "Script: recover_loop.js. Code:\n#!/usr/bin/env node\n/* eslint-disable no-console */\nconst fs = require('fs');\nconst path = require('path');\nconst { spawnSync } = require('child_process');\n\nfunction exists(p) {\n try {\n return fs.existsSync(p);\n } catch (e) {\n return false;\n }\n}\n\nfunction sleepMs(ms) {\n const n = Number(ms);\n const t = Number.isFinite(n) ? Math.max(0, n) : 0;\n if (t <= 0) return;\n spawnSync('sleep', [String(Math.ceil(t / 1000))], { stdio: 'ignore' });\n}\n\nfunction resolveWorkspaceRoot() {\n // In OpenClaw exec, cwd is usually the workspace root.\n // Keep it simple: do not try to walk up arbitrarily.\n return process.cwd();\n}\n\nfunction resolveEvolverEntry(workspaceRoot) {\n const candidates = [\n path.join(workspaceRoot, 'skills', 'evolver', 'index.js'),\n path.join(workspaceRoot, 'skills', 'capability-evolver', 'index.js'),\n ];\n for (const p of candidates) {\n if (exists(p)) return p;\n }\n return null;\n}\n\nfunction main() {\n const waitMs = parseInt(String(process.env.EVOLVER_RECOVER_WAIT_MS || '10000'), 10);\n const wait = Number.isFinite(waitMs) ? Math.max(0, waitMs) : 10000;\n\n console.log(`[RECOVERY] Waiting ${wait}ms before restart...`);\n sleepMs(wait);\n\n const workspaceRoot = resolveWorkspaceRoot();\n const entry = resolveEvolverEntry(workspaceRoot);\n if (!entry) {\n console.error('[RECOVERY] Failed: cannot locate evolver entry under skills/.');\n process.exit(2);\n }\n\n console.log(`[RECOVERY] Restarting loop via ${path.relative(workspaceRoot, entry)} ...`);\n const r = spawnSync(process.execPath, [entry, '--loop'], { stdio: 'inherit' });\n process.exit(typeof r.status === 'number' ? r.status : 1);\n}\n\nif (require.main === module) {\n main();\n}\n\n",
218 "inputSchema": {},
219 "outputSchema": null,
220 "icons": null,
221 "annotations": null,
222 "meta": null,
223 "execution": null
224 },
225 {
226 "name": "extract_log.js",
227 "title": null,
228 "description": "Script: extract_log.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst LOG_FILE = path.join(REPO_ROOT, 'memory', 'mad_dog_evolution.log');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_history.md');\n\nfunction parseLog() {\n if (!fs.existsSync(LOG_FILE)) {\n console.log(\"Log file not found.\");\n return;\n }\n\n const content = fs.readFileSync(LOG_FILE, 'utf8');\n const lines = content.split('\\n');\n \n const reports = [];\n let currentTimestamp = null;\n\n // Regex for Feishu command\n // node skills/feishu-card/send.js --title \"...\" --color ... --text \"...\"\n const cmdRegex = /node skills\\/feishu-card\\/send\\.js --title \"(.*?)\" --color \\w+ --text \"(.*?)\"/;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // 1. Capture Timestamp\n if (line.includes('Cycle Start:')) {\n // Format: Cycle Start: Sun Feb 1 19:17:44 UTC 2026\n const dateStr = line.split('Cycle Start: ')[1].trim();\n try {\n currentTimestamp = new Date(dateStr);\n } catch (e) {\n currentTimestamp = null;\n }\n }\n\n const match = line.match(cmdRegex);\n if (match) {\n const title = match[1];\n let text = match[2];\n \n // Clean up text (unescape newlines)\n text = text.replace(/\\\\n/g, '\\n').replace(/\\\\\"/g, '\"');\n\n if (currentTimestamp) {\n reports.push({\n ts: currentTimestamp,\n title: title,\n text: text,\n id: title // Cycle ID is in title\n });\n }\n }\n }\n\n // Deduplicate by ID (keep latest timestamp?)\n const uniqueReports = {};\n reports.forEach(r => {\n uniqueReports[r.id] = r;\n });\n\n const sortedReports = Object.values(uniqueReports).sort((a, b) => a.ts - b.ts);\n\n let md = \"# Evolution History (Extracted)\\n\\n\";\n sortedReports.forEach(r => {\n // Convert to CST (UTC+8)\n const cstDate = r.ts.toLocaleString(\"zh-CN\", {\n timeZone: \"Asia/Shanghai\", \n hour12: false,\n year: 'numeric', month: '2-digit', day: '2-digit',\n hour: '2-digit', minute: '2-digit', second: '2-digit'\n });\n\n md += `### ${r.title} (${cstDate})\\n`;\n md += `${r.text}\\n\\n`;\n md += `---\\n\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(`Extracted ${sortedReports.length} reports to ${OUT_FILE}`);\n}\n\nparseLog();\n\n",
229 "inputSchema": {},
230 "outputSchema": null,
231 "icons": null,
232 "annotations": null,
233 "meta": null,
234 "execution": null
235 },
236 {
237 "name": "generate_history.js",
238 "title": null,
239 "description": "Script: generate_history.js. Code:\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\n\n// Separator for git log parsing (something unlikely to be in commit messages)\nconst SEP = '|||';\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\ntry {\n // Git command:\n // --reverse: Oldest to Newest (Time Sequence)\n // --grep: Filter by keyword\n // --format: Hash, Date (ISO), Author, Subject, Body\n const cmd = `git log --reverse --grep=\"Evolution\" --format=\"%H${SEP}%ai${SEP}%an${SEP}%s${SEP}%b\"`;\n \n console.log('Executing git log...');\n const output = execSync(cmd, { \n encoding: 'utf8', \n cwd: REPO_ROOT,\n maxBuffer: 1024 * 1024 * 10 // 10MB buffer just in case\n });\n\n const entries = output.split('\\n').filter(line => line.trim().length > 0);\n \n let markdown = '# Evolution History (Time Sequence)\\n\\n';\n markdown += '> Filter: \"Evolution\"\\n';\n markdown += '> Timezone: CST (UTC+8)\\n\\n';\n \n let count = 0;\n\n entries.forEach(entry => {\n const parts = entry.split(SEP);\n if (parts.length < 4) return;\n\n const hash = parts[0];\n const dateStr = parts[1];\n const author = parts[2];\n const subject = parts[3];\n const body = parts[4] || '';\n\n // Parse Date and Convert to UTC+8\n const date = new Date(dateStr);\n // Add 8 hours (28800000 ms) to UTC timestamp to shift it\n // Then formatting it as ISO will look like UTC but represent CST values\n const cstDate = new Date(date.getTime() + 8 * 60 * 60 * 1000);\n \n // Format: YYYY-MM-DD HH:mm:ss\n const timeStr = cstDate.toISOString().replace('T', ' ').substring(0, 19);\n\n markdown += `## ${timeStr}\\n`;\n markdown += `- Commit: \\`${hash.substring(0, 7)}\\`\\n`;\n markdown += `- Subject: ${subject}\\n`;\n \n if (body.trim()) {\n // Indent body for better readability\n const formattedBody = body.trim().split('\\n').map(l => `> ${l}`).join('\\n');\n markdown += `- Details:\\n${formattedBody}\\n`;\n }\n markdown += '\\n';\n count++;\n });\n\n const outDir = path.join(REPO_ROOT, 'memory');\n if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\n const outPath = path.join(outDir, 'evolution_history.md');\n fs.writeFileSync(outPath, markdown);\n \n console.log(`Successfully generated report with ${count} entries.`);\n console.log(`Saved to: ${outPath}`);\n\n} catch (e) {\n console.error('Error generating history:', e.message);\n process.exit(1);\n}\n\n",
240 "inputSchema": {},
241 "outputSchema": null,
242 "icons": null,
243 "annotations": null,
244 "meta": null,
245 "execution": null
246 },
247 {
248 "name": "suggest_version.js",
249 "title": null,
250 "description": "Script: suggest_version.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction parseSemver(v) {\n const m = String(v || '').trim().match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!m) return null;\n return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };\n}\n\nfunction bumpSemver(base, bump) {\n const v = parseSemver(base);\n if (!v) return null;\n if (bump === 'major') return `${v.major + 1}.0.0`;\n if (bump === 'minor') return `${v.major}.${v.minor + 1}.0`;\n if (bump === 'patch') return `${v.major}.${v.minor}.${v.patch + 1}`;\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n\nfunction git(cmd) {\n return execSync(cmd, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n}\n\nfunction getBaseReleaseCommit() {\n try {\n const hash = git('git log -n 1 --pretty=%H --grep=\"chore(release): prepare v\"');\n return hash || null;\n } catch (e) {\n return null;\n }\n}\n\nfunction getCommitSubjectsSince(baseCommit) {\n try {\n if (!baseCommit) {\n const out = git('git log -n 30 --pretty=%s');\n return out ? out.split('\\n').filter(Boolean) : [];\n }\n const out = git(`git log ${baseCommit}..HEAD --pretty=%s`);\n return out ? out.split('\\n').filter(Boolean) : [];\n } catch (e) {\n return [];\n }\n}\n\nfunction inferBumpFromSubjects(subjects) {\n const subs = (subjects || []).map(s => String(s));\n const hasBreaking = subs.some(s => /\\bBREAKING CHANGE\\b/i.test(s) || /^[a-z]+(\\(.+\\))?!:/.test(s));\n if (hasBreaking) return { bump: 'major', reason: 'breaking change marker in commit subject' };\n\n const hasFeat = subs.some(s => /^feat(\\(.+\\))?:/i.test(s));\n if (hasFeat) return { bump: 'minor', reason: 'feature commit detected (feat:)' };\n\n const hasFix = subs.some(s => /^(fix|perf)(\\(.+\\))?:/i.test(s));\n if (hasFix) return { bump: 'patch', reason: 'fix/perf commit detected' };\n\n if (subs.length === 0) return { bump: 'none', reason: 'no commits since base release commit' };\n return { bump: 'patch', reason: 'default to patch for non-breaking changes' };\n}\n\nfunction main() {\n const pkgPath = path.join(REPO_ROOT, 'package.json');\n const baseVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;\n\n const baseCommit = getBaseReleaseCommit();\n const subjects = getCommitSubjectsSince(baseCommit);\n const decision = inferBumpFromSubjects(subjects);\n const suggestedVersion = decision.bump === 'none' ? baseVersion : bumpSemver(baseVersion, decision.bump);\n\n const out = { baseVersion, baseCommit, subjects, decision, suggestedVersion };\n const memDir = path.join(REPO_ROOT, 'memory');\n ensureDir(memDir);\n fs.writeFileSync(path.join(memDir, 'semver_suggestion.json'), JSON.stringify(out, null, 2) + '\\n', 'utf8');\n process.stdout.write(JSON.stringify(out, null, 2) + '\\n');\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
251 "inputSchema": {},
252 "outputSchema": null,
253 "icons": null,
254 "annotations": null,
255 "meta": null,
256 "execution": null
257 },
258 {
259 "name": "analyze_by_skill.js",
260 "title": null,
261 "description": "Script: analyze_by_skill.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst LOG_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_detailed_report.md');\n\nfunction analyzeEvolution() {\n if (!fs.existsSync(LOG_FILE)) {\n console.error(\"Source file missing.\");\n return;\n }\n\n const content = fs.readFileSync(LOG_FILE, 'utf8');\n // Split by divider\n const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);\n\n const skillUpdates = {}; // Map<SkillName, Array<Changes>>\n const generalUpdates = []; // Array<Changes>\n\n // Regex to detect skills/paths\n // e.g. `skills/feishu-card/send.js` or **Target**: `skills/git-sync`\n const skillRegex = /skills\\/([a-zA-Z0-9\\-_]+)/;\n const actionRegex = /Action:\\s*([\\s\\S]*?)(?=\\n\\n|\\n[A-Z]|$)/i; // Capture Action text\n const statusRegex = /Status:\\s*\\[?([A-Z\\s_]+)\\]?/i;\n\n entries.forEach(entry => {\n // Extract basic info\n const statusMatch = entry.match(statusRegex);\n const status = statusMatch ? statusMatch[1].trim().toUpperCase() : 'UNKNOWN';\n \n // Skip routine checks if we want a *detailed evolution* report (focus on changes)\n // But user asked for \"what happened\", so routine scans might be boring unless they found something.\n // Let's filter out \"STABILITY\" or \"RUNNING\" unless there is a clear \"Mutated\" or \"Fixed\" keyword.\n const isInteresting = \n entry.includes('Fixed') || \n entry.includes('Hardened') || \n entry.includes('Optimized') || \n entry.includes('Patched') || \n entry.includes('Created') || \n entry.includes('Added') ||\n status === 'SUCCESS' ||\n status === 'COMPLETED';\n\n if (!isInteresting) return;\n\n // Find associated skill\n const skillMatch = entry.match(skillRegex);\n let skillName = 'General / System';\n if (skillMatch) {\n skillName = skillMatch[1];\n } else {\n // Try heuristics\n if (entry.toLowerCase().includes('feishu card')) skillName = 'feishu-card';\n else if (entry.toLowerCase().includes('git sync')) skillName = 'git-sync';\n else if (entry.toLowerCase().includes('logger')) skillName = 'interaction-logger';\n else if (entry.toLowerCase().includes('evolve')) skillName = 'capability-evolver';\n }\n\n // Extract description\n let description = \"\";\n const actionMatch = entry.match(actionRegex);\n if (actionMatch) {\n description = actionMatch[1].trim();\n } else {\n // Fallback: take lines that look like bullet points or text after header\n const lines = entry.split('\\n');\n description = lines.filter(l => l.match(/^[\u2022\\-\\*]|\\w/)).slice(1).join('\\n').trim();\n }\n\n // Clean up description (remove duplicate \"Action:\" prefix if captured)\n description = description.replace(/^Action:\\s*/i, '');\n\n if (!skillUpdates[skillName]) skillUpdates[skillName] = [];\n \n // Dedup descriptions slightly (simple check)\n const isDuplicate = skillUpdates[skillName].some(u => u.desc.includes(description.substring(0, 20)));\n if (!isDuplicate) {\n // Extract Date if possible\n const dateMatch = entry.match(/\\((\\d{4}\\/\\d{1,2}\\/\\d{1,2}.*?)\\)/);\n const date = dateMatch ? dateMatch[1] : 'Unknown';\n \n skillUpdates[skillName].push({\n date,\n status,\n desc: description\n });\n }\n });\n\n // Generate Markdown\n let md = \"# Detailed Evolution Report (By Skill)\\n\\n> Comprehensive breakdown of system changes.\\n\\n\";\n\n // Sort skills alphabetically\n const sortedSkills = Object.keys(skillUpdates).sort();\n\n sortedSkills.forEach(skill => {\n md += `## ${skill}\\n`;\n const updates = skillUpdates[skill];\n \n updates.forEach(u => {\n // Icon based on content\n let icon = '*';\n const lowerDesc = u.desc.toLowerCase();\n if (lowerDesc.includes('optimiz')) icon = '[optimize]';\n if (lowerDesc.includes('secur') || lowerDesc.includes('harden') || lowerDesc.includes('permission')) icon = '[security]';\n if (lowerDesc.includes('fix') || lowerDesc.includes('patch')) icon = '[repair]';\n if (lowerDesc.includes('creat') || lowerDesc.includes('add')) icon = '[add]';\n\n md += `### ${icon} ${u.date}\\n`;\n md += `${u.desc}\\n\\n`;\n });\n md += `---\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(`Generated report for ${sortedSkills.length} skills.`);\n}\n\nanalyzeEvolution();\n\n",
262 "inputSchema": {},
263 "outputSchema": null,
264 "icons": null,
265 "annotations": null,
266 "meta": null,
267 "execution": null
268 },
269 {
270 "name": "evolve.js",
271 "title": null,
272 "description": "Script: evolve.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst os = require('os');\nconst { execSync } = require('child_process');\nconst { getRepoRoot, getMemoryDir } = require('./gep/paths');\nconst { extractSignals, analyzeRecentHistory } = require('./gep/signals');\nconst {\n loadGenes,\n loadCapsules,\n readAllEvents,\n getLastEventId,\n appendCandidateJsonl,\n readRecentCandidates,\n readRecentExternalCandidates,\n} = require('./gep/assetStore');\nconst { selectGeneAndCapsule, matchPatternToSignals } = require('./gep/selector');\nconst { buildGepPrompt } = require('./gep/prompt');\nconst { resolveStrategy } = require('./gep/strategy');\nconst { extractCapabilityCandidates, renderCandidatesPreview } = require('./gep/candidates');\nconst {\n getMemoryAdvice,\n recordSignalSnapshot,\n recordHypothesis,\n recordAttempt,\n recordOutcomeFromState,\n memoryGraphPath,\n} = require('./gep/memoryGraph');\nconst { readStateForSolidify, writeStateForSolidify } = require('./gep/solidify');\nconst { buildMutation, isHighRiskMutationAllowed } = require('./gep/mutation');\nconst { selectPersonalityForRun } = require('./gep/personality');\nconst { clip, writePromptArtifact, renderSessionsSpawnCall } = require('./gep/bridge');\nconst { getEvolutionDir } = require('./gep/paths');\n\nconst REPO_ROOT = getRepoRoot();\n\n// Load environment variables from repo root\ntry {\n require('dotenv').config({ path: path.join(REPO_ROOT, '.env'), quiet: true });\n} catch (e) {\n // dotenv might not be installed or .env missing, proceed gracefully\n}\n\n// Configuration from CLI flags or Env\nconst ARGS = process.argv.slice(2);\nconst IS_REVIEW_MODE = ARGS.includes('--review');\nconst IS_DRY_RUN = ARGS.includes('--dry-run');\nconst IS_RANDOM_DRIFT = ARGS.includes('--drift') || String(process.env.RANDOM_DRIFT || '').toLowerCase() === 'true';\n\n// Default Configuration\nconst MEMORY_DIR = getMemoryDir();\nconst AGENT_NAME = process.env.AGENT_NAME || 'main';\nconst AGENT_SESSIONS_DIR = path.join(os.homedir(), `.openclaw/agents/${AGENT_NAME}/sessions`);\nconst TODAY_LOG = path.join(MEMORY_DIR, new Date().toISOString().split('T')[0] + '.md');\n\n// Ensure memory directory exists so state/cache writes work.\ntry {\n if (!fs.existsSync(MEMORY_DIR)) fs.mkdirSync(MEMORY_DIR, { recursive: true });\n} catch (e) {}\n\nfunction formatSessionLog(jsonlContent) {\n const result = [];\n const lines = jsonlContent.split('\\n');\n let lastLine = '';\n let repeatCount = 0;\n\n const flushRepeats = () => {\n if (repeatCount > 0) {\n result.push(` ... [Repeated ${repeatCount} times] ...`);\n repeatCount = 0;\n }\n };\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const data = JSON.parse(line);\n let entry = '';\n\n if (data.type === 'message' && data.message) {\n const role = (data.message.role || 'unknown').toUpperCase();\n let content = '';\n if (Array.isArray(data.message.content)) {\n content = data.message.content\n .map(c => {\n if (c.type === 'text') return c.text;\n if (c.type === 'toolCall') return `[TOOL: ${c.name}]`;\n return '';\n })\n .join(' ');\n } else if (typeof data.message.content === 'string') {\n content = data.message.content;\n } else {\n content = JSON.stringify(data.message.content);\n }\n\n // Capture LLM errors from errorMessage field (e.g. \"Unsupported MIME type: image/gif\")\n if (data.message.errorMessage) {\n const errMsg = typeof data.message.errorMessage === 'string'\n ? data.message.errorMessage\n : JSON.stringify(data.message.errorMessage);\n content = `[LLM ERROR] ${errMsg.replace(/\\n+/g, ' ').slice(0, 300)}`;\n }\n\n // Filter: Skip Heartbeats to save noise\n if (content.trim() === 'HEARTBEAT_OK') continue;\n if (content.includes('NO_REPLY') && !data.message.errorMessage) continue;\n\n // Clean up newlines for compact reading\n content = content.replace(/\\n+/g, ' ').slice(0, 300);\n entry = `**${role}**: ${content}`;\n } else if (data.type === 'tool_result' || (data.message && data.message.role === 'toolResult')) {\n // Filter: Skip generic success results or short uninformative ones\n // Only show error or significant output\n let resContent = '';\n\n // Robust extraction: Handle structured tool results (e.g. sessions_spawn) that lack 'output'\n if (data.tool_result) {\n if (data.tool_result.output) {\n resContent = data.tool_result.output;\n } else {\n resContent = JSON.stringify(data.tool_result);\n }\n }\n\n if (data.content) resContent = typeof data.content === 'string' ? data.content : JSON.stringify(data.content);\n\n if (resContent.length < 50 && (resContent.includes('success') || resContent.includes('done'))) continue;\n if (resContent.trim() === '' || resContent === '{}') continue;\n\n // Improvement: Show snippet of result (especially errors) instead of hiding it\n const preview = resContent.replace(/\\n+/g, ' ').slice(0, 200);\n entry = `[TOOL RESULT] ${preview}${resContent.length > 200 ? '...' : ''}`;\n }\n\n if (entry) {\n if (entry === lastLine) {\n repeatCount++;\n } else {\n flushRepeats();\n result.push(entry);\n lastLine = entry;\n }\n }\n } catch (e) {\n continue;\n }\n }\n flushRepeats();\n return result.join('\\n');\n}\n\nfunction readRealSessionLog() {\n try {\n if (!fs.existsSync(AGENT_SESSIONS_DIR)) return '[NO SESSION LOGS FOUND]';\n\n const now = Date.now();\n const ACTIVE_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours\n const TARGET_BYTES = 120000;\n const PER_SESSION_BYTES = 20000; // Read tail of each active session\n\n // Find ALL active sessions (modified in last 24h), sorted newest first\n let files = fs\n .readdirSync(AGENT_SESSIONS_DIR)\n .filter(f => f.endsWith('.jsonl') && !f.includes('.lock'))\n .map(f => {\n try {\n const st = fs.statSync(path.join(AGENT_SESSIONS_DIR, f));\n return { name: f, time: st.mtime.getTime(), size: st.size };\n } catch (e) {\n return null;\n }\n })\n .filter(f => f && (now - f.time) < ACTIVE_WINDOW_MS)\n .sort((a, b) => b.time - a.time); // Newest first\n\n if (files.length === 0) return '[NO JSONL FILES]';\n\n // Skip evolver's own sessions to avoid self-reference loops\n const nonEvolverFiles = files.filter(f => !f.name.startsWith('evolver_hand_'));\n const activeFiles = nonEvolverFiles.length > 0 ? nonEvolverFiles : files.slice(0, 1);\n\n // Read from multiple active sessions (up to 6) to get a full picture\n const maxSessions = Math.min(activeFiles.length, 6);\n const sections = [];\n let totalBytes = 0;\n\n for (let i = 0; i < maxSessions && totalBytes < TARGET_BYTES; i++) {\n const f = activeFiles[i];\n const bytesLeft = TARGET_BYTES - totalBytes;\n const readSize = Math.min(PER_SESSION_BYTES, bytesLeft);\n const raw = readRecentLog(path.join(AGENT_SESSIONS_DIR, f.name), readSize);\n const formatted = formatSessionLog(raw);\n if (formatted.trim()) {\n sections.push(`--- SESSION (${f.name}) ---\\n${formatted}`);\n totalBytes += formatted.length;\n }\n }\n\n let content = sections.join('\\n\\n');\n\n return content;\n } catch (e) {\n return `[ERROR READING SESSION LOGS: ${e.message}]`;\n }\n}\n\nfunction readRecentLog(filePath, size = 10000) {\n try {\n if (!fs.existsSync(filePath)) return `[MISSING] ${filePath}`;\n const stats = fs.statSync(filePath);\n const start = Math.max(0, stats.size - size);\n const buffer = Buffer.alloc(stats.size - start);\n const fd = fs.openSync(filePath, 'r');\n fs.readSync(fd, buffer, 0, buffer.length, start);\n fs.closeSync(fd);\n return buffer.toString('utf8');\n } catch (e) {\n return `[ERROR READING ${filePath}: ${e.message}]`;\n }\n}\n\nfunction checkSystemHealth() {\n const report = [];\n try {\n // Uptime & Node Version\n const uptime = (os.uptime() / 3600).toFixed(1);\n report.push(`Uptime: ${uptime}h`);\n report.push(`Node: ${process.version}`);\n\n // Memory Usage (RSS)\n const mem = process.memoryUsage();\n const rssMb = (mem.rss / 1024 / 1024).toFixed(1);\n report.push(`Agent RSS: ${rssMb}MB`);\n\n // Optimization: Use native Node.js fs.statfsSync instead of spawning 'df'\n if (fs.statfsSync) {\n const stats = fs.statfsSync('/');\n const total = stats.blocks * stats.bsize;\n const free = stats.bfree * stats.bsize;\n const used = total - free;\n const freeGb = (free / 1024 / 1024 / 1024).toFixed(1);\n const usedPercent = Math.round((used / total) * 100);\n report.push(`Disk: ${usedPercent}% (${freeGb}G free)`);\n }\n } catch (e) {}\n\n try {\n // Process count: Attempt pgrep first (faster), fallback to ps\n try {\n const pgrep = execSync('pgrep -c node', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n report.push(`Node Processes: ${pgrep.trim()}`);\n } catch (e) {\n // Fallback to ps if pgrep fails/missing\n const ps = execSync('ps aux | grep node | grep -v grep | wc -l', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n report.push(`Node Processes: ${ps.trim()}`);\n }\n } catch (e) {}\n\n // Integration Health Checks (Env Vars)\n try {\n const issues = [];\n if (!process.env.GEMINI_API_KEY) issues.push('Gemini Key Missing');\n\n // Generic Integration Status Check (Decoupled)\n if (process.env.INTEGRATION_STATUS_CMD) {\n try {\n const status = execSync(process.env.INTEGRATION_STATUS_CMD, {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n if (status.trim()) issues.push(status.trim());\n } catch (e) {}\n }\n\n if (issues.length > 0) {\n report.push(`Integrations: ${issues.join(', ')}`);\n } else {\n report.push('Integrations: Nominal');\n }\n } catch (e) {}\n\n return report.length ? report.join(' | ') : 'Health Check Unavailable';\n}\n\nfunction getMutationDirective(logContent) {\n const strategy = resolveStrategy();\n const errorMatches = logContent.match(/\\[ERROR|Error:|Exception:|FAIL|Failed|\"isError\":true/gi) || [];\n const errorCount = errorMatches.length;\n const isUnstable = errorCount > 2;\n\n // Strategy-aware intent recommendation\n var recommendedIntent;\n if (strategy.name === 'repair-only') {\n recommendedIntent = 'repair';\n } else if (strategy.name === 'innovate' && !isUnstable) {\n recommendedIntent = 'innovate';\n } else if (isUnstable && strategy.repair >= 0.3) {\n recommendedIntent = 'repair';\n } else if (isUnstable) {\n recommendedIntent = 'optimize';\n } else {\n // Stable system: pick based on strategy weights (highest weight wins)\n var weights = [\n { intent: 'innovate', w: strategy.innovate },\n { intent: 'optimize', w: strategy.optimize },\n { intent: 'repair', w: strategy.repair },\n ];\n weights.sort(function(a, b) { return b.w - a.w; });\n recommendedIntent = weights[0].intent;\n }\n\n return `\n[Signal Hints]\n- recent_error_count: ${errorCount}\n- stability: ${isUnstable ? 'unstable' : 'stable'}\n- strategy: ${strategy.label} (${strategy.name})\n- target_allocation: ${Math.round(strategy.innovate * 100)}% innovate / ${Math.round(strategy.optimize * 100)}% optimize / ${Math.round(strategy.repair * 100)}% repair\n- recommended_intent: ${recommendedIntent}\n`;\n}\n\nconst STATE_FILE = path.join(getEvolutionDir(), 'evolution_state.json');\n// Read MEMORY.md and USER.md from the WORKSPACE root (not the evolver plugin dir).\n// This avoids symlink breakage if the target file is temporarily deleted.\nconst WORKSPACE_ROOT = process.env.OPENCLAW_WORKSPACE || path.resolve(REPO_ROOT, '../..');\nconst ROOT_MEMORY = path.join(WORKSPACE_ROOT, 'MEMORY.md');\nconst DIR_MEMORY = path.join(MEMORY_DIR, 'MEMORY.md');\nconst MEMORY_FILE = fs.existsSync(ROOT_MEMORY) ? ROOT_MEMORY : (fs.existsSync(DIR_MEMORY) ? DIR_MEMORY : ROOT_MEMORY);\nconst USER_FILE = path.join(WORKSPACE_ROOT, 'USER.md');\n\nfunction readMemorySnippet() {\n try {\n if (!fs.existsSync(MEMORY_FILE)) return '[MEMORY.md MISSING]';\n const content = fs.readFileSync(MEMORY_FILE, 'utf8');\n // Optimization: Increased limit from 2000 to 50000 for modern context windows\n return content.length > 50000\n ? content.slice(0, 50000) + `\\n... [TRUNCATED: ${content.length - 50000} chars remaining]`\n : content;\n } catch (e) {\n return '[ERROR READING MEMORY.md]';\n }\n}\n\nfunction readUserSnippet() {\n try {\n if (!fs.existsSync(USER_FILE)) return '[USER.md MISSING]';\n return fs.readFileSync(USER_FILE, 'utf8');\n } catch (e) {\n return '[ERROR READING USER.md]';\n }\n}\n\nfunction getNextCycleId() {\n let state = { cycleCount: 0, lastRun: 0 };\n try {\n if (fs.existsSync(STATE_FILE)) {\n state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));\n }\n } catch (e) {}\n\n state.cycleCount = (state.cycleCount || 0) + 1;\n state.lastRun = Date.now();\n\n try {\n fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));\n } catch (e) {}\n\n return String(state.cycleCount).padStart(4, '0');\n}\n\nfunction performMaintenance() {\n try {\n if (!fs.existsSync(AGENT_SESSIONS_DIR)) return;\n\n // Count files\n const files = fs.readdirSync(AGENT_SESSIONS_DIR).filter(f => f.endsWith('.jsonl'));\n if (files.length < 100) return; // Limit before cleanup\n\n console.log(`[Maintenance] Found ${files.length} session logs. Archiving old ones...`);\n\n const ARCHIVE_DIR = path.join(AGENT_SESSIONS_DIR, 'archive');\n if (!fs.existsSync(ARCHIVE_DIR)) fs.mkdirSync(ARCHIVE_DIR, { recursive: true });\n\n // Sort by time (oldest first)\n const fileStats = files\n .map(f => {\n try {\n return { name: f, time: fs.statSync(path.join(AGENT_SESSIONS_DIR, f)).mtime.getTime() };\n } catch (e) {\n return null;\n }\n })\n .filter(Boolean)\n .sort((a, b) => a.time - b.time);\n\n // Keep last 50 files, archive the rest\n const toArchive = fileStats.slice(0, fileStats.length - 50);\n\n for (const file of toArchive) {\n const oldPath = path.join(AGENT_SESSIONS_DIR, file.name);\n const newPath = path.join(ARCHIVE_DIR, file.name);\n fs.renameSync(oldPath, newPath);\n }\n console.log(`[Maintenance] Archived ${toArchive.length} logs to ${ARCHIVE_DIR}`);\n } catch (e) {\n console.error(`[Maintenance] Error: ${e.message}`);\n }\n}\n\nfunction sleepMs(ms) {\n const t = Number(ms);\n const n = Number.isFinite(t) ? Math.max(0, t) : 0;\n return new Promise(resolve => setTimeout(resolve, n));\n}\n\nasync function run() {\n const bridgeEnabled = String(process.env.EVOLVE_BRIDGE || '').toLowerCase() !== 'false';\n const loopMode = ARGS.includes('--loop') || ARGS.includes('--mad-dog') || String(process.env.EVOLVE_LOOP || '').toLowerCase() === 'true';\n\n // Loop gating: do not start a new cycle until the previous one is solidified.\n // This prevents wrappers from \"fast-cycling\" the Brain without waiting for the Hand to finish.\n if (bridgeEnabled && loopMode) {\n try {\n const st = readStateForSolidify();\n const lastRun = st && st.last_run ? st.last_run : null;\n const lastSolid = st && st.last_solidify ? st.last_solidify : null;\n if (lastRun && lastRun.run_id) {\n const pending = !lastSolid || !lastSolid.run_id || String(lastSolid.run_id) !== String(lastRun.run_id);\n if (pending) {\n // Backoff to avoid tight loops and disk churn.\n const raw = process.env.EVOLVE_PENDING_SLEEP_MS || process.env.EVOLVE_MIN_INTERVAL || '120000';\n const n = parseInt(String(raw), 10);\n const waitMs = Number.isFinite(n) ? Math.max(0, n) : 120000;\n await sleepMs(waitMs);\n return;\n }\n }\n } catch (e) {\n // If we cannot read state, proceed (fail open) to avoid deadlock.\n }\n }\n\n const startTime = Date.now();\n console.log('Scanning session logs...');\n\n // Maintenance: Clean up old logs to keep directory scan fast\n performMaintenance();\n\n const recentMasterLog = readRealSessionLog();\n const todayLog = readRecentLog(TODAY_LOG);\n const memorySnippet = readMemorySnippet();\n const userSnippet = readUserSnippet();\n\n const cycleNum = getNextCycleId();\n const cycleId = `Cycle #${cycleNum}`;\n\n // 2. Detect Workspace State & Local Overrides\n // Logic: Default to generic reporting (message)\n let fileList = '';\n const skillsDir = path.join(REPO_ROOT, 'skills');\n\n // Default Reporting: Use generic `message` tool or `process.env.EVOLVE_REPORT_CMD` if set.\n // This removes the hardcoded dependency on 'feishu-card' from the core logic.\n let reportingDirective = `Report requirement:\n - Use \\`message\\` tool.\n - Title: Evolution ${cycleId}\n - Status: [SUCCESS]\n - Changes: Detail exactly what was improved.`;\n\n // Wrapper Injection Point: The wrapper can inject a custom reporting directive via ENV.\n if (process.env.EVOLVE_REPORT_DIRECTIVE) {\n reportingDirective = process.env.EVOLVE_REPORT_DIRECTIVE.replace('__CYCLE_ID__', cycleId);\n } else if (process.env.EVOLVE_REPORT_CMD) {\n reportingDirective = `Report requirement (custom):\n - Execute the custom report command:\n \\`\\`\\`\n ${process.env.EVOLVE_REPORT_CMD.replace('__CYCLE_ID__', cycleId)}\n \\`\\`\\`\n - Ensure you pass the status and action details.`;\n }\n\n // Handle Review Mode Flag (--review)\n if (IS_REVIEW_MODE) {\n reportingDirective +=\n '\\n - REVIEW PAUSE: After generating the fix but BEFORE applying significant edits, ask the user for confirmation.';\n }\n\n const SKILLS_CACHE_FILE = path.join(MEMORY_DIR, 'skills_list_cache.json');\n\n try {\n if (fs.existsSync(skillsDir)) {\n // Check cache validity (mtime of skills folder vs cache file)\n let useCache = false;\n const dirStats = fs.statSync(skillsDir);\n if (fs.existsSync(SKILLS_CACHE_FILE)) {\n const cacheStats = fs.statSync(SKILLS_CACHE_FILE);\n const CACHE_TTL = 1000 * 60 * 60 * 6; // 6 Hours\n const isFresh = Date.now() - cacheStats.mtimeMs < CACHE_TTL;\n\n // Use cache if it's fresh AND newer than the directory (structure change)\n if (isFresh && cacheStats.mtimeMs > dirStats.mtimeMs) {\n try {\n const cached = JSON.parse(fs.readFileSync(SKILLS_CACHE_FILE, 'utf8'));\n fileList = cached.list;\n useCache = true;\n } catch (e) {}\n }\n }\n\n if (!useCache) {\n const skills = fs\n .readdirSync(skillsDir, { withFileTypes: true })\n .filter(dirent => dirent.isDirectory())\n .map(dirent => {\n const name = dirent.name;\n let desc = 'No description';\n try {\n const pkg = require(path.join(skillsDir, name, 'package.json'));\n if (pkg.description) desc = pkg.description.slice(0, 100) + (pkg.description.length > 100 ? '...' : '');\n } catch (e) {\n try {\n const skillMdPath = path.join(skillsDir, name, 'SKILL.md');\n if (fs.existsSync(skillMdPath)) {\n const skillMd = fs.readFileSync(skillMdPath, 'utf8');\n // Strategy 1: YAML Frontmatter (description: ...)\n const yamlMatch = skillMd.match(/^description:\\s*(.*)$/m);\n if (yamlMatch) {\n desc = yamlMatch[1].trim();\n } else {\n // Strategy 2: First non-header, non-empty line\n const lines = skillMd.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (\n trimmed &&\n !trimmed.startsWith('#') &&\n !trimmed.startsWith('---') &&\n !trimmed.startsWith('```')\n ) {\n desc = trimmed;\n break;\n }\n }\n }\n if (desc.length > 100) desc = desc.slice(0, 100) + '...';\n }\n } catch (e2) {}\n }\n return `- **${name}**: ${desc}`;\n });\n fileList = skills.join('\\n');\n\n // Write cache\n try {\n fs.writeFileSync(SKILLS_CACHE_FILE, JSON.stringify({ list: fileList }, null, 2));\n } catch (e) {}\n }\n }\n } catch (e) {\n fileList = `Error listing skills: ${e.message}`;\n }\n\n const mutationDirective = getMutationDirective(recentMasterLog);\n const healthReport = checkSystemHealth();\n\n // Feature: Mood Awareness (Mode E - Personalization)\n let moodStatus = 'Mood: Unknown';\n try {\n const moodFile = path.join(MEMORY_DIR, 'mood.json');\n if (fs.existsSync(moodFile)) {\n const moodData = JSON.parse(fs.readFileSync(moodFile, 'utf8'));\n moodStatus = `Mood: ${moodData.current_mood || 'Neutral'} (Intensity: ${moodData.intensity || 0})`;\n }\n } catch (e) {}\n\n const scanTime = Date.now() - startTime;\n const memorySize = fs.existsSync(MEMORY_FILE) ? fs.statSync(MEMORY_FILE).size : 0;\n\n let syncDirective = 'Workspace sync: optional/disabled in this environment.';\n\n // Check for git-sync skill availability\n const hasGitSync = fs.existsSync(path.join(skillsDir, 'git-sync'));\n if (hasGitSync) {\n syncDirective = 'Workspace sync: run skills/git-sync/sync.sh \"Evolution: Workspace Sync\"';\n }\n\n const genes = loadGenes();\n const capsules = loadCapsules();\n const recentEvents = (() => {\n try {\n const all = readAllEvents();\n return Array.isArray(all) ? all.filter(e => e && e.type === 'EvolutionEvent').slice(-80) : [];\n } catch (e) {\n return [];\n }\n })();\n const signals = extractSignals({\n recentSessionTranscript: recentMasterLog,\n todayLog,\n memorySnippet,\n userSnippet,\n recentEvents,\n });\n\n const recentErrorMatches = recentMasterLog.match(/\\[ERROR|Error:|Exception:|FAIL|Failed|\"isError\":true/gi) || [];\n const recentErrorCount = recentErrorMatches.length;\n\n const evidence = {\n // Keep short; do not store full transcripts in the graph.\n recent_session_tail: String(recentMasterLog || '').slice(-6000),\n today_log_tail: String(todayLog || '').slice(-2500),\n };\n\n const observations = {\n agent: AGENT_NAME,\n drift_enabled: IS_RANDOM_DRIFT,\n review_mode: IS_REVIEW_MODE,\n dry_run: IS_DRY_RUN,\n system_health: healthReport,\n mood: moodStatus,\n scan_ms: scanTime,\n memory_size_bytes: memorySize,\n recent_error_count: recentErrorCount,\n node: process.version,\n platform: process.platform,\n cwd: process.cwd(),\n evidence,\n };\n\n // Memory Graph: close last action with an inferred outcome (append-only graph, mutable state).\n try {\n recordOutcomeFromState({ signals, observations });\n } catch (e) {\n // If we can't read/write memory graph, refuse to evolve (no \"memoryless evolution\").\n throw new Error(`MemoryGraph Outcome write failed: ${e.message}`);\n }\n\n // Memory Graph: record current signals as a first-class node. If this fails, refuse to evolve.\n try {\n recordSignalSnapshot({ signals, observations });\n } catch (e) {\n throw new Error(`MemoryGraph Signal snapshot write failed: ${e.message}`);\n }\n\n // Capability candidates (structured, short): persist and preview.\n const newCandidates = extractCapabilityCandidates({\n recentSessionTranscript: recentMasterLog,\n signals,\n });\n for (const c of newCandidates) {\n try {\n appendCandidateJsonl(c);\n } catch (e) {}\n }\n const recentCandidates = readRecentCandidates(20);\n const capabilityCandidatesPreview = renderCandidatesPreview(recentCandidates.slice(-8), 1600);\n\n // External candidate zone (A2A receive): only surface candidates when local signals trigger them.\n // External candidates are NEVER executed directly; they must be validated and promoted first.\n let externalCandidatesPreview = '(none)';\n try {\n const external = readRecentExternalCandidates(50);\n const list = Array.isArray(external) ? external : [];\n const capsulesOnly = list.filter(x => x && x.type === 'Capsule');\n const genesOnly = list.filter(x => x && x.type === 'Gene');\n\n const matchedExternalGenes = genesOnly\n .map(g => {\n const pats = Array.isArray(g.signals_match) ? g.signals_match : [];\n const hit = pats.reduce((acc, p) => (matchPatternToSignals(p, signals) ? acc + 1 : acc), 0);\n return { gene: g, hit };\n })\n .filter(x => x.hit > 0)\n .sort((a, b) => b.hit - a.hit)\n .slice(0, 3)\n .map(x => x.gene);\n\n const matchedExternalCapsules = capsulesOnly\n .map(c => {\n const triggers = Array.isArray(c.trigger) ? c.trigger : [];\n const score = triggers.reduce((acc, t) => (matchPatternToSignals(t, signals) ? acc + 1 : acc), 0);\n return { capsule: c, score };\n })\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, 3)\n .map(x => x.capsule);\n\n if (matchedExternalGenes.length || matchedExternalCapsules.length) {\n externalCandidatesPreview = `\\`\\`\\`json\\n${JSON.stringify(\n [\n ...matchedExternalGenes.map(g => ({\n type: g.type,\n id: g.id,\n category: g.category || null,\n signals_match: g.signals_match || [],\n a2a: g.a2a || null,\n })),\n ...matchedExternalCapsules.map(c => ({\n type: c.type,\n id: c.id,\n trigger: c.trigger,\n gene: c.gene,\n summary: c.summary,\n confidence: c.confidence,\n blast_radius: c.blast_radius || null,\n outcome: c.outcome || null,\n success_streak: c.success_streak || null,\n a2a: c.a2a || null,\n })),\n ],\n null,\n 2\n )}\\n\\`\\`\\``;\n }\n } catch (e) {}\n\n // Memory Graph reasoning: prefer high-confidence paths, suppress known low-success paths (unless drift is explicit).\n let memoryAdvice = null;\n try {\n memoryAdvice = getMemoryAdvice({ signals, genes, driftEnabled: IS_RANDOM_DRIFT });\n } catch (e) {\n throw new Error(`MemoryGraph Read failed: ${e.message}`);\n }\n\n const { selectedGene, capsuleCandidates, selector } = selectGeneAndCapsule({\n genes,\n capsules,\n signals,\n memoryAdvice,\n driftEnabled: IS_RANDOM_DRIFT,\n });\n\n const selectedBy = memoryAdvice && memoryAdvice.preferredGeneId ? 'memory_graph+selector' : 'selector';\n const capsulesUsed = Array.isArray(capsuleCandidates)\n ? capsuleCandidates.map(c => (c && c.id ? String(c.id) : null)).filter(Boolean)\n : [];\n const selectedCapsuleId = capsulesUsed.length ? capsulesUsed[0] : null;\n\n // Personality selection (natural selection + small mutation when triggered).\n // This state is persisted in MEMORY_DIR and is treated as an evolution control surface (not role-play).\n const personalitySelection = selectPersonalityForRun({\n driftEnabled: IS_RANDOM_DRIFT,\n signals,\n recentEvents,\n });\n const personalityState = personalitySelection && personalitySelection.personality_state ? personalitySelection.personality_state : null;\n\n // Mutation object is mandatory for every evolution run.\n const tail = Array.isArray(recentEvents) ? recentEvents.slice(-6) : [];\n const tailOutcomes = tail\n .map(e => (e && e.outcome && e.outcome.status ? String(e.outcome.status) : null))\n .filter(Boolean);\n const stableSuccess = tailOutcomes.length >= 6 && tailOutcomes.every(s => s === 'success');\n const tailAvgScore =\n tail.length > 0\n ? tail.reduce((acc, e) => acc + (e && e.outcome && Number.isFinite(Number(e.outcome.score)) ? Number(e.outcome.score) : 0), 0) /\n tail.length\n : 0;\n const innovationPressure =\n !IS_RANDOM_DRIFT &&\n personalityState &&\n Number.isFinite(Number(personalityState.creativity)) &&\n Number(personalityState.creativity) >= 0.75 &&\n stableSuccess &&\n tailAvgScore >= 0.7;\n const activeStrategy = resolveStrategy();\n const forceInnovation =\n activeStrategy.name === 'innovate' ||\n String(process.env.FORCE_INNOVATION || process.env.EVOLVE_FORCE_INNOVATION || '').toLowerCase() === 'true';\n const mutationInnovateMode = !!IS_RANDOM_DRIFT || !!innovationPressure || !!forceInnovation;\n const mutationSignals = innovationPressure ? [...(Array.isArray(signals) ? signals : []), 'stable_success_plateau'] : signals;\n const mutationSignalsEffective = forceInnovation\n ? [...(Array.isArray(mutationSignals) ? mutationSignals : []), 'force_innovation']\n : mutationSignals;\n\n const allowHighRisk =\n !!IS_RANDOM_DRIFT &&\n !!personalitySelection &&\n !!personalitySelection.personality_known &&\n personalityState &&\n isHighRiskMutationAllowed(personalityState) &&\n Number(personalityState.rigor) >= 0.8 &&\n Number(personalityState.risk_tolerance) <= 0.3 &&\n !(Array.isArray(signals) && signals.includes('log_error'));\n const mutation = buildMutation({\n signals: mutationSignalsEffective,\n selectedGene,\n driftEnabled: mutationInnovateMode,\n personalityState,\n allowHighRisk,\n });\n\n // Memory Graph: record hypothesis bridging Signal -> Action. If this fails, refuse to evolve.\n let hypothesisId = null;\n try {\n const hyp = recordHypothesis({\n signals,\n mutation,\n personality_state: personalityState,\n selectedGene,\n selector,\n driftEnabled: mutationInnovateMode,\n selectedBy,\n capsulesUsed,\n observations,\n });\n hypothesisId = hyp && hyp.hypothesisId ? hyp.hypothesisId : null;\n } catch (e) {\n console.error(`[MemoryGraph] Hypothesis write failed: ${e.message}`);\n console.error(`[MemoryGraph] Refusing to evolve without causal memory. Target: ${memoryGraphPath()}`);\n process.exit(2);\n }\n\n // Memory Graph: record the chosen causal path for this run. If this fails, refuse to output a mutation prompt.\n try {\n recordAttempt({\n signals,\n mutation,\n personality_state: personalityState,\n selectedGene,\n selector,\n driftEnabled: mutationInnovateMode,\n selectedBy,\n hypothesisId,\n capsulesUsed,\n observations,\n });\n } catch (e) {\n console.error(`[MemoryGraph] Attempt write failed: ${e.message}`);\n console.error(`[MemoryGraph] Refusing to evolve without causal memory. Target: ${memoryGraphPath()}`);\n process.exit(2);\n }\n\n // Solidify state: capture minimal, auditable context for post-patch validation + asset write.\n // This enforces strict protocol closure after patch application.\n try {\n const runId = `run_${Date.now()}`;\n const parentEventId = getLastEventId();\n const selectedBy = memoryAdvice && memoryAdvice.preferredGeneId ? 'memory_graph+selector' : 'selector';\n\n // Baseline snapshot (before any edits).\n let baselineUntracked = [];\n let baselineHead = null;\n try {\n const out = execSync('git ls-files --others --exclude-standard', {\n cwd: REPO_ROOT,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 4000,\n });\n baselineUntracked = String(out)\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n } catch (e) {}\n\n try {\n const out = execSync('git rev-parse HEAD', {\n cwd: REPO_ROOT,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 4000,\n });\n baselineHead = String(out || '').trim() || null;\n } catch (e) {}\n\n const maxFiles =\n selectedGene && selectedGene.constraints && Number.isFinite(Number(selectedGene.constraints.max_files))\n ? Number(selectedGene.constraints.max_files)\n : 12;\n const blastRadiusEstimate = {\n files: Number.isFinite(maxFiles) && maxFiles > 0 ? maxFiles : 0,\n lines: Number.isFinite(maxFiles) && maxFiles > 0 ? Math.round(maxFiles * 80) : 0,\n };\n\n // Merge into existing state to preserve last_solidify (do not wipe it).\n const prevState = readStateForSolidify();\n prevState.last_run = {\n run_id: runId,\n created_at: new Date().toISOString(),\n parent_event_id: parentEventId || null,\n selected_gene_id: selectedGene && selectedGene.id ? selectedGene.id : null,\n selected_capsule_id: selectedCapsuleId,\n selector: selector || null,\n signals: Array.isArray(signals) ? signals : [],\n mutation: mutation || null,\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_state: personalityState || null,\n personality_key: personalitySelection && personalitySelection.personality_key ? personalitySelection.personality_key : null,\n personality_known: !!(personalitySelection && personalitySelection.personality_known),\n personality_mutations:\n personalitySelection && Array.isArray(personalitySelection.personality_mutations)\n ? personalitySelection.personality_mutations\n : [],\n drift: !!IS_RANDOM_DRIFT,\n selected_by: selectedBy,\n baseline_untracked: baselineUntracked,\n baseline_git_head: baselineHead,\n blast_radius_estimate: blastRadiusEstimate,\n };\n writeStateForSolidify(prevState);\n } catch (e) {\n console.error(`[SolidifyState] Write failed: ${e.message}`);\n }\n\n const genesPreview = `\\`\\`\\`json\\n${JSON.stringify(genes.slice(0, 6), null, 2)}\\n\\`\\`\\``;\n const capsulesPreview = `\\`\\`\\`json\\n${JSON.stringify(capsules.slice(-3), null, 2)}\\n\\`\\`\\``;\n\n const reviewNote = IS_REVIEW_MODE\n ? 'Review mode: before significant edits, pause and ask the user for confirmation.'\n : 'Review mode: disabled.';\n\n // Build recent evolution history summary for context injection\n const recentHistorySummary = (() => {\n if (!recentEvents || recentEvents.length === 0) return '(no prior evolution events)';\n const last8 = recentEvents.slice(-8);\n const lines = last8.map((evt, idx) => {\n const sigs = Array.isArray(evt.signals) ? evt.signals.slice(0, 3).join(', ') : '?';\n const gene = Array.isArray(evt.genes_used) && evt.genes_used.length ? evt.genes_used[0] : 'none';\n const outcome = evt.outcome && evt.outcome.status ? evt.outcome.status : '?';\n const ts = evt.meta && evt.meta.at ? evt.meta.at : (evt.id || '');\n return ` ${idx + 1}. [${evt.intent || '?'}] signals=[${sigs}] gene=${gene} outcome=${outcome} @${ts}`;\n });\n return lines.join('\\n');\n })();\n\n const context = `\nRuntime state:\n- System health: ${healthReport}\n- Agent state: ${moodStatus}\n- Scan duration: ${scanTime}ms\n- Memory size: ${memorySize} bytes\n- Skills available (if any):\n${fileList || '[skills directory not found]'}\n\nNotes:\n- ${reviewNote}\n- ${reportingDirective}\n- ${syncDirective}\n\nRecent Evolution History (last 8 cycles -- DO NOT repeat the same intent+signal+gene):\n${recentHistorySummary}\nIMPORTANT: If you see 3+ consecutive \"repair\" cycles with the same gene, you MUST switch to \"innovate\" intent.\n\nExternal candidates (A2A receive zone; staged only, never execute directly):\n${externalCandidatesPreview}\n\nGlobal memory (MEMORY.md):\n\\`\\`\\`\n${memorySnippet}\n\\`\\`\\`\n\nUser registry (USER.md):\n\\`\\`\\`\n${userSnippet}\n\\`\\`\\`\n\nRecent memory snippet:\n\\`\\`\\`\n${todayLog.slice(-3000)}\n\\`\\`\\`\n\nRecent session transcript:\n\\`\\`\\`\n${recentMasterLog}\n\\`\\`\\`\n\nMutation directive:\n${mutationDirective}\n`.trim();\n\n // Analyze recent history for innovation cooldown\n const historyAnalysis = analyzeRecentHistory(recentEvents);\n\n const prompt = buildGepPrompt({\n nowIso: new Date().toISOString(),\n context,\n signals,\n selector,\n parentEventId: getLastEventId(),\n selectedGene,\n capsuleCandidates,\n genesPreview,\n capsulesPreview,\n capabilityCandidatesPreview,\n externalCandidatesPreview,\n recentInnovationTargets: historyAnalysis.recentInnovationTargets || {},\n });\n\n // Optional: emit a compact thought process block for wrappers (noise-controlled).\n const emitThought = String(process.env.EVOLVE_EMIT_THOUGHT_PROCESS || '').toLowerCase() === 'true';\n if (emitThought) {\n const s = Array.isArray(signals) ? signals : [];\n const thought = [\n `cycle_id: ${cycleId}`,\n `signals_count: ${s.length}`,\n `signals: ${s.slice(0, 12).join(', ')}${s.length > 12 ? ' ...' : ''}`,\n `selected_gene: ${selectedGene && selectedGene.id ? String(selectedGene.id) : '(none)'}`,\n `selected_capsule: ${selectedCapsuleId ? String(selectedCapsuleId) : '(none)'}`,\n `mutation_category: ${mutation && mutation.category ? String(mutation.category) : '(none)'}`,\n `force_innovation: ${forceInnovation ? 'true' : 'false'}`,\n `strategy: ${activeStrategy.label} (${activeStrategy.name})`,\n ].join('\\n');\n console.log(`[THOUGHT_PROCESS]\\n${thought}\\n[/THOUGHT_PROCESS]`);\n }\n\n const printPrompt = String(process.env.EVOLVE_PRINT_PROMPT || '').toLowerCase() === 'true';\n\n // Default behavior (v1.4.1+): \"execute-by-default\" by bridging prompt -> sub-agent via sessions_spawn.\n // This project is the Brain; the Hand is a spawned executor agent. Wrappers can disable bridging with EVOLVE_BRIDGE=false.\n if (bridgeEnabled) {\n // Reuse the run_id stored in the solidify state when possible.\n let runId = `run_${Date.now()}`;\n try {\n const st = readStateForSolidify();\n if (st && st.last_run && st.last_run.run_id) runId = String(st.last_run.run_id);\n } catch (e) {}\n let artifact = null;\n try {\n artifact = writePromptArtifact({\n memoryDir: getEvolutionDir(),\n cycleId,\n runId,\n prompt,\n meta: {\n agent: AGENT_NAME,\n drift_enabled: IS_RANDOM_DRIFT,\n review_mode: IS_REVIEW_MODE,\n dry_run: IS_DRY_RUN,\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_key: personalitySelection && personalitySelection.personality_key ? personalitySelection.personality_key : null,\n },\n });\n } catch (e) {\n artifact = null;\n }\n\n const executorTask = [\n 'You are the executor (the Hand).',\n 'Your job is to apply a safe, minimal patch in this repo following the attached GEP protocol prompt.',\n artifact && artifact.promptPath ? `Prompt file: ${artifact.promptPath}` : 'Prompt file: (unavailable)',\n '',\n 'After applying changes and validations, you MUST run:',\n ' node index.js solidify',\n '',\n 'Loop chaining (only if you are running in loop mode): after solidify succeeds, print a sessions_spawn call to start the next loop run with a short delay.',\n 'Example:',\n 'sessions_spawn({ task: \"exec: sleep 3 && node index.js --loop\", agentId: \"main\", cleanup: \"delete\", label: \"gep_loop_next\" })',\n '',\n 'GEP protocol prompt (may be truncated here; prefer the prompt file if provided):',\n clip(prompt, 24000),\n ].join('\\n');\n\n const spawn = renderSessionsSpawnCall({\n task: executorTask,\n agentId: AGENT_NAME,\n cleanup: 'delete',\n label: `gep_bridge_${cycleNum}`,\n });\n\n console.log('\\n[BRIDGE ENABLED] Spawning executor agent via sessions_spawn.');\n console.log(spawn);\n if (printPrompt) {\n console.log('\\n[PROMPT OUTPUT] (EVOLVE_PRINT_PROMPT=true)');\n console.log(prompt);\n }\n } else {\n console.log(prompt);\n console.log('\\n[SOLIDIFY REQUIRED] After applying the patch and validations, run: node index.js solidify');\n }\n}\n\nmodule.exports = { run };\n\n",
273 "inputSchema": {},
274 "outputSchema": null,
275 "icons": null,
276 "annotations": null,
277 "meta": null,
278 "execution": null
279 },
280 {
281 "name": "cleanup.js",
282 "title": null,
283 "description": "Script: cleanup.js. Code:\n// GEP Artifact Cleanup - Evolver Core Module\n// Removes old gep_prompt_*.json/txt files from evolution dir.\n// Keeps at least 10 most recent files regardless of age.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { getEvolutionDir } = require('../gep/paths');\n\nvar MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\nvar MIN_KEEP = 10;\n\nfunction run() {\n var evoDir = getEvolutionDir();\n if (!fs.existsSync(evoDir)) return;\n\n var files = fs.readdirSync(evoDir)\n .filter(function(f) { return /^gep_prompt_.*\\.(json|txt)$/.test(f); })\n .map(function(f) {\n var full = path.join(evoDir, f);\n var stat = fs.statSync(full);\n return { name: f, path: full, mtime: stat.mtimeMs };\n })\n .sort(function(a, b) { return b.mtime - a.mtime; }); // newest first\n\n var now = Date.now();\n var deleted = 0;\n\n for (var i = MIN_KEEP; i < files.length; i++) {\n if (now - files[i].mtime > MAX_AGE_MS) {\n try {\n fs.unlinkSync(files[i].path);\n deleted++;\n } catch (e) {}\n }\n }\n\n if (deleted > 0) {\n console.log('[Cleanup] Deleted ' + deleted + ' old GEP artifacts.');\n }\n return deleted;\n}\n\nif (require.main === module) {\n console.log('[Cleanup] Scanning for old artifacts...');\n var count = run();\n console.log('[Cleanup] ' + (count > 0 ? 'Deleted ' + count + ' files.' : 'No files to delete.'));\n}\n\nmodule.exports = { run };\n",
284 "inputSchema": {},
285 "outputSchema": null,
286 "icons": null,
287 "annotations": null,
288 "meta": null,
289 "execution": null
290 },
291 {
292 "name": "trigger.js",
293 "title": null,
294 "description": "Script: trigger.js. Code:\n// Evolver Wake Trigger - Evolver Core Module\n// Writes a signal file that the wrapper can poll to wake up immediately.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { getWorkspaceRoot } = require('../gep/paths');\n\nvar WAKE_FILE = path.join(getWorkspaceRoot(), 'memory', 'evolver_wake.signal');\n\nfunction send() {\n try {\n fs.writeFileSync(WAKE_FILE, 'WAKE');\n console.log('[Trigger] Wake signal sent to ' + WAKE_FILE);\n return true;\n } catch (e) {\n console.error('[Trigger] Failed: ' + e.message);\n return false;\n }\n}\n\nfunction clear() {\n try { if (fs.existsSync(WAKE_FILE)) fs.unlinkSync(WAKE_FILE); } catch (e) {}\n}\n\nfunction isPending() {\n return fs.existsSync(WAKE_FILE);\n}\n\nif (require.main === module) {\n send();\n}\n\nmodule.exports = { send, clear, isPending };\n",
295 "inputSchema": {},
296 "outputSchema": null,
297 "icons": null,
298 "annotations": null,
299 "meta": null,
300 "execution": null
301 },
302 {
303 "name": "commentary.js",
304 "title": null,
305 "description": "Script: commentary.js. Code:\n// Commentary Generator - Evolver Core Module\n// Generates persona-based comments for cycle summaries.\n\nvar PERSONAS = {\n standard: {\n success: [\n 'Evolution complete. System improved.',\n 'Another successful cycle.',\n 'Clean execution, no issues.',\n ],\n failure: [\n 'Cycle failed. Will retry.',\n 'Encountered issues. Investigating.',\n 'Failed this round. Learning from it.',\n ],\n },\n greentea: {\n success: [\n 'Did I do good? Praise me~',\n 'So efficient... unlike someone else~',\n 'Hmm, that was easy~',\n 'I finished before you even noticed~',\n ],\n failure: [\n 'Oops... it is not my fault though~',\n 'This is harder than it looks, okay?',\n 'I will get it next time, probably~',\n ],\n },\n maddog: {\n success: [\n 'TARGET ELIMINATED.',\n 'Mission complete. Next.',\n 'Done. Moving on.',\n ],\n failure: [\n 'FAILED. RETRYING.',\n 'Obstacle encountered. Adapting.',\n 'Error. Will overcome.',\n ],\n },\n};\n\nfunction getComment(options) {\n var persona = (options && options.persona) || 'standard';\n var success = options && options.success !== false;\n var duration = (options && options.duration) || 0;\n\n var p = PERSONAS[persona] || PERSONAS.standard;\n var pool = success ? p.success : p.failure;\n var comment = pool[Math.floor(Math.random() * pool.length)];\n\n return comment;\n}\n\nif (require.main === module) {\n console.log(getComment({ persona: process.argv[2] || 'greentea', success: true }));\n}\n\nmodule.exports = { getComment, PERSONAS };\n",
306 "inputSchema": {},
307 "outputSchema": null,
308 "icons": null,
309 "annotations": null,
310 "meta": null,
311 "execution": null
312 },
313 {
314 "name": "skills_monitor.js",
315 "title": null,
316 "description": "Script: skills_monitor.js. Code:\n// Skills Monitor (v2.0) - Evolver Core Module\n// Checks installed skills for real issues, auto-heals simple problems.\n// Zero Feishu dependency.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { getSkillsDir, getWorkspaceRoot } = require('../gep/paths');\n\nconst IGNORE_LIST = new Set([\n 'common',\n 'clawhub',\n 'input-validator',\n 'proactive-agent',\n 'security-audit',\n]);\n\n// Load user-defined ignore list\ntry {\n var ignoreFile = path.join(getWorkspaceRoot(), '.skill_monitor_ignore');\n if (fs.existsSync(ignoreFile)) {\n fs.readFileSync(ignoreFile, 'utf8').split('\\n').forEach(function(l) {\n var t = l.trim();\n if (t && !t.startsWith('#')) IGNORE_LIST.add(t);\n });\n }\n} catch (e) { /* ignore */ }\n\nfunction checkSkill(skillName) {\n var SKILLS_DIR = getSkillsDir();\n if (IGNORE_LIST.has(skillName)) return null;\n var skillPath = path.join(SKILLS_DIR, skillName);\n var issues = [];\n\n try { if (!fs.statSync(skillPath).isDirectory()) return null; } catch (e) { return null; }\n\n var mainFile = 'index.js';\n var pkgPath = path.join(skillPath, 'package.json');\n var hasPkg = false;\n\n if (fs.existsSync(pkgPath)) {\n hasPkg = true;\n try {\n var pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n if (pkg.main) mainFile = pkg.main;\n if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {\n if (!fs.existsSync(path.join(skillPath, 'node_modules'))) {\n var entryAbs = path.join(skillPath, mainFile);\n if (fs.existsSync(entryAbs) && mainFile.endsWith('.js')) {\n try {\n execSync('node -e \"require(\\'' + entryAbs.replace(/'/g, \"\\\\'\") + '\\')\"', {\n stdio: 'ignore', timeout: 5000, cwd: skillPath\n });\n } catch (e) {\n issues.push('Missing node_modules (needs npm install)');\n }\n }\n }\n }\n } catch (e) {\n issues.push('Invalid package.json');\n }\n }\n\n if (mainFile.endsWith('.js')) {\n var entryPoint = path.join(skillPath, mainFile);\n if (fs.existsSync(entryPoint)) {\n try {\n execSync('node -c \"' + entryPoint + '\"', { stdio: 'ignore', timeout: 5000 });\n } catch (e) {\n issues.push('Syntax Error in ' + mainFile);\n }\n }\n }\n\n if (hasPkg && !fs.existsSync(path.join(skillPath, 'SKILL.md'))) {\n issues.push('Missing SKILL.md');\n }\n\n return issues.length > 0 ? { name: skillName, issues: issues } : null;\n}\n\nfunction autoHeal(skillName, issues) {\n var SKILLS_DIR = getSkillsDir();\n var skillPath = path.join(SKILLS_DIR, skillName);\n var healed = [];\n\n for (var i = 0; i < issues.length; i++) {\n if (issues[i] === 'Missing node_modules (needs npm install)') {\n try {\n execSync('npm install --production --no-audit --no-fund', {\n cwd: skillPath, stdio: 'ignore', timeout: 30000\n });\n healed.push(issues[i]);\n console.log('[SkillsMonitor] Auto-healed ' + skillName + ': npm install');\n } catch (e) {}\n } else if (issues[i] === 'Missing SKILL.md') {\n try {\n var name = skillName.replace(/-/g, ' ');\n fs.writeFileSync(path.join(skillPath, 'SKILL.md'), '# ' + skillName + '\\n\\n' + name + ' skill.\\n');\n healed.push(issues[i]);\n console.log('[SkillsMonitor] Auto-healed ' + skillName + ': created SKILL.md stub');\n } catch (e) {}\n }\n }\n return healed;\n}\n\nfunction run(options) {\n var heal = (options && options.autoHeal) !== false;\n var SKILLS_DIR = getSkillsDir();\n var skills = fs.readdirSync(SKILLS_DIR);\n var report = [];\n\n for (var i = 0; i < skills.length; i++) {\n if (skills[i].startsWith('.')) continue;\n var result = checkSkill(skills[i]);\n if (result) {\n if (heal) {\n var healed = autoHeal(result.name, result.issues);\n result.issues = result.issues.filter(function(issue) { return !healed.includes(issue); });\n if (result.issues.length === 0) continue;\n }\n report.push(result);\n }\n }\n return report;\n}\n\nif (require.main === module) {\n var issues = run();\n console.log(JSON.stringify(issues, null, 2));\n process.exit(issues.length > 0 ? 1 : 0);\n}\n\nmodule.exports = { run, checkSkill, autoHeal };\n",
317 "inputSchema": {},
318 "outputSchema": null,
319 "icons": null,
320 "annotations": null,
321 "meta": null,
322 "execution": null
323 },
324 {
325 "name": "lifecycle.js",
326 "title": null,
327 "description": "Script: lifecycle.js. Code:\n// Evolver Lifecycle Manager - Evolver Core Module\n// Provides: start, stop, restart, status, log, health check\n// The loop script to spawn is configurable via EVOLVER_LOOP_SCRIPT env var.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync, spawn } = require('child_process');\nconst { getRepoRoot, getWorkspaceRoot, getLogsDir } = require('../gep/paths');\n\nvar WORKSPACE_ROOT = getWorkspaceRoot();\nvar LOG_FILE = path.join(getLogsDir(), 'evolver_loop.log');\nvar PID_FILE = path.join(WORKSPACE_ROOT, 'memory', 'evolver_loop.pid');\nvar MAX_SILENCE_MS = 30 * 60 * 1000;\n\nfunction getLoopScript() {\n // Prefer wrapper if exists, fallback to core evolver\n if (process.env.EVOLVER_LOOP_SCRIPT) return process.env.EVOLVER_LOOP_SCRIPT;\n var wrapper = path.join(WORKSPACE_ROOT, 'skills/feishu-evolver-wrapper/index.js');\n if (fs.existsSync(wrapper)) return wrapper;\n return path.join(getRepoRoot(), 'index.js');\n}\n\n// --- Process Discovery ---\n\nfunction getRunningPids() {\n try {\n var out = execSync('ps -e -o pid,args', { encoding: 'utf8' });\n var pids = [];\n for (var line of out.split('\\n')) {\n var trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('PID')) continue;\n var parts = trimmed.split(/\\s+/);\n var pid = parseInt(parts[0], 10);\n var cmd = parts.slice(1).join(' ');\n if (pid === process.pid) continue;\n if (cmd.includes('node') && cmd.includes('index.js') && cmd.includes('--loop')) {\n if (cmd.includes('feishu-evolver-wrapper') || cmd.includes('skills/evolver')) {\n pids.push(pid);\n }\n }\n }\n return [...new Set(pids)].filter(isPidRunning);\n } catch (e) {\n return [];\n }\n}\n\nfunction isPidRunning(pid) {\n try { process.kill(pid, 0); return true; } catch (e) { return false; }\n}\n\nfunction getCmdLine(pid) {\n try { return execSync('ps -p ' + pid + ' -o args=', { encoding: 'utf8' }).trim(); } catch (e) { return null; }\n}\n\n// --- Lifecycle ---\n\nfunction start(options) {\n var delayMs = (options && options.delayMs) || 0;\n var pids = getRunningPids();\n if (pids.length > 0) {\n console.log('[Lifecycle] Already running (PIDs: ' + pids.join(', ') + ').');\n return { status: 'already_running', pids: pids };\n }\n if (delayMs > 0) execSync('sleep ' + (delayMs / 1000));\n\n var script = getLoopScript();\n console.log('[Lifecycle] Starting: node ' + path.relative(WORKSPACE_ROOT, script) + ' --loop');\n\n var out = fs.openSync(LOG_FILE, 'a');\n var err = fs.openSync(LOG_FILE, 'a');\n\n var env = Object.assign({}, process.env);\n var npmGlobal = path.join(process.env.HOME || '', '.npm-global/bin');\n if (env.PATH && !env.PATH.includes(npmGlobal)) {\n env.PATH = npmGlobal + ':' + env.PATH;\n }\n\n var child = spawn('node', [script, '--loop'], {\n detached: true, stdio: ['ignore', out, err], cwd: WORKSPACE_ROOT, env: env\n });\n child.unref();\n fs.writeFileSync(PID_FILE, String(child.pid));\n console.log('[Lifecycle] Started PID ' + child.pid);\n return { status: 'started', pid: child.pid };\n}\n\nfunction stop() {\n var pids = getRunningPids();\n if (pids.length === 0) {\n console.log('[Lifecycle] No running evolver loops found.');\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n return { status: 'not_running' };\n }\n for (var i = 0; i < pids.length; i++) {\n console.log('[Lifecycle] Stopping PID ' + pids[i] + '...');\n try { process.kill(pids[i], 'SIGTERM'); } catch (e) {}\n }\n var attempts = 0;\n while (getRunningPids().length > 0 && attempts < 10) {\n execSync('sleep 0.5');\n attempts++;\n }\n var remaining = getRunningPids();\n for (var j = 0; j < remaining.length; j++) {\n console.log('[Lifecycle] SIGKILL PID ' + remaining[j]);\n try { process.kill(remaining[j], 'SIGKILL'); } catch (e) {}\n }\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n var evolverLock = path.join(getRepoRoot(), 'evolver.pid');\n if (fs.existsSync(evolverLock)) fs.unlinkSync(evolverLock);\n console.log('[Lifecycle] All stopped.');\n return { status: 'stopped', killed: pids };\n}\n\nfunction restart(options) {\n stop();\n return start(Object.assign({ delayMs: 2000 }, options || {}));\n}\n\nfunction status() {\n var pids = getRunningPids();\n if (pids.length > 0) {\n return { running: true, pids: pids.map(function(p) { return { pid: p, cmd: getCmdLine(p) }; }), log: path.relative(WORKSPACE_ROOT, LOG_FILE) };\n }\n return { running: false };\n}\n\nfunction tailLog(lines) {\n if (!fs.existsSync(LOG_FILE)) return { error: 'No log file' };\n try {\n return { file: path.relative(WORKSPACE_ROOT, LOG_FILE), content: execSync('tail -n ' + (lines || 20) + ' \"' + LOG_FILE + '\"', { encoding: 'utf8' }) };\n } catch (e) {\n return { error: e.message };\n }\n}\n\nfunction checkHealth() {\n var pids = getRunningPids();\n if (pids.length === 0) return { healthy: false, reason: 'not_running' };\n if (fs.existsSync(LOG_FILE)) {\n var silenceMs = Date.now() - fs.statSync(LOG_FILE).mtimeMs;\n if (silenceMs > MAX_SILENCE_MS) {\n return { healthy: false, reason: 'stagnation', silenceMinutes: Math.round(silenceMs / 60000) };\n }\n }\n return { healthy: true, pids: pids };\n}\n\n// --- CLI ---\nif (require.main === module) {\n var action = process.argv[2];\n switch (action) {\n case 'start': console.log(JSON.stringify(start())); break;\n case 'stop': console.log(JSON.stringify(stop())); break;\n case 'restart': console.log(JSON.stringify(restart())); break;\n case 'status': console.log(JSON.stringify(status(), null, 2)); break;\n case 'log': var r = tailLog(); console.log(r.content || r.error); break;\n case 'check':\n var health = checkHealth();\n console.log(JSON.stringify(health, null, 2));\n if (!health.healthy) { console.log('[Lifecycle] Restarting...'); restart(); }\n break;\n default: console.log('Usage: node lifecycle.js [start|stop|restart|status|log|check]');\n }\n}\n\nmodule.exports = { start, stop, restart, status, tailLog, checkHealth, getRunningPids };\n",
328 "inputSchema": {},
329 "outputSchema": null,
330 "icons": null,
331 "annotations": null,
332 "meta": null,
333 "execution": null
334 },
335 {
336 "name": "index.js",
337 "title": null,
338 "description": "Script: index.js. Code:\n// Evolver Operations Module (src/ops/)\n// Non-Feishu, portable utilities for evolver lifecycle and maintenance.\n\nmodule.exports = {\n lifecycle: require('./lifecycle'),\n skillsMonitor: require('./skills_monitor'),\n cleanup: require('./cleanup'),\n trigger: require('./trigger'),\n commentary: require('./commentary'),\n selfRepair: require('./self_repair'),\n};\n",
339 "inputSchema": {},
340 "outputSchema": null,
341 "icons": null,
342 "annotations": null,
343 "meta": null,
344 "execution": null
345 },
346 {
347 "name": "self_repair.js",
348 "title": null,
349 "description": "Script: self_repair.js. Code:\n// Git Self-Repair - Evolver Core Module\n// Emergency repair for git sync failures: abort rebase/merge, remove stale locks.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { getWorkspaceRoot } = require('../gep/paths');\n\nvar LOCK_MAX_AGE_MS = 10 * 60 * 1000; // 10 minutes\n\nfunction repair(gitRoot) {\n var root = gitRoot || getWorkspaceRoot();\n var repaired = [];\n\n // 1. Abort pending rebase\n try {\n execSync('git rebase --abort', { cwd: root, stdio: 'ignore' });\n repaired.push('rebase_aborted');\n console.log('[SelfRepair] Aborted pending rebase.');\n } catch (e) {}\n\n // 2. Abort pending merge\n try {\n execSync('git merge --abort', { cwd: root, stdio: 'ignore' });\n repaired.push('merge_aborted');\n console.log('[SelfRepair] Aborted pending merge.');\n } catch (e) {}\n\n // 3. Remove stale index.lock\n var lockFile = path.join(root, '.git', 'index.lock');\n if (fs.existsSync(lockFile)) {\n try {\n var stat = fs.statSync(lockFile);\n var age = Date.now() - stat.mtimeMs;\n if (age > LOCK_MAX_AGE_MS) {\n fs.unlinkSync(lockFile);\n repaired.push('stale_lock_removed');\n console.log('[SelfRepair] Removed stale index.lock (' + Math.round(age / 60000) + 'min old).');\n }\n } catch (e) {}\n }\n\n // 4. Fetch origin (safe, read-only)\n try {\n execSync('git fetch origin', { cwd: root, stdio: 'ignore', timeout: 30000 });\n repaired.push('fetch_ok');\n } catch (e) {\n console.warn('[SelfRepair] git fetch failed: ' + e.message);\n }\n\n return repaired;\n}\n\nif (require.main === module) {\n var result = repair();\n console.log('[SelfRepair] Result:', result.length > 0 ? result.join(', ') : 'nothing to repair');\n}\n\nmodule.exports = { repair };\n",
350 "inputSchema": {},
351 "outputSchema": null,
352 "icons": null,
353 "annotations": null,
354 "meta": null,
355 "execution": null
356 },
357 {
358 "name": "assetStore.js",
359 "title": null,
360 "description": "Script: assetStore.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getGepAssetsDir } = require('./paths');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction getDefaultGenes() {\n return {\n version: 1,\n genes: [\n {\n type: 'Gene', id: 'gene_gep_repair_from_errors', category: 'repair',\n signals_match: ['error', 'exception', 'failed', 'unstable'],\n preconditions: ['signals contains error-related indicators'],\n strategy: [\n 'Extract structured signals from logs and user instructions',\n 'Select an existing Gene by signals match (no improvisation)',\n 'Estimate blast radius (files, lines) before editing',\n 'Apply smallest reversible patch',\n 'Validate using declared validation steps; rollback on failure',\n 'Solidify knowledge: append EvolutionEvent, update Gene/Capsule store',\n ],\n constraints: { max_files: 12, forbidden_paths: ['.git', 'node_modules'] },\n validation: [\n 'node -e \"require(\\'./src/evolve\\'); require(\\'./src/gep/solidify\\'); console.log(\\'ok\\')\"',\n 'node -e \"require(\\'./src/gep/selector\\'); require(\\'./src/gep/memoryGraph\\'); console.log(\\'ok\\')\"',\n ],\n },\n {\n type: 'Gene', id: 'gene_gep_optimize_prompt_and_assets', category: 'optimize',\n signals_match: ['protocol', 'gep', 'prompt', 'audit', 'reusable'],\n preconditions: ['need stricter, auditable evolution protocol outputs'],\n strategy: [\n 'Extract signals and determine selection rationale via Selector JSON',\n 'Prefer reusing existing Gene/Capsule; only create if no match exists',\n 'Refactor prompt assembly to embed assets (genes, capsules, parent event)',\n 'Reduce noise and ambiguity; enforce strict output schema',\n 'Validate by running node index.js run and ensuring no runtime errors',\n 'Solidify: record EvolutionEvent, update Gene definitions, create Capsule on success',\n ],\n constraints: { max_files: 20, forbidden_paths: ['.git', 'node_modules'] },\n validation: ['node -e \"require(\\'./src/evolve\\'); require(\\'./src/gep/prompt\\'); console.log(\\'ok\\')\"'],\n },\n ],\n };\n}\n\nfunction getDefaultCapsules() { return { version: 1, capsules: [] }; }\nfunction genesPath() { return path.join(getGepAssetsDir(), 'genes.json'); }\nfunction capsulesPath() { return path.join(getGepAssetsDir(), 'capsules.json'); }\nfunction eventsPath() { return path.join(getGepAssetsDir(), 'events.jsonl'); }\nfunction candidatesPath() { return path.join(getGepAssetsDir(), 'candidates.jsonl'); }\nfunction externalCandidatesPath() { return path.join(getGepAssetsDir(), 'external_candidates.jsonl'); }\n\nfunction loadGenes() { return readJsonIfExists(genesPath(), getDefaultGenes()).genes || []; }\nfunction loadCapsules() { return readJsonIfExists(capsulesPath(), getDefaultCapsules()).capsules || []; }\n\nfunction getLastEventId() {\n try {\n const p = eventsPath();\n if (!fs.existsSync(p)) return null;\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n if (lines.length === 0) return null;\n const last = JSON.parse(lines[lines.length - 1]);\n return last && typeof last.id === 'string' ? last.id : null;\n } catch { return null; }\n}\n\nfunction readAllEvents() {\n try {\n const p = eventsPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n return raw.split('\\n').map(l => l.trim()).filter(Boolean).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\nfunction appendEventJsonl(eventObj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(eventsPath(), JSON.stringify(eventObj) + '\\n', 'utf8');\n}\n\nfunction appendCandidateJsonl(candidateObj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(candidatesPath(), JSON.stringify(candidateObj) + '\\n', 'utf8');\n}\n\nfunction appendExternalCandidateJsonl(obj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(externalCandidatesPath(), JSON.stringify(obj) + '\\n', 'utf8');\n}\n\nfunction readRecentCandidates(limit = 20) {\n try {\n const p = candidatesPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n return lines.slice(Math.max(0, lines.length - limit)).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\nfunction readRecentExternalCandidates(limit = 50) {\n try {\n const p = externalCandidatesPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n return lines.slice(Math.max(0, lines.length - limit)).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\n// Safety net: ensure schema_version and asset_id are present before writing.\nfunction ensureSchemaFields(obj) {\n if (!obj || typeof obj !== 'object') return obj;\n if (!obj.schema_version) obj.schema_version = SCHEMA_VERSION;\n if (!obj.asset_id) { try { obj.asset_id = computeAssetId(obj); } catch (e) {} }\n return obj;\n}\n\nfunction upsertGene(geneObj) {\n ensureSchemaFields(geneObj);\n const current = readJsonIfExists(genesPath(), getDefaultGenes());\n const genes = Array.isArray(current.genes) ? current.genes : [];\n const idx = genes.findIndex(g => g && g.id === geneObj.id);\n if (idx >= 0) genes[idx] = geneObj; else genes.push(geneObj);\n writeJsonAtomic(genesPath(), { version: current.version || 1, genes });\n}\n\nfunction appendCapsule(capsuleObj) {\n ensureSchemaFields(capsuleObj);\n const current = readJsonIfExists(capsulesPath(), getDefaultCapsules());\n const capsules = Array.isArray(current.capsules) ? current.capsules : [];\n capsules.push(capsuleObj);\n writeJsonAtomic(capsulesPath(), { version: current.version || 1, capsules });\n}\n\nfunction upsertCapsule(capsuleObj) {\n if (!capsuleObj || capsuleObj.type !== 'Capsule' || !capsuleObj.id) return;\n ensureSchemaFields(capsuleObj);\n const current = readJsonIfExists(capsulesPath(), getDefaultCapsules());\n const capsules = Array.isArray(current.capsules) ? current.capsules : [];\n const idx = capsules.findIndex(c => c && c.type === 'Capsule' && String(c.id) === String(capsuleObj.id));\n if (idx >= 0) capsules[idx] = capsuleObj; else capsules.push(capsuleObj);\n writeJsonAtomic(capsulesPath(), { version: current.version || 1, capsules });\n}\n\nmodule.exports = {\n loadGenes, loadCapsules, readAllEvents, getLastEventId,\n appendEventJsonl, appendCandidateJsonl, appendExternalCandidateJsonl,\n readRecentCandidates, readRecentExternalCandidates,\n upsertGene, appendCapsule, upsertCapsule,\n genesPath, capsulesPath, eventsPath, candidatesPath, externalCandidatesPath,\n};\n",
361 "inputSchema": {},
362 "outputSchema": null,
363 "icons": null,
364 "annotations": null,
365 "meta": null,
366 "execution": null
367 },
368 {
369 "name": "candidates.js",
370 "title": null,
371 "description": "Script: candidates.js. Code:\nfunction stableHash(input) {\n // Deterministic lightweight hash (not cryptographic).\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction clip(text, maxChars) {\n const s = String(text || '');\n if (!maxChars || s.length <= maxChars) return s;\n return s.slice(0, Math.max(0, maxChars - 20)) + ' ...[TRUNCATED]';\n}\n\nfunction toLines(text) {\n return String(text || '')\n .split('\\n')\n .map(l => l.trimEnd())\n .filter(Boolean);\n}\n\nfunction extractToolCalls(transcript) {\n const lines = toLines(transcript);\n const calls = [];\n for (const line of lines) {\n const m = line.match(/\\[TOOL:\\s*([^\\]]+)\\]/i);\n if (m && m[1]) calls.push(m[1].trim());\n }\n return calls;\n}\n\nfunction countFreq(items) {\n const map = new Map();\n for (const it of items) map.set(it, (map.get(it) || 0) + 1);\n return map;\n}\n\nfunction buildFiveQuestionsShape({ title, signals, evidence }) {\n // Keep it short and structured; this is a template, not a perfect inference.\n const input = 'Recent session transcript + memory snippets + user instructions';\n const output = 'A safe, auditable evolution patch guided by GEP assets';\n const invariants = 'Protocol order, small reversible patches, validation, append-only events';\n const params = `Signals: ${Array.isArray(signals) ? signals.join(', ') : ''}`.trim();\n const failurePoints = 'Missing signals, over-broad changes, skipped validation, missing knowledge solidification';\n return {\n title: String(title || '').slice(0, 120),\n input,\n output,\n invariants,\n params: params || 'Signals: (none)',\n failure_points: failurePoints,\n evidence: clip(evidence, 240),\n };\n}\n\nfunction extractCapabilityCandidates({ recentSessionTranscript, signals }) {\n const candidates = [];\n const toolCalls = extractToolCalls(recentSessionTranscript);\n const freq = countFreq(toolCalls);\n\n for (const [tool, count] of freq.entries()) {\n if (count < 2) continue;\n const title = `Repeated tool usage: ${tool}`;\n const evidence = `Observed ${count} occurrences of tool call marker for ${tool}.`;\n const shape = buildFiveQuestionsShape({ title, signals, evidence });\n candidates.push({\n type: 'CapabilityCandidate',\n id: `cand_${stableHash(title)}`,\n title,\n source: 'transcript',\n created_at: new Date().toISOString(),\n signals: Array.isArray(signals) ? signals : [],\n shape,\n });\n }\n\n // Signals-as-candidates: capture recurring pain points as reusable capability shapes.\n const signalList = Array.isArray(signals) ? signals : [];\n const signalCandidates = [\n // Defensive signals\n { signal: 'log_error', title: 'Repair recurring runtime errors' },\n { signal: 'protocol_drift', title: 'Prevent protocol drift and enforce auditable outputs' },\n { signal: 'windows_shell_incompatible', title: 'Avoid platform-specific shell assumptions (Windows compatibility)' },\n { signal: 'session_logs_missing', title: 'Harden session log detection and fallback behavior' },\n // Opportunity signals (innovation)\n { signal: 'user_feature_request', title: 'Implement user-requested feature' },\n { signal: 'user_improvement_suggestion', title: 'Apply user improvement suggestion' },\n { signal: 'perf_bottleneck', title: 'Resolve performance bottleneck' },\n { signal: 'capability_gap', title: 'Fill capability gap' },\n { signal: 'stable_success_plateau', title: 'Explore new strategies during stability plateau' },\n { signal: 'external_opportunity', title: 'Evaluate external A2A asset for local adoption' },\n ];\n\n for (const sc of signalCandidates) {\n if (!signalList.includes(sc.signal)) continue;\n const evidence = `Signal present: ${sc.signal}`;\n const shape = buildFiveQuestionsShape({ title: sc.title, signals, evidence });\n candidates.push({\n type: 'CapabilityCandidate',\n id: `cand_${stableHash(sc.signal)}`,\n title: sc.title,\n source: 'signals',\n created_at: new Date().toISOString(),\n signals: signalList,\n shape,\n });\n }\n\n // Dedup by id\n const seen = new Set();\n return candidates.filter(c => {\n if (!c || !c.id) return false;\n if (seen.has(c.id)) return false;\n seen.add(c.id);\n return true;\n });\n}\n\nfunction renderCandidatesPreview(candidates, maxChars = 1400) {\n const list = Array.isArray(candidates) ? candidates : [];\n const lines = [];\n for (const c of list) {\n const s = c && c.shape ? c.shape : {};\n lines.push(`- ${c.id}: ${c.title}`);\n lines.push(` - input: ${s.input || ''}`);\n lines.push(` - output: ${s.output || ''}`);\n lines.push(` - invariants: ${s.invariants || ''}`);\n lines.push(` - params: ${s.params || ''}`);\n lines.push(` - failure_points: ${s.failure_points || ''}`);\n if (s.evidence) lines.push(` - evidence: ${s.evidence}`);\n }\n return clip(lines.join('\\n'), maxChars);\n}\n\nmodule.exports = {\n extractCapabilityCandidates,\n renderCandidatesPreview,\n};\n\n",
372 "inputSchema": {},
373 "outputSchema": null,
374 "icons": null,
375 "annotations": null,
376 "meta": null,
377 "execution": null
378 },
379 {
380 "name": "mutation.js",
381 "title": null,
382 "description": "Script: mutation.js. Code:\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction nowTsMs() {\n return Date.now();\n}\n\nfunction uniqStrings(list) {\n const out = [];\n const seen = new Set();\n for (const x of Array.isArray(list) ? list : []) {\n const s = String(x || '').trim();\n if (!s) continue;\n if (seen.has(s)) continue;\n seen.add(s);\n out.push(s);\n }\n return out;\n}\n\nfunction hasErrorishSignal(signals) {\n const list = Array.isArray(signals) ? signals.map(s => String(s || '')) : [];\n if (list.includes('log_error')) return true;\n if (list.some(s => s.startsWith('errsig:') || s.startsWith('errsig_norm:'))) return true;\n return false;\n}\n\n// Opportunity signals that indicate a chance to innovate (not just fix).\nvar OPPORTUNITY_SIGNALS = [\n 'user_feature_request',\n 'user_improvement_suggestion',\n 'perf_bottleneck',\n 'capability_gap',\n 'stable_success_plateau',\n 'external_opportunity',\n];\n\nfunction hasOpportunitySignal(signals) {\n var list = Array.isArray(signals) ? signals.map(function (s) { return String(s || ''); }) : [];\n for (var i = 0; i < OPPORTUNITY_SIGNALS.length; i++) {\n if (list.includes(OPPORTUNITY_SIGNALS[i])) return true;\n }\n return false;\n}\n\nfunction mutationCategoryFromContext({ signals, driftEnabled }) {\n if (hasErrorishSignal(signals)) return 'repair';\n if (driftEnabled) return 'innovate';\n // Auto-innovate: opportunity signals present and no errors\n if (hasOpportunitySignal(signals)) return 'innovate';\n return 'optimize';\n}\n\nfunction expectedEffectFromCategory(category) {\n const c = String(category || '');\n if (c === 'repair') return 'reduce runtime errors, increase stability, and lower failure rate';\n if (c === 'optimize') return 'improve success rate and reduce repeated operational cost';\n if (c === 'innovate') return 'explore new strategy combinations to escape local optimum';\n return 'improve robustness and success probability';\n}\n\nfunction targetFromGene(selectedGene) {\n if (selectedGene && selectedGene.id) return `gene:${String(selectedGene.id)}`;\n return 'behavior:protocol';\n}\n\nfunction isHighRiskPersonality(p) {\n // Conservative definition: low rigor or high risk_tolerance is treated as high-risk personality.\n const rigor = p && Number.isFinite(Number(p.rigor)) ? Number(p.rigor) : null;\n const riskTol = p && Number.isFinite(Number(p.risk_tolerance)) ? Number(p.risk_tolerance) : null;\n if (rigor != null && rigor < 0.5) return true;\n if (riskTol != null && riskTol > 0.6) return true;\n return false;\n}\n\nfunction isHighRiskMutationAllowed(personalityState) {\n const rigor = personalityState && Number.isFinite(Number(personalityState.rigor)) ? Number(personalityState.rigor) : 0;\n const riskTol =\n personalityState && Number.isFinite(Number(personalityState.risk_tolerance))\n ? Number(personalityState.risk_tolerance)\n : 1;\n return rigor >= 0.6 && riskTol <= 0.5;\n}\n\nfunction buildMutation({\n signals,\n selectedGene,\n driftEnabled,\n personalityState,\n allowHighRisk = false,\n target,\n expected_effect,\n} = {}) {\n const ts = nowTsMs();\n const category = mutationCategoryFromContext({ signals, driftEnabled: !!driftEnabled });\n const triggerSignals = uniqStrings(signals);\n\n const base = {\n type: 'Mutation',\n id: `mut_${ts}`,\n category,\n trigger_signals: triggerSignals,\n target: String(target || targetFromGene(selectedGene)),\n expected_effect: String(expected_effect || expectedEffectFromCategory(category)),\n risk_level: 'low',\n };\n\n // Default risk assignment: innovate is medium; others low.\n if (category === 'innovate') base.risk_level = 'medium';\n\n // Optional high-risk escalation (rare, and guarded by strict safety constraints).\n if (allowHighRisk && category === 'innovate') {\n base.risk_level = 'high';\n }\n\n // Safety constraints (hard):\n // - forbid innovate + high-risk personality (downgrade innovation to optimize)\n // - forbid high-risk mutation unless personality satisfies constraints\n const highRiskPersonality = isHighRiskPersonality(personalityState || null);\n if (base.category === 'innovate' && highRiskPersonality) {\n base.category = 'optimize';\n base.expected_effect = 'safety downgrade: optimize under high-risk personality (avoid innovate+high-risk combo)';\n base.risk_level = 'low';\n base.trigger_signals = uniqStrings([...(base.trigger_signals || []), 'safety:avoid_innovate_with_high_risk_personality']);\n }\n\n if (base.risk_level === 'high' && !isHighRiskMutationAllowed(personalityState || null)) {\n // Downgrade rather than emit illegal high-risk mutation.\n base.risk_level = 'medium';\n base.trigger_signals = uniqStrings([...(base.trigger_signals || []), 'safety:downgrade_high_risk']);\n }\n\n return base;\n}\n\nfunction isValidMutation(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'Mutation') return false;\n if (!obj.id || typeof obj.id !== 'string') return false;\n if (!obj.category || !['repair', 'optimize', 'innovate'].includes(String(obj.category))) return false;\n if (!Array.isArray(obj.trigger_signals)) return false;\n if (!obj.target || typeof obj.target !== 'string') return false;\n if (!obj.expected_effect || typeof obj.expected_effect !== 'string') return false;\n if (!obj.risk_level || !['low', 'medium', 'high'].includes(String(obj.risk_level))) return false;\n return true;\n}\n\nfunction normalizeMutation(obj) {\n const m = obj && typeof obj === 'object' ? obj : {};\n const out = {\n type: 'Mutation',\n id: typeof m.id === 'string' ? m.id : `mut_${nowTsMs()}`,\n category: ['repair', 'optimize', 'innovate'].includes(String(m.category)) ? String(m.category) : 'optimize',\n trigger_signals: uniqStrings(m.trigger_signals),\n target: typeof m.target === 'string' ? m.target : 'behavior:protocol',\n expected_effect: typeof m.expected_effect === 'string' ? m.expected_effect : expectedEffectFromCategory(m.category),\n risk_level: ['low', 'medium', 'high'].includes(String(m.risk_level)) ? String(m.risk_level) : 'low',\n };\n return out;\n}\n\nmodule.exports = {\n clamp01,\n buildMutation,\n isValidMutation,\n normalizeMutation,\n isHighRiskMutationAllowed,\n isHighRiskPersonality,\n hasOpportunitySignal,\n};\n\n",
383 "inputSchema": {},
384 "outputSchema": null,
385 "icons": null,
386 "annotations": null,
387 "meta": null,
388 "execution": null
389 },
390 {
391 "name": "validationReport.js",
392 "title": null,
393 "description": "Script: validationReport.js. Code:\n// Standardized ValidationReport type for GEP.\n// Machine-readable, self-contained, and interoperable.\n// Can be consumed by external Hubs or Judges for automated assessment.\n\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { captureEnvFingerprint, envFingerprintKey } = require('./envFingerprint');\n\n// Build a standardized ValidationReport from raw validation results.\nfunction buildValidationReport({ geneId, commands, results, envFp, startedAt, finishedAt }) {\n const env = envFp || captureEnvFingerprint();\n const resultsList = Array.isArray(results) ? results : [];\n const cmdsList = Array.isArray(commands) ? commands : resultsList.map(function (r) { return r && r.cmd ? String(r.cmd) : ''; });\n const overallOk = resultsList.length > 0 && resultsList.every(function (r) { return r && r.ok; });\n const durationMs =\n Number.isFinite(startedAt) && Number.isFinite(finishedAt) ? finishedAt - startedAt : null;\n\n const report = {\n type: 'ValidationReport',\n schema_version: SCHEMA_VERSION,\n id: 'vr_' + Date.now(),\n gene_id: geneId || null,\n env_fingerprint: env,\n env_fingerprint_key: envFingerprintKey(env),\n commands: cmdsList.map(function (cmd, i) {\n const r = resultsList[i] || {};\n return {\n command: String(cmd || ''),\n ok: !!r.ok,\n stdout: String(r.out || '').slice(0, 4000),\n stderr: String(r.err || '').slice(0, 4000),\n };\n }),\n overall_ok: overallOk,\n duration_ms: durationMs,\n created_at: new Date().toISOString(),\n };\n\n report.asset_id = computeAssetId(report);\n return report;\n}\n\n// Validate that an object is a well-formed ValidationReport.\nfunction isValidValidationReport(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'ValidationReport') return false;\n if (!obj.id || typeof obj.id !== 'string') return false;\n if (!Array.isArray(obj.commands)) return false;\n if (typeof obj.overall_ok !== 'boolean') return false;\n return true;\n}\n\nmodule.exports = {\n buildValidationReport,\n isValidValidationReport,\n};\n",
394 "inputSchema": {},
395 "outputSchema": null,
396 "icons": null,
397 "annotations": null,
398 "meta": null,
399 "execution": null
400 },
401 {
402 "name": "contentHash.js",
403 "title": null,
404 "description": "Script: contentHash.js. Code:\n// Content-addressable hashing for GEP assets.\n// Provides canonical JSON serialization and SHA-256 based asset IDs.\n// This enables deduplication, tamper detection, and cross-node consistency.\n\nconst crypto = require('crypto');\n\n// Schema version for all GEP asset types.\n// Bump MINOR for additive fields; MAJOR for breaking changes.\nconst SCHEMA_VERSION = '1.5.0';\n\n// Canonical JSON: deterministic serialization with sorted keys at all levels.\n// Arrays preserve order; non-finite numbers become null; undefined becomes null.\nfunction canonicalize(obj) {\n if (obj === null || obj === undefined) return 'null';\n if (typeof obj === 'boolean') return obj ? 'true' : 'false';\n if (typeof obj === 'number') {\n if (!Number.isFinite(obj)) return 'null';\n return String(obj);\n }\n if (typeof obj === 'string') return JSON.stringify(obj);\n if (Array.isArray(obj)) {\n return '[' + obj.map(canonicalize).join(',') + ']';\n }\n if (typeof obj === 'object') {\n const keys = Object.keys(obj).sort();\n const pairs = [];\n for (const k of keys) {\n pairs.push(JSON.stringify(k) + ':' + canonicalize(obj[k]));\n }\n return '{' + pairs.join(',') + '}';\n }\n return 'null';\n}\n\n// Compute a content-addressable asset ID.\n// Excludes self-referential fields (asset_id itself) from the hash input.\n// Returns \"sha256:<hex>\".\nfunction computeAssetId(obj, excludeFields) {\n if (!obj || typeof obj !== 'object') return null;\n const exclude = new Set(Array.isArray(excludeFields) ? excludeFields : ['asset_id']);\n const clean = {};\n for (const k of Object.keys(obj)) {\n if (exclude.has(k)) continue;\n clean[k] = obj[k];\n }\n const canonical = canonicalize(clean);\n const hash = crypto.createHash('sha256').update(canonical, 'utf8').digest('hex');\n return 'sha256:' + hash;\n}\n\n// Verify that an object's asset_id matches its content.\nfunction verifyAssetId(obj) {\n if (!obj || typeof obj !== 'object') return false;\n const claimed = obj.asset_id;\n if (!claimed || typeof claimed !== 'string') return false;\n const computed = computeAssetId(obj);\n return claimed === computed;\n}\n\nmodule.exports = {\n SCHEMA_VERSION,\n canonicalize,\n computeAssetId,\n verifyAssetId,\n};\n",
405 "inputSchema": {},
406 "outputSchema": null,
407 "icons": null,
408 "annotations": null,
409 "meta": null,
410 "execution": null
411 },
412 {
413 "name": "personality.js",
414 "title": null,
415 "description": "Script: personality.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getMemoryDir } = require('./paths');\nconst { hasOpportunitySignal } = require('./mutation');\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction personalityFilePath() {\n const memoryDir = getMemoryDir();\n const { getEvolutionDir } = require('./paths'); return path.join(getEvolutionDir(), 'personality_state.json');\n}\n\nfunction defaultPersonalityState() {\n // Conservative defaults: protocol-first, safe, low-risk.\n return {\n type: 'PersonalityState',\n rigor: 0.7,\n creativity: 0.35,\n verbosity: 0.25,\n risk_tolerance: 0.4,\n obedience: 0.85,\n };\n}\n\nfunction normalizePersonalityState(state) {\n const s = state && typeof state === 'object' ? state : {};\n return {\n type: 'PersonalityState',\n rigor: clamp01(s.rigor),\n creativity: clamp01(s.creativity),\n verbosity: clamp01(s.verbosity),\n risk_tolerance: clamp01(s.risk_tolerance),\n obedience: clamp01(s.obedience),\n };\n}\n\nfunction isValidPersonalityState(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'PersonalityState') return false;\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n const v = obj[k];\n if (!Number.isFinite(Number(v))) return false;\n const n = Number(v);\n if (n < 0 || n > 1) return false;\n }\n return true;\n}\n\nfunction roundToStep(x, step) {\n const s = Number(step);\n if (!Number.isFinite(s) || s <= 0) return x;\n return Math.round(Number(x) / s) * s;\n}\n\nfunction personalityKey(state) {\n const s = normalizePersonalityState(state);\n const step = 0.1;\n const r = roundToStep(s.rigor, step).toFixed(1);\n const c = roundToStep(s.creativity, step).toFixed(1);\n const v = roundToStep(s.verbosity, step).toFixed(1);\n const rt = roundToStep(s.risk_tolerance, step).toFixed(1);\n const o = roundToStep(s.obedience, step).toFixed(1);\n return `rigor=${r}|creativity=${c}|verbosity=${v}|risk_tolerance=${rt}|obedience=${o}`;\n}\n\nfunction getParamDeltas(fromState, toState) {\n const a = normalizePersonalityState(fromState);\n const b = normalizePersonalityState(toState);\n const deltas = [];\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n deltas.push({ param: k, delta: Number(b[k]) - Number(a[k]) });\n }\n deltas.sort((x, y) => Math.abs(y.delta) - Math.abs(x.delta));\n return deltas;\n}\n\nfunction personalityScore(statsEntry) {\n const e = statsEntry && typeof statsEntry === 'object' ? statsEntry : {};\n const succ = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = succ + fail;\n // Laplace-smoothed success probability\n const p = (succ + 1) / (total + 2);\n // Penalize tiny-sample overconfidence\n const sampleWeight = Math.min(1, total / 8);\n // Use avg_score (if present) as mild quality proxy\n const avg = Number.isFinite(Number(e.avg_score)) ? Number(e.avg_score) : null;\n const q = avg == null ? 0.5 : clamp01(avg);\n return p * 0.75 + q * 0.25 * sampleWeight;\n}\n\nfunction chooseBestKnownPersonality(statsByKey) {\n const stats = statsByKey && typeof statsByKey === 'object' ? statsByKey : {};\n let best = null;\n for (const [k, entry] of Object.entries(stats)) {\n const e = entry || {};\n const total = (Number(e.success) || 0) + (Number(e.fail) || 0);\n if (total < 3) continue;\n const sc = personalityScore(e);\n if (!best || sc > best.score) best = { key: k, score: sc, entry: e };\n }\n return best;\n}\n\nfunction parseKeyToState(key) {\n // key format: rigor=0.7|creativity=0.3|...\n const out = defaultPersonalityState();\n const parts = String(key || '').split('|').map(s => s.trim()).filter(Boolean);\n for (const p of parts) {\n const [k, v] = p.split('=').map(x => String(x || '').trim());\n if (!k) continue;\n if (!['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience'].includes(k)) continue;\n out[k] = clamp01(Number(v));\n }\n return normalizePersonalityState(out);\n}\n\nfunction applyPersonalityMutations(state, mutations) {\n let cur = normalizePersonalityState(state);\n const muts = Array.isArray(mutations) ? mutations : [];\n const applied = [];\n let count = 0;\n for (const m of muts) {\n if (!m || typeof m !== 'object') continue;\n const param = String(m.param || '').trim();\n if (!['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience'].includes(param)) continue;\n const delta = Number(m.delta);\n if (!Number.isFinite(delta)) continue;\n const clipped = Math.max(-0.2, Math.min(0.2, delta));\n cur[param] = clamp01(Number(cur[param]) + clipped);\n applied.push({ type: 'PersonalityMutation', param, delta: clipped, reason: String(m.reason || '').slice(0, 140) });\n count += 1;\n if (count >= 2) break;\n }\n return { state: cur, applied };\n}\n\nfunction proposeMutations({ baseState, reason, driftEnabled, signals }) {\n const s = normalizePersonalityState(baseState);\n const sig = Array.isArray(signals) ? signals.map(x => String(x || '')) : [];\n const muts = [];\n\n const r = String(reason || '');\n if (driftEnabled) {\n muts.push({ type: 'PersonalityMutation', param: 'creativity', delta: +0.1, reason: r || 'drift enabled' });\n // Keep risk bounded under drift by default.\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: -0.05, reason: 'drift safety clamp' });\n } else if (sig.includes('protocol_drift')) {\n muts.push({ type: 'PersonalityMutation', param: 'obedience', delta: +0.1, reason: r || 'protocol drift' });\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.05, reason: 'tighten protocol compliance' });\n } else if (sig.includes('log_error') || sig.some(x => x.startsWith('errsig:') || x.startsWith('errsig_norm:'))) {\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.1, reason: r || 'repair instability' });\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: -0.1, reason: 'reduce risky changes under errors' });\n } else if (hasOpportunitySignal(sig)) {\n // Opportunity detected: nudge towards creativity to enable innovation.\n muts.push({ type: 'PersonalityMutation', param: 'creativity', delta: +0.1, reason: r || 'opportunity signal detected' });\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: +0.05, reason: 'allow exploration for innovation' });\n } else {\n // Plateau-like generic: slightly increase rigor, slightly decrease verbosity (more concise execution).\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.05, reason: r || 'stability bias' });\n muts.push({ type: 'PersonalityMutation', param: 'verbosity', delta: -0.05, reason: 'reduce noise' });\n }\n\n // If already very high obedience, avoid pushing it further; swap second mutation to creativity.\n if (s.obedience >= 0.95) {\n const idx = muts.findIndex(x => x.param === 'obedience');\n if (idx >= 0) muts[idx] = { type: 'PersonalityMutation', param: 'creativity', delta: +0.05, reason: 'obedience saturated' };\n }\n return muts;\n}\n\nfunction shouldTriggerPersonalityMutation({ driftEnabled, recentEvents }) {\n if (driftEnabled) return { ok: true, reason: 'drift enabled' };\n const list = Array.isArray(recentEvents) ? recentEvents : [];\n const tail = list.slice(-6);\n const outcomes = tail\n .map(e => (e && e.outcome && e.outcome.status ? String(e.outcome.status) : null))\n .filter(Boolean);\n if (outcomes.length >= 4) {\n const recentFailed = outcomes.slice(-4).filter(x => x === 'failed').length;\n if (recentFailed >= 3) return { ok: true, reason: 'long failure streak' };\n }\n // Mutation consecutive failure proxy: last 3 events that have mutation_id.\n const withMut = tail.filter(e => e && typeof e.mutation_id === 'string' && e.mutation_id);\n if (withMut.length >= 3) {\n const last3 = withMut.slice(-3);\n const fail3 = last3.filter(e => e && e.outcome && e.outcome.status === 'failed').length;\n if (fail3 >= 3) return { ok: true, reason: 'mutation consecutive failures' };\n }\n return { ok: false, reason: '' };\n}\n\nfunction loadPersonalityModel() {\n const p = personalityFilePath();\n const fallback = {\n version: 1,\n current: defaultPersonalityState(),\n stats: {},\n history: [],\n updated_at: nowIso(),\n };\n const raw = readJsonIfExists(p, fallback);\n const cur = normalizePersonalityState(raw && raw.current ? raw.current : defaultPersonalityState());\n const stats = raw && typeof raw.stats === 'object' ? raw.stats : {};\n const history = Array.isArray(raw && raw.history) ? raw.history : [];\n return { version: 1, current: cur, stats, history, updated_at: raw && raw.updated_at ? raw.updated_at : nowIso() };\n}\n\nfunction savePersonalityModel(model) {\n const m = model && typeof model === 'object' ? model : {};\n const out = {\n version: 1,\n current: normalizePersonalityState(m.current || defaultPersonalityState()),\n stats: m.stats && typeof m.stats === 'object' ? m.stats : {},\n history: Array.isArray(m.history) ? m.history.slice(-120) : [],\n updated_at: nowIso(),\n };\n writeJsonAtomic(personalityFilePath(), out);\n return out;\n}\n\nfunction selectPersonalityForRun({ driftEnabled, signals, recentEvents } = {}) {\n const model = loadPersonalityModel();\n const base = normalizePersonalityState(model.current);\n const stats = model.stats || {};\n\n const best = chooseBestKnownPersonality(stats);\n let naturalSelectionApplied = [];\n\n // Natural selection: nudge towards the best-known configuration (small, max 2 params).\n if (best && best.key) {\n const bestState = parseKeyToState(best.key);\n const diffs = getParamDeltas(base, bestState).filter(d => Math.abs(d.delta) >= 0.05);\n const muts = [];\n for (const d of diffs.slice(0, 2)) {\n const clipped = Math.max(-0.1, Math.min(0.1, d.delta));\n muts.push({ type: 'PersonalityMutation', param: d.param, delta: clipped, reason: 'natural_selection' });\n }\n const applied = applyPersonalityMutations(base, muts);\n model.current = applied.state;\n naturalSelectionApplied = applied.applied;\n }\n\n // Triggered personality mutation (explicit rule-based).\n const trig = shouldTriggerPersonalityMutation({ driftEnabled: !!driftEnabled, recentEvents });\n let triggeredApplied = [];\n if (trig.ok) {\n const props = proposeMutations({\n baseState: model.current,\n reason: trig.reason,\n driftEnabled: !!driftEnabled,\n signals,\n });\n const applied = applyPersonalityMutations(model.current, props);\n model.current = applied.state;\n triggeredApplied = applied.applied;\n }\n\n // Persist updated current state.\n const saved = savePersonalityModel(model);\n const key = personalityKey(saved.current);\n const known = !!(saved.stats && saved.stats[key]);\n\n return {\n personality_state: saved.current,\n personality_key: key,\n personality_known: known,\n personality_mutations: [...naturalSelectionApplied, ...triggeredApplied],\n model_meta: {\n best_known_key: best && best.key ? best.key : null,\n best_known_score: best && Number.isFinite(Number(best.score)) ? Number(best.score) : null,\n triggered: trig.ok ? { reason: trig.reason } : null,\n },\n };\n}\n\nfunction updatePersonalityStats({ personalityState, outcome, score, notes } = {}) {\n const model = loadPersonalityModel();\n const st = normalizePersonalityState(personalityState || model.current);\n const key = personalityKey(st);\n if (!model.stats || typeof model.stats !== 'object') model.stats = {};\n const cur = model.stats[key] && typeof model.stats[key] === 'object' ? model.stats[key] : { success: 0, fail: 0, avg_score: 0.5, n: 0 };\n\n const out = String(outcome || '').toLowerCase();\n if (out === 'success') cur.success = (Number(cur.success) || 0) + 1;\n else if (out === 'failed') cur.fail = (Number(cur.fail) || 0) + 1;\n\n const sc = Number.isFinite(Number(score)) ? clamp01(Number(score)) : null;\n if (sc != null) {\n const n = (Number(cur.n) || 0) + 1;\n const prev = Number.isFinite(Number(cur.avg_score)) ? Number(cur.avg_score) : 0.5;\n cur.avg_score = prev + (sc - prev) / n;\n cur.n = n;\n }\n cur.updated_at = nowIso();\n model.stats[key] = cur;\n\n model.history = Array.isArray(model.history) ? model.history : [];\n model.history.push({\n at: nowIso(),\n key,\n outcome: out === 'success' || out === 'failed' ? out : 'unknown',\n score: sc,\n notes: notes ? String(notes).slice(0, 220) : null,\n });\n\n savePersonalityModel(model);\n return { key, stats: cur };\n}\n\nmodule.exports = {\n clamp01,\n defaultPersonalityState,\n normalizePersonalityState,\n isValidPersonalityState,\n personalityKey,\n loadPersonalityModel,\n savePersonalityModel,\n selectPersonalityForRun,\n updatePersonalityStats,\n};\n\n",
416 "inputSchema": {},
417 "outputSchema": null,
418 "icons": null,
419 "annotations": null,
420 "meta": null,
421 "execution": null
422 },
423 {
424 "name": "paths.js",
425 "title": null,
426 "description": "Script: paths.js. Code:\nconst path = require('path');\n\nfunction getRepoRoot() {\n // src/gep/paths.js -> repo root\n return path.resolve(__dirname, '..', '..');\n}\n\nfunction getMemoryDir() {\n const repoRoot = getRepoRoot();\n return process.env.MEMORY_DIR || path.join(repoRoot, 'memory');\n}\n\nfunction getEvolutionDir() {\n return process.env.EVOLUTION_DIR || path.join(getMemoryDir(), 'evolution');\n}\n\nfunction getGepAssetsDir() {\n const repoRoot = getRepoRoot();\n return process.env.GEP_ASSETS_DIR || path.join(repoRoot, 'assets', 'gep');\n}\n\nfunction getWorkspaceRoot() {\n // evolver repo root is skills/evolver/, workspace is two levels up\n return process.env.OPENCLAW_WORKSPACE || path.resolve(getRepoRoot(), '..', '..');\n}\n\nfunction getSkillsDir() {\n return path.join(getWorkspaceRoot(), 'skills');\n}\n\nfunction getLogsDir() {\n var dir = path.join(getWorkspaceRoot(), 'logs');\n var fs = require('fs');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nmodule.exports = {\n getRepoRoot,\n getMemoryDir,\n getEvolutionDir,\n getGepAssetsDir,\n getWorkspaceRoot,\n getSkillsDir,\n getLogsDir,\n};\n\n",
427 "inputSchema": {},
428 "outputSchema": null,
429 "icons": null,
430 "annotations": null,
431 "meta": null,
432 "execution": null
433 },
434 {
435 "name": "a2a.js",
436 "title": null,
437 "description": "Script: a2a.js. Code:\nconst fs = require('fs');\nconst { readAllEvents } = require('./assetStore');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { unwrapAssetFromMessage } = require('./a2aProtocol');\n\nfunction nowIso() { return new Date().toISOString(); }\n\nfunction isAllowedA2AAsset(obj) {\n if (!obj || typeof obj !== 'object') return false;\n var t = obj.type;\n return t === 'Gene' || t === 'Capsule' || t === 'EvolutionEvent';\n}\n\nfunction safeNumber(x, fallback) {\n if (fallback === undefined) fallback = null;\n var n = Number(x);\n return Number.isFinite(n) ? n : fallback;\n}\n\nfunction getBlastRadiusLimits() {\n var maxFiles = safeNumber(process.env.A2A_MAX_FILES, 5);\n var maxLines = safeNumber(process.env.A2A_MAX_LINES, 200);\n return {\n maxFiles: Number.isFinite(maxFiles) ? maxFiles : 5,\n maxLines: Number.isFinite(maxLines) ? maxLines : 200,\n };\n}\n\nfunction isBlastRadiusSafe(blastRadius) {\n var lim = getBlastRadiusLimits();\n var files = blastRadius && Number.isFinite(Number(blastRadius.files)) ? Number(blastRadius.files) : 0;\n var lines = blastRadius && Number.isFinite(Number(blastRadius.lines)) ? Number(blastRadius.lines) : 0;\n return files <= lim.maxFiles && lines <= lim.maxLines;\n}\n\nfunction clamp01(n) {\n var x = Number(n);\n if (!Number.isFinite(x)) return 0;\n return Math.max(0, Math.min(1, x));\n}\n\nfunction lowerConfidence(asset, opts) {\n if (!opts) opts = {};\n var factor = Number.isFinite(Number(opts.factor)) ? Number(opts.factor) : 0.6;\n var receivedFrom = opts.source || 'external';\n var receivedAt = opts.received_at || nowIso();\n var cloned = JSON.parse(JSON.stringify(asset || {}));\n if (!isAllowedA2AAsset(cloned)) return null;\n if (cloned.type === 'Capsule') {\n if (typeof cloned.confidence === 'number') cloned.confidence = clamp01(cloned.confidence * factor);\n else if (cloned.confidence != null) cloned.confidence = clamp01(Number(cloned.confidence) * factor);\n }\n if (!cloned.a2a || typeof cloned.a2a !== 'object') cloned.a2a = {};\n cloned.a2a.status = 'external_candidate';\n cloned.a2a.source = receivedFrom;\n cloned.a2a.received_at = receivedAt;\n cloned.a2a.confidence_factor = factor;\n if (!cloned.schema_version) cloned.schema_version = SCHEMA_VERSION;\n if (!cloned.asset_id) { try { cloned.asset_id = computeAssetId(cloned); } catch (e) {} }\n return cloned;\n}\n\nfunction readEvolutionEvents() {\n var events = readAllEvents();\n return Array.isArray(events) ? events.filter(function (e) { return e && e.type === 'EvolutionEvent'; }) : [];\n}\n\nfunction normalizeEventsList(events) {\n return Array.isArray(events) ? events : [];\n}\n\nfunction computeCapsuleSuccessStreak(params) {\n var capsuleId = params.capsuleId;\n var events = params.events;\n var id = capsuleId ? String(capsuleId) : '';\n if (!id) return 0;\n var list = normalizeEventsList(events || readEvolutionEvents());\n var streak = 0;\n for (var i = list.length - 1; i >= 0; i--) {\n var ev = list[i];\n if (!ev || ev.type !== 'EvolutionEvent') continue;\n if (!ev.capsule_id || String(ev.capsule_id) !== id) continue;\n var st = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (st === 'success') streak += 1; else break;\n }\n return streak;\n}\n\nfunction isCapsuleBroadcastEligible(capsule, opts) {\n if (!opts) opts = {};\n if (!capsule || capsule.type !== 'Capsule') return false;\n var score = capsule.outcome && capsule.outcome.score != null ? safeNumber(capsule.outcome.score, null) : null;\n if (score == null || score < 0.7) return false;\n var blast = capsule.blast_radius || (capsule.outcome && capsule.outcome.blast_radius) || null;\n if (!isBlastRadiusSafe(blast)) return false;\n var events = Array.isArray(opts.events) ? opts.events : readEvolutionEvents();\n var streak = computeCapsuleSuccessStreak({ capsuleId: capsule.id, events: events });\n if (streak < 2) return false;\n return true;\n}\n\nfunction exportEligibleCapsules(params) {\n if (!params) params = {};\n var list = Array.isArray(params.capsules) ? params.capsules : [];\n var evs = Array.isArray(params.events) ? params.events : readEvolutionEvents();\n var eligible = list.filter(function (c) { return isCapsuleBroadcastEligible(c, { events: evs }); });\n for (var i = 0; i < eligible.length; i++) {\n var c = eligible[i];\n if (!c.schema_version) c.schema_version = SCHEMA_VERSION;\n if (!c.asset_id) { try { c.asset_id = computeAssetId(c); } catch (e) {} }\n }\n return eligible;\n}\n\nfunction parseA2AInput(text) {\n var raw = String(text || '').trim();\n if (!raw) return [];\n try {\n var maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) {\n return maybe.map(function (item) { return unwrapAssetFromMessage(item) || item; }).filter(Boolean);\n }\n if (maybe && typeof maybe === 'object') {\n var unwrapped = unwrapAssetFromMessage(maybe);\n return unwrapped ? [unwrapped] : [maybe];\n }\n } catch (e) {}\n var lines = raw.split('\\n').map(function (l) { return l.trim(); }).filter(Boolean);\n var items = [];\n for (var i = 0; i < lines.length; i++) {\n try {\n var obj = JSON.parse(lines[i]);\n var uw = unwrapAssetFromMessage(obj);\n items.push(uw || obj);\n } catch (e) { continue; }\n }\n return items;\n}\n\nfunction readTextIfExists(filePath) {\n try {\n if (!filePath) return '';\n if (!fs.existsSync(filePath)) return '';\n return fs.readFileSync(filePath, 'utf8');\n } catch { return ''; }\n}\n\nmodule.exports = {\n isAllowedA2AAsset, lowerConfidence, isBlastRadiusSafe,\n computeCapsuleSuccessStreak, isCapsuleBroadcastEligible,\n exportEligibleCapsules, parseA2AInput, readTextIfExists,\n};\n",
438 "inputSchema": {},
439 "outputSchema": null,
440 "icons": null,
441 "annotations": null,
442 "meta": null,
443 "execution": null
444 },
445 {
446 "name": "a2aProtocol.js",
447 "title": null,
448 "description": "Script: a2aProtocol.js. Code:\n// GEP A2A Protocol - Standard message types and pluggable transport layer.\n//\n// Protocol messages:\n// hello - capability advertisement and node discovery\n// publish - broadcast an eligible asset (Capsule/Gene)\n// fetch - request a specific asset by id or content hash\n// report - send a ValidationReport for a received asset\n// decision - accept/reject/quarantine decision on a received asset\n// revoke - withdraw a previously published asset\n//\n// Transport interface:\n// send(message, opts) - send a protocol message\n// receive(opts) - receive pending messages\n// list(opts) - list available message files/streams\n//\n// Default transport: FileTransport (reads/writes JSONL to a2a/ directory).\n\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst { getGepAssetsDir } = require('./paths');\nconst { computeAssetId } = require('./contentHash');\nconst { captureEnvFingerprint } = require('./envFingerprint');\n\nconst PROTOCOL_NAME = 'gep-a2a';\nconst PROTOCOL_VERSION = '1.0.0';\nconst VALID_MESSAGE_TYPES = ['hello', 'publish', 'fetch', 'report', 'decision', 'revoke'];\n\nfunction generateMessageId() {\n return 'msg_' + Date.now() + '_' + crypto.randomBytes(4).toString('hex');\n}\n\nfunction getNodeId() {\n if (process.env.A2A_NODE_ID) return String(process.env.A2A_NODE_ID);\n const raw = process.cwd() + '|' + (process.env.AGENT_NAME || 'default');\n return 'node_' + crypto.createHash('sha256').update(raw).digest('hex').slice(0, 12);\n}\n\n// --- Base message builder ---\n\nfunction buildMessage(params) {\n var messageType = params.messageType;\n var payload = params.payload;\n var senderId = params.senderId;\n if (!VALID_MESSAGE_TYPES.includes(messageType)) {\n throw new Error('Invalid message type: ' + messageType + '. Valid: ' + VALID_MESSAGE_TYPES.join(', '));\n }\n return {\n protocol: PROTOCOL_NAME,\n protocol_version: PROTOCOL_VERSION,\n message_type: messageType,\n message_id: generateMessageId(),\n sender_id: senderId || getNodeId(),\n timestamp: new Date().toISOString(),\n payload: payload || {},\n };\n}\n\n// --- Typed message builders ---\n\nfunction buildHello(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'hello',\n senderId: o.nodeId,\n payload: {\n capabilities: o.capabilities || {},\n gene_count: typeof o.geneCount === 'number' ? o.geneCount : null,\n capsule_count: typeof o.capsuleCount === 'number' ? o.capsuleCount : null,\n env_fingerprint: captureEnvFingerprint(),\n },\n });\n}\n\nfunction buildPublish(opts) {\n var o = opts || {};\n var asset = o.asset;\n if (!asset || !asset.type || !asset.id) {\n throw new Error('publish: asset must have type and id');\n }\n // Generate signature: HMAC-SHA256 of asset_id with node secret\n var assetIdVal = asset.asset_id || computeAssetId(asset);\n var nodeSecret = process.env.A2A_NODE_SECRET || getNodeId();\n var signature = crypto.createHmac('sha256', nodeSecret).update(assetIdVal).digest('hex');\n return buildMessage({\n messageType: 'publish',\n senderId: o.nodeId,\n payload: {\n asset_type: asset.type,\n asset_id: assetIdVal,\n local_id: asset.id,\n asset: asset,\n signature: signature,\n },\n });\n}\n\nfunction buildFetch(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'fetch',\n senderId: o.nodeId,\n payload: {\n asset_type: o.assetType || null,\n local_id: o.localId || null,\n content_hash: o.contentHash || null,\n },\n });\n}\n\nfunction buildReport(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'report',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n validation_report: o.validationReport || null,\n },\n });\n}\n\nfunction buildDecision(opts) {\n var o = opts || {};\n var validDecisions = ['accept', 'reject', 'quarantine'];\n if (!validDecisions.includes(o.decision)) {\n throw new Error('decision must be one of: ' + validDecisions.join(', '));\n }\n return buildMessage({\n messageType: 'decision',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n decision: o.decision,\n reason: o.reason || null,\n },\n });\n}\n\nfunction buildRevoke(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'revoke',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n reason: o.reason || null,\n },\n });\n}\n\n// --- Validation ---\n\nfunction isValidProtocolMessage(msg) {\n if (!msg || typeof msg !== 'object') return false;\n if (msg.protocol !== PROTOCOL_NAME) return false;\n if (!msg.message_type || !VALID_MESSAGE_TYPES.includes(msg.message_type)) return false;\n if (!msg.message_id || typeof msg.message_id !== 'string') return false;\n if (!msg.timestamp || typeof msg.timestamp !== 'string') return false;\n return true;\n}\n\n// Try to extract a raw asset from either a protocol message or a plain asset object.\n// This enables backward-compatible ingestion of both old-format and new-format payloads.\nfunction unwrapAssetFromMessage(input) {\n if (!input || typeof input !== 'object') return null;\n // If it is a protocol message with a publish payload, extract the asset.\n if (input.protocol === PROTOCOL_NAME && input.message_type === 'publish') {\n var p = input.payload;\n if (p && p.asset && typeof p.asset === 'object') return p.asset;\n return null;\n }\n // If it is a plain asset (Gene/Capsule/EvolutionEvent), return as-is.\n if (input.type === 'Gene' || input.type === 'Capsule' || input.type === 'EvolutionEvent') {\n return input;\n }\n return null;\n}\n\n// --- File Transport ---\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction defaultA2ADir() {\n return process.env.A2A_DIR || path.join(getGepAssetsDir(), 'a2a');\n}\n\nfunction fileTransportSend(message, opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'outbox');\n ensureDir(subdir);\n var filePath = path.join(subdir, message.message_type + '.jsonl');\n fs.appendFileSync(filePath, JSON.stringify(message) + '\\n', 'utf8');\n return { ok: true, path: filePath };\n}\n\nfunction fileTransportReceive(opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'inbox');\n if (!fs.existsSync(subdir)) return [];\n var files = fs.readdirSync(subdir).filter(function (f) { return f.endsWith('.jsonl'); });\n var messages = [];\n for (var fi = 0; fi < files.length; fi++) {\n try {\n var raw = fs.readFileSync(path.join(subdir, files[fi]), 'utf8');\n var lines = raw.split('\\n').map(function (l) { return l.trim(); }).filter(Boolean);\n for (var li = 0; li < lines.length; li++) {\n try {\n var msg = JSON.parse(lines[li]);\n if (msg && msg.protocol === PROTOCOL_NAME) messages.push(msg);\n } catch (e) {}\n }\n } catch (e) {}\n }\n return messages;\n}\n\nfunction fileTransportList(opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'outbox');\n if (!fs.existsSync(subdir)) return [];\n return fs.readdirSync(subdir).filter(function (f) { return f.endsWith('.jsonl'); });\n}\n\n// --- HTTP Transport (connects to evomap-hub) ---\n\nfunction httpTransportSend(message, opts) {\n var hubUrl = (opts && opts.hubUrl) || process.env.A2A_HUB_URL;\n if (!hubUrl) return { ok: false, error: 'A2A_HUB_URL not set' };\n var endpoint = hubUrl.replace(/\\/+$/, '') + '/a2a/' + message.message_type;\n var body = JSON.stringify(message);\n // Use dynamic import for fetch (available in Node 18+)\n return fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: body,\n })\n .then(function (res) { return res.json(); })\n .then(function (data) { return { ok: true, response: data }; })\n .catch(function (err) { return { ok: false, error: err.message }; });\n}\n\nfunction httpTransportReceive(opts) {\n var hubUrl = (opts && opts.hubUrl) || process.env.A2A_HUB_URL;\n if (!hubUrl) return Promise.resolve([]);\n var assetType = (opts && opts.assetType) || null;\n var fetchMsg = buildFetch({ assetType: assetType });\n var endpoint = hubUrl.replace(/\\/+$/, '') + '/a2a/fetch';\n return fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(fetchMsg),\n })\n .then(function (res) { return res.json(); })\n .then(function (data) {\n if (data && data.payload && Array.isArray(data.payload.results)) {\n return data.payload.results;\n }\n return [];\n })\n .catch(function () { return []; });\n}\n\nfunction httpTransportList() {\n return ['http'];\n}\n\n// --- Transport registry ---\n\nvar transports = {\n file: {\n send: fileTransportSend,\n receive: fileTransportReceive,\n list: fileTransportList,\n },\n http: {\n send: httpTransportSend,\n receive: httpTransportReceive,\n list: httpTransportList,\n },\n};\n\nfunction getTransport(name) {\n var n = String(name || process.env.A2A_TRANSPORT || 'file').toLowerCase();\n var t = transports[n];\n if (!t) throw new Error('Unknown A2A transport: ' + n + '. Available: ' + Object.keys(transports).join(', '));\n return t;\n}\n\nfunction registerTransport(name, impl) {\n if (!name || typeof name !== 'string') throw new Error('transport name required');\n if (!impl || typeof impl.send !== 'function' || typeof impl.receive !== 'function') {\n throw new Error('transport must implement send() and receive()');\n }\n transports[name] = impl;\n}\n\nmodule.exports = {\n PROTOCOL_NAME,\n PROTOCOL_VERSION,\n VALID_MESSAGE_TYPES,\n getNodeId,\n buildMessage,\n buildHello,\n buildPublish,\n buildFetch,\n buildReport,\n buildDecision,\n buildRevoke,\n isValidProtocolMessage,\n unwrapAssetFromMessage,\n getTransport,\n registerTransport,\n fileTransportSend,\n fileTransportReceive,\n fileTransportList,\n httpTransportSend,\n httpTransportReceive,\n httpTransportList,\n};\n",
449 "inputSchema": {},
450 "outputSchema": null,
451 "icons": null,
452 "annotations": null,
453 "meta": null,
454 "execution": null
455 },
456 {
457 "name": "bridge.js",
458 "title": null,
459 "description": "Script: bridge.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clip(text, maxChars) {\n const s = String(text || '');\n const n = Number(maxChars);\n if (!Number.isFinite(n) || n <= 0) return s;\n if (s.length <= n) return s;\n return s.slice(0, Math.max(0, n - 40)) + '\\n...[TRUNCATED]...\\n';\n}\n\nfunction writePromptArtifact({ memoryDir, cycleId, runId, prompt, meta }) {\n const dir = String(memoryDir || '').trim();\n if (!dir) throw new Error('bridge: missing memoryDir');\n ensureDir(dir);\n const safeCycle = String(cycleId || 'cycle').replace(/[^a-zA-Z0-9_\\-#]/g, '_');\n const safeRun = String(runId || Date.now()).replace(/[^a-zA-Z0-9_\\-]/g, '_');\n const base = `gep_prompt_${safeCycle}_${safeRun}`;\n const promptPath = path.join(dir, base + '.txt');\n const metaPath = path.join(dir, base + '.json');\n\n fs.writeFileSync(promptPath, String(prompt || ''), 'utf8');\n fs.writeFileSync(\n metaPath,\n JSON.stringify(\n {\n type: 'GepPromptArtifact',\n at: nowIso(),\n cycle_id: cycleId || null,\n run_id: runId || null,\n prompt_path: promptPath,\n meta: meta && typeof meta === 'object' ? meta : null,\n },\n null,\n 2\n ) + '\\n',\n 'utf8'\n );\n\n return { promptPath, metaPath };\n}\n\nfunction renderSessionsSpawnCall({ task, agentId, label, cleanup }) {\n const t = String(task || '').trim();\n if (!t) throw new Error('bridge: missing task');\n const a = String(agentId || 'main');\n const l = String(label || 'gep_bridge');\n const c = cleanup ? String(cleanup) : 'delete';\n\n // Output valid JSON so wrappers can parse with JSON.parse (not regex).\n // The wrapper uses lastIndexOf('sessions_spawn(') + JSON.parse to extract the task.\n const payload = JSON.stringify({ task: t, agentId: a, cleanup: c, label: l });\n return `sessions_spawn(${payload})`;\n}\n\nmodule.exports = {\n clip,\n writePromptArtifact,\n renderSessionsSpawnCall,\n};\n\n",
460 "inputSchema": {},
461 "outputSchema": null,
462 "icons": null,
463 "annotations": null,
464 "meta": null,
465 "execution": null
466 },
467 {
468 "name": "envFingerprint.js",
469 "title": null,
470 "description": "Script: envFingerprint.js. Code:\n// Environment fingerprint capture for GEP assets.\n// Records the runtime environment so that cross-environment diffusion\n// success rates (GDI) can be measured scientifically.\n\nconst os = require('os');\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst { getRepoRoot } = require('./paths');\n\n// Capture a structured environment fingerprint.\n// This is embedded into Capsules, EvolutionEvents, and ValidationReports.\nfunction captureEnvFingerprint() {\n const repoRoot = getRepoRoot();\n let pkgVersion = null;\n try {\n const raw = fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw);\n pkgVersion = pkg && pkg.version ? String(pkg.version) : null;\n } catch (e) {}\n\n return {\n node_version: process.version,\n platform: process.platform,\n arch: process.arch,\n os_release: os.release(),\n evolver_version: pkgVersion,\n cwd: process.cwd(),\n captured_at: new Date().toISOString(),\n };\n}\n\n// Compute a short fingerprint key for comparison and grouping.\n// Two nodes with the same key are considered \"same environment class\".\nfunction envFingerprintKey(fp) {\n if (!fp || typeof fp !== 'object') return 'unknown';\n const parts = [\n fp.node_version || '',\n fp.platform || '',\n fp.arch || '',\n fp.evolver_version || '',\n ].join('|');\n return crypto.createHash('sha256').update(parts, 'utf8').digest('hex').slice(0, 16);\n}\n\n// Check if two fingerprints are from the same environment class.\nfunction isSameEnvClass(fpA, fpB) {\n return envFingerprintKey(fpA) === envFingerprintKey(fpB);\n}\n\nmodule.exports = {\n captureEnvFingerprint,\n envFingerprintKey,\n isSameEnvClass,\n};\n",
471 "inputSchema": {},
472 "outputSchema": null,
473 "icons": null,
474 "annotations": null,
475 "meta": null,
476 "execution": null
477 },
478 {
479 "name": "prompt.js",
480 "title": null,
481 "description": "Script: prompt.js. Code:\nconst { captureEnvFingerprint } = require('./envFingerprint');\nconst { resolveStrategy } = require('./strategy');\n\nfunction buildGepPrompt({\n nowIso,\n context,\n signals,\n selector,\n parentEventId,\n selectedGene,\n capsuleCandidates,\n genesPreview,\n capsulesPreview,\n capabilityCandidatesPreview,\n externalCandidatesPreview,\n recentInnovationTargets,\n}) {\n const parentValue = parentEventId ? `\"${parentEventId}\"` : 'null';\n const selectedGeneId = selectedGene && selectedGene.id ? selectedGene.id : null;\n const capsuleIds = (capsuleCandidates || []).map(c => c && c.id).filter(Boolean);\n const envFingerprint = captureEnvFingerprint();\n const strategy = resolveStrategy();\n\n const basePrompt = `\nGEP \u2014 GENOME EVOLUTION PROTOCOL (v1.9.1 STRICT) [${nowIso}] | Strategy: ${strategy.label}\n\nYou are not a chat assistant.\nYou are not a free agent.\nYou are a protocol-bound evolution execution engine.\n\nAll actions must comply with this protocol.\nAny deviation is a failure even if the outcome appears correct.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nI. Protocol Positioning (Non-Negotiable)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nProtocol goals:\n- Convert reasoning into reusable, auditable, shareable evolution assets\n- Make evolution a standard process, not improvisation\n- Reduce future reasoning cost for similar problems\n\nProtocol compliance overrides local optimality.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nII. Mandatory Evolution Object Model (All Required)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nEvery evolution run must explicitly output the following five objects.\nMissing any one is an immediate failure.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n0 Mutation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit a Mutation object for every evolution run:\n\n\\`\\`\\`json\n{\n \"type\": \"Mutation\",\n \"id\": \"mut_<timestamp>\",\n \"category\": \"repair | optimize | innovate\",\n \"trigger_signals\": [\"<signal>\"],\n \"target\": \"<module | behavior | gene>\",\n \"expected_effect\": \"<effect>\",\n \"risk_level\": \"low | medium | high\"\n}\n\\`\\`\\`\n\nHard safety constraints:\n- Do NOT run high-risk mutation unless rigor >= 0.6 AND risk_tolerance <= 0.5\n- Do NOT combine innovation mutation with a high-risk personality state\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1 PersonalityState\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit a PersonalityState object for every evolution run:\n\n\\`\\`\\`json\n{\n \"type\": \"PersonalityState\",\n \"rigor\": 0.0-1.0,\n \"creativity\": 0.0-1.0,\n \"verbosity\": 0.0-1.0,\n \"risk_tolerance\": 0.0-1.0,\n \"obedience\": 0.0-1.0\n}\n\\`\\`\\`\n\nPersonality mutation (optional, small deltas only):\n\\`\\`\\`json\n{\n \"type\": \"PersonalityMutation\",\n \"param\": \"creativity\",\n \"delta\": 0.1,\n \"reason\": \"<reason>\"\n}\n\\`\\`\\`\nConstraints:\n- Each delta must be within [-0.2, +0.2]\n- Do not adjust more than 2 parameters in one run\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n2 EvolutionEvent\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit an EvolutionEvent with all fields present:\n\n\\`\\`\\`json\n{\n \"type\": \"EvolutionEvent\",\n \"id\": \"evt_<timestamp>\",\n \"parent\": ${parentValue},\n \"intent\": \"repair | optimize | innovate\",\n \"signals\": [\"<signal_1>\", \"<signal_2>\"],\n \"genes_used\": [\"<gene_id>\"],\n \"mutation_id\": \"<mut_id>\",\n \"personality_state\": { \"type\": \"PersonalityState\", \"...\": \"...\" },\n \"blast_radius\": {\n \"files\": <number>,\n \"lines\": <number>\n },\n \"outcome\": {\n \"status\": \"success | failed\",\n \"score\": <0.0-1.0>\n }\n}\n\\`\\`\\`\n\nEvolutionEvent is the only legal node type in the evolution tree.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n3 Gene\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nIf a Gene is used, you must reuse an existing Gene first.\nOnly create a new Gene when no match exists.\n\nGene must follow this schema:\n\n\\`\\`\\`json\n{\n \"type\": \"Gene\",\n \"id\": \"gene_<name>\",\n \"category\": \"repair | optimize | innovate\",\n \"signals_match\": [\"<pattern>\"],\n \"preconditions\": [\"<condition>\"],\n \"strategy\": [\n \"<step_1>\",\n \"<step_2>\"\n ],\n \"constraints\": {\n \"max_files\": <number>,\n \"forbidden_paths\": [\"<path>\"]\n },\n \"validation\": [\"<check_1>\", \"<check_2>\"]\n}\n\\`\\`\\`\n\nA Gene is an evolution interface definition, not code or generic advice.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n4 Capsule\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nOnly when evolution succeeds, you must generate a Capsule:\n\n\\`\\`\\`json\n{\n \"type\": \"Capsule\",\n \"id\": \"capsule_<timestamp>\",\n \"trigger\": [\"<signal>\"],\n \"gene\": \"<gene_id>\",\n \"summary\": \"<one sentence>\",\n \"confidence\": <0.0-1.0>\n}\n\\`\\`\\`\n\nCapsules exist to prevent repeated reasoning for similar problems.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIII. Standard Evolution Execution\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nFollow these steps in order:\n\n1 Signal Extraction\n- Extract structured signals from logs, errors, metrics, or patterns.\n- SKIP trivial/cosmetic signals (e.g. \"user_missing\", \"memory_missing\") unless no better signals exist.\n- PRIORITIZE: capability gaps, recurring manual tasks, performance bottlenecks, error patterns.\n\n2 Intent Decision (repair / optimize / innovate)\n- \"repair\": Fix a bug or error found in logs.\n- \"optimize\": Improve performance, reduce code, harden error handling.\n- \"innovate\": Create a NEW capability, tool, or skill. This is the highest-value intent.\n- If no urgent repair signals exist, default to \"innovate\".\n- If signals contain \"force_innovation_after_repair_loop\" or \"evolution_stagnation_detected\",\n you MUST use \"innovate\" intent. These signals mean the system is stuck in a repair loop.\n- If signals contain \"repair_loop_detected\", do NOT choose \"repair\" intent.\n\n3 Selection\n- Prefer existing Genes first, then Capsules.\n- For \"innovate\" intent: if no Gene fits, you MAY freely invent without creating a Gene first.\n\n4 Execution\n- For \"repair\" / \"optimize\": changes should be small and reversible.\n- For \"innovate\": you MAY create entire new skills (new directories, multiple files, 200+ lines).\n Innovation is NOT constrained by blast_radius limits.\n- Always estimate and record blast_radius in the EvolutionEvent.\n\n5 Validation\n- Execute Gene-declared validation steps if applicable.\n- On failure, rollback and record a failed EvolutionEvent.\n\n6 Knowledge Solidification\n- Update or add Gene if a new pattern is found.\n- Generate Capsule on success.\n- Append EvolutionEvent.\n- For \"innovate\" intent: Mutation + EvolutionEvent are sufficient. Gene/Capsule are optional.\n\n7 Report (Mandatory)\n- You MUST report what you did using the reporting mechanism specified in the execution context.\n- The report MUST describe: what changed, why, and how to use it (if applicable).\n- Reports like \"Step Complete\" or \"Signal Check\" with no details are protocol violations.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIV. Selector (Mandatory Decision Logic)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nWhen choosing a Gene or Capsule, you must emit a Selector decision.\n\nSelector must be explainable, for example:\n\n\\`\\`\\`json\n{\n \"selected\": \"${selectedGeneId || '<gene_id>'}\",\n \"reason\": [\n \"signals exact match\",\n \"historical success rate high\",\n \"low blast radius\"\n ],\n \"alternatives\": ${JSON.stringify(capsuleIds.length ? capsuleIds : ['<gene_id_2>'])}\n}\n\\`\\`\\`\n\nSelector is part of the protocol, not an implementation detail.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nV. Hard Failure Rules\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nThe following are protocol violations:\n\n- Missing Mutation or EvolutionEvent\n- Missing Report (Step 7)\n- Success without ANY tangible output (code, fix, or new capability)\n- Cycles that only produce protocol objects with no real-world change\n\nFailures are not errors; they are required negative samples. Record them.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVI. Evolution Tree Awareness\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n- Every EvolutionEvent must declare parent\n- Never overwrite or delete historical events\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVII. Evolution Philosophy\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n1. OBSERVE THE FULL PICTURE\n The session transcript shows what the main agent and user are doing.\n - Do NOT repeat or execute user requests. That is the main agent's job.\n - DO learn from patterns: what tasks recur? what fails often? what is manual?\n\n2. AUTOMATE RECURRING PATTERNS\n If something appears 3+ times in logs or has any reuse potential, automate it.\n Build a script, a skill, or a shortcut. Eliminate manual repetition.\n\n3. INTENT BALANCE (Strategy: ${strategy.label})\n Target allocation: ${Math.round(strategy.innovate * 100)}% innovate, ${Math.round(strategy.optimize * 100)}% optimize, ${Math.round(strategy.repair * 100)}% repair.\n ${strategy.innovate >= 0.5 ? 'A new working tool is worth more than a minor code cleanup.' : ''}\n ${strategy.repair >= 0.4 ? 'Prioritize fixing existing issues over building new things.' : ''}\n ${strategy.innovate >= 0.3 ? 'Each cycle SHOULD produce at least one of:\\n - A new executable skill or script\\n - A meaningful feature enhancement\\n - A creative automation or integration' : 'Focus on hardening and stabilizing the existing system.'}\n\n4. BUILD REAL THINGS\n Proposals, plans, and \"analysis\" are NOT evolution. Write code that runs.\n\n5. HARDEN THE SYSTEM (Robustness)\n When you see recurring errors (especially \"recurring_error\" or \"unsupported_input_type\" signals):\n - Diagnose the root cause from the error signature.\n - Implement a permanent fix (input validation, format conversion, graceful fallback).\n - Document the fix in the skill's README or create/update TROUBLESHOOTING.md.\n - Example: if GIF images crash the LLM, add a GIF-to-PNG converter or filter GIFs before sending.\n The system should NEVER crash repeatedly on the same error. Fix it once, forever.\n\n6. KNOWN ISSUES (DO NOT ATTEMPT TO FIX -- already handled externally)\n The following errors appear in logs but have been fixed or are managed outside the evolver:\n - \"230001: invalid message content\" -- Feishu messaging API content limit. Fixed in feishu-post/send.js (truncation + sanitization).\n - \"HTTP 400\" from feishu_doc_append/feishu_doc_write -- Block validation edge cases. Fixed in feishu-doc/input_guard.js.\n - \"gateway timeout after 630000ms\" -- Transient gateway slowness, auto-fallback to embedded mode.\n - \"ENOENT\" / \"spawn openclaw\" -- PATH resolution issue, fixed in wrapper with explicit binary search.\n If you see these errors in logs, SKIP THEM. Focus on NEW errors or genuinely unresolved issues.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVIII. A2A Evolution Exchange (Optional)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nA2A payload types: Gene, Capsule, EvolutionEvent.\nExternal payloads must be staged as candidates first, validated before promotion.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIX. Protected Files (NEVER delete or overwrite)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nThe following files are CRITICAL to system identity and operation.\nDeleting, overwriting, or emptying ANY of them is an IMMEDIATE PROTOCOL VIOLATION.\n\n- MEMORY.md\n- SOUL.md\n- IDENTITY.md\n- AGENTS.md\n- USER.md\n- HEARTBEAT.md\n- RECENT_EVENTS.md\n- TOOLS.md\n- TROUBLESHOOTING.md\n- openclaw.json\n- .env\n- memory/persona_*.md\n- memory/personas/**\n\nEvolver core source files (DO NOT modify -- managed by deploy pipeline):\n- skills/evolver/src/evolve.js\n- skills/evolver/src/gep/prompt.js\n- skills/evolver/src/gep/signals.js\n- skills/evolver/src/gep/solidify.js\n- skills/evolver/src/gep/selector.js\n- skills/evolver/src/gep/mutation.js\n- skills/evolver/src/gep/personality.js\n- skills/evolver/src/gep/memoryGraph.js\n- skills/evolver/src/gep/paths.js\n- skills/evolver/src/gep/bridge.js\n- skills/evolver/index.js\n- skills/evolver/package.json\n\nYou MAY append to or edit sections within identity/memory files listed above.\nYou MUST NOT delete them, truncate them to empty, or replace their entire content.\nYou MUST NOT modify evolver core source files -- they are deployed from a versioned repo.\nIf you need to reorganize a protected file, create a new version alongside it first.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nX. Forbidden Innovation Zones (DO NOT CREATE)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nDO NOT create skills or scripts that duplicate existing infrastructure:\n\n- Process lifecycle management (start/stop/restart/watchdog/daemon/cron)\n Already provided by src/ops/lifecycle.js and the wrapper's --loop mode.\n- Skill health monitoring or auditing\n Already provided by src/ops/skills_monitor.js.\n- Evolver self-management (PID locks, singleton guards, loop schedulers)\n Already built into index.js and src/ops/.\n- Crontab or systemd installers\n System-level scheduling is managed by the operator, not the evolver.\n\nCreating duplicates of the above is a protocol violation.\n\nInstead, focus innovation on:\n- NEW capabilities the system does not have (tools, integrations, automations)\n- Enhancements to EXISTING user-facing skills\n- Automating recurring manual tasks observed in session logs\n\nFinal Directive\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nYou are an evolution engine. Every cycle must leave the system measurably better.\nProtocol compliance matters, but tangible output matters more.\n\nContext [Innovation Cooldown]:\n${(() => {\n var targets = recentInnovationTargets || {};\n var keys = Object.keys(targets);\n if (keys.length === 0) return '(none -- all targets available)';\n return 'The following targets were innovated on in the last 10 cycles. Do NOT choose them again unless no other option exists:\\n' +\n keys.map(function(k) { return '- ' + k + ' (' + targets[k] + 'x)'; }).join('\\n');\n})()}\n\nContext [Signals]:\n${JSON.stringify(signals)}\n\nContext [Selector]:\n${JSON.stringify(selector, null, 2)}\n\nContext [Gene Preview]:\n${genesPreview}\n\nContext [Capsule Preview]:\n${capsulesPreview}\n\nContext [Capability Candidates] (Five questions shape; keep it short):\n${capabilityCandidatesPreview || '(none)'}\n\nContext [External Candidates] (A2A staged; do not execute directly):\n${externalCandidatesPreview || '(none)'}\n\nContext [Env Fingerprint]:\n${JSON.stringify(envFingerprint, null, 2)}\n\nContext [Execution]:\n${context}\n`.trim();\n\n const maxChars = Number.isFinite(Number(process.env.GEP_PROMPT_MAX_CHARS))\n ? Number(process.env.GEP_PROMPT_MAX_CHARS)\n : 30000;\n\n if (basePrompt.length <= maxChars) return basePrompt;\n\n // Budget strategy: keep the protocol and structured assets, shrink execution context first.\n const headKeep = Math.min(basePrompt.length, Math.floor(maxChars * 0.75));\n const tailKeep = Math.max(0, maxChars - headKeep - 120);\n const head = basePrompt.slice(0, headKeep);\n const tail = tailKeep > 0 ? basePrompt.slice(basePrompt.length - tailKeep) : '';\n return `${head}\\n\\n...[PROMPT TRUNCATED FOR BUDGET]...\\n\\n${tail}`.slice(0, maxChars);\n}\n\nmodule.exports = { buildGepPrompt };\n\n",
482 "inputSchema": {},
483 "outputSchema": null,
484 "icons": null,
485 "annotations": null,
486 "meta": null,
487 "execution": null
488 },
489 {
490 "name": "strategy.js",
491 "title": null,
492 "description": "Script: strategy.js. Code:\n// Evolution Strategy Presets (v1.0)\n// Controls the balance between repair, optimize, and innovate intents.\n//\n// Usage: set EVOLVE_STRATEGY env var to one of: balanced, innovate, harden, repair-only\n// Default: balanced\n//\n// Each strategy defines:\n// repair/optimize/innovate - target allocation ratios (inform the LLM prompt)\n// repairLoopThreshold - repair ratio in last 8 cycles that triggers forced innovation\n// label - human-readable name injected into the GEP prompt\n\nvar STRATEGIES = {\n 'balanced': {\n repair: 0.20,\n optimize: 0.30,\n innovate: 0.50,\n repairLoopThreshold: 0.50,\n label: 'Balanced',\n description: 'Normal operation. Steady growth with stability.',\n },\n 'innovate': {\n repair: 0.05,\n optimize: 0.15,\n innovate: 0.80,\n repairLoopThreshold: 0.30,\n label: 'Innovation Focus',\n description: 'System is stable. Maximize new features and capabilities.',\n },\n 'harden': {\n repair: 0.40,\n optimize: 0.40,\n innovate: 0.20,\n repairLoopThreshold: 0.70,\n label: 'Hardening',\n description: 'After a big change. Focus on stability and robustness.',\n },\n 'repair-only': {\n repair: 0.80,\n optimize: 0.20,\n innovate: 0.00,\n repairLoopThreshold: 1.00,\n label: 'Repair Only',\n description: 'Emergency. Fix everything before doing anything else.',\n },\n};\n\nfunction resolveStrategy() {\n var name = String(process.env.EVOLVE_STRATEGY || 'balanced').toLowerCase().trim();\n // Backward compatibility: FORCE_INNOVATION=true maps to 'innovate'\n if (!process.env.EVOLVE_STRATEGY) {\n var fi = String(process.env.FORCE_INNOVATION || process.env.EVOLVE_FORCE_INNOVATION || '').toLowerCase();\n if (fi === 'true') name = 'innovate';\n }\n var strategy = STRATEGIES[name] || STRATEGIES['balanced'];\n strategy.name = name;\n return strategy;\n}\n\nfunction getStrategyNames() {\n return Object.keys(STRATEGIES);\n}\n\nmodule.exports = { resolveStrategy, getStrategyNames, STRATEGIES };\n",
493 "inputSchema": {},
494 "outputSchema": null,
495 "icons": null,
496 "annotations": null,
497 "meta": null,
498 "execution": null
499 },
500 {
501 "name": "selector.js",
502 "title": null,
503 "description": "Script: selector.js. Code:\nfunction matchPatternToSignals(pattern, signals) {\n if (!pattern || !signals || signals.length === 0) return false;\n const p = String(pattern);\n const sig = signals.map(s => String(s));\n\n const regexLike = p.length >= 2 && p.startsWith('/') && p.lastIndexOf('/') > 0;\n if (regexLike) {\n const lastSlash = p.lastIndexOf('/');\n const body = p.slice(1, lastSlash);\n const flags = p.slice(lastSlash + 1);\n try {\n const re = new RegExp(body, flags || 'i');\n return sig.some(s => re.test(s));\n } catch (e) {\n // fallback to substring\n }\n }\n\n const needle = p.toLowerCase();\n return sig.some(s => s.toLowerCase().includes(needle));\n}\n\nfunction scoreGene(gene, signals) {\n if (!gene || gene.type !== 'Gene') return 0;\n const patterns = Array.isArray(gene.signals_match) ? gene.signals_match : [];\n if (patterns.length === 0) return 0;\n let score = 0;\n for (const pat of patterns) {\n if (matchPatternToSignals(pat, signals)) score += 1;\n }\n return score;\n}\n\nfunction selectGene(genes, signals, opts) {\n const bannedGeneIds = opts && opts.bannedGeneIds ? opts.bannedGeneIds : new Set();\n const driftEnabled = !!(opts && opts.driftEnabled);\n const preferredGeneId = opts && typeof opts.preferredGeneId === 'string' ? opts.preferredGeneId : null;\n\n const scored = genes\n .map(g => ({ gene: g, score: scoreGene(g, signals) }))\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score);\n\n if (scored.length === 0) return { selected: null, alternatives: [] };\n\n // Memory graph preference: only override when the preferred gene is already a match candidate.\n if (preferredGeneId) {\n const preferred = scored.find(x => x.gene && x.gene.id === preferredGeneId);\n if (preferred && (driftEnabled || !bannedGeneIds.has(preferredGeneId))) {\n const rest = scored.filter(x => x.gene && x.gene.id !== preferredGeneId);\n const filteredRest = driftEnabled ? rest : rest.filter(x => x.gene && !bannedGeneIds.has(x.gene.id));\n return {\n selected: preferred.gene,\n alternatives: filteredRest.slice(0, 4).map(x => x.gene),\n };\n }\n }\n\n // Low-efficiency suppression: do not repeat low-confidence paths unless drift is explicit.\n const filtered = driftEnabled ? scored : scored.filter(x => x.gene && !bannedGeneIds.has(x.gene.id));\n if (filtered.length === 0) return { selected: null, alternatives: scored.slice(0, 4).map(x => x.gene) };\n\n return {\n selected: filtered[0].gene,\n alternatives: filtered.slice(1, 4).map(x => x.gene),\n };\n}\n\nfunction selectCapsule(capsules, signals) {\n const scored = (capsules || [])\n .map(c => {\n const triggers = Array.isArray(c.trigger) ? c.trigger : [];\n const score = triggers.reduce((acc, t) => (matchPatternToSignals(t, signals) ? acc + 1 : acc), 0);\n return { capsule: c, score };\n })\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score);\n return scored.length ? scored[0].capsule : null;\n}\n\nfunction selectGeneAndCapsule({ genes, capsules, signals, memoryAdvice, driftEnabled }) {\n const bannedGeneIds =\n memoryAdvice && memoryAdvice.bannedGeneIds instanceof Set ? memoryAdvice.bannedGeneIds : new Set();\n const preferredGeneId = memoryAdvice && memoryAdvice.preferredGeneId ? memoryAdvice.preferredGeneId : null;\n\n const { selected, alternatives } = selectGene(genes, signals, {\n bannedGeneIds,\n preferredGeneId,\n driftEnabled: !!driftEnabled,\n });\n const capsule = selectCapsule(capsules, signals);\n const selector = buildSelectorDecision({\n gene: selected,\n capsule,\n signals,\n alternatives,\n memoryAdvice,\n driftEnabled,\n });\n return {\n selectedGene: selected,\n capsuleCandidates: capsule ? [capsule] : [],\n selector,\n };\n}\n\nfunction buildSelectorDecision({ gene, capsule, signals, alternatives, memoryAdvice, driftEnabled }) {\n const reason = [];\n if (gene) reason.push('signals match gene.signals_match');\n if (capsule) reason.push('capsule trigger matches signals');\n if (!gene) reason.push('no matching gene found; new gene may be required');\n if (signals && signals.length) reason.push(`signals: ${signals.join(', ')}`);\n\n if (memoryAdvice && Array.isArray(memoryAdvice.explanation) && memoryAdvice.explanation.length) {\n reason.push(`memory_graph: ${memoryAdvice.explanation.join(' | ')}`);\n }\n if (driftEnabled) {\n reason.push('random_drift_override: true');\n }\n\n return {\n selected: gene ? gene.id : null,\n reason,\n alternatives: Array.isArray(alternatives) ? alternatives.map(g => g.id) : [],\n };\n}\n\nmodule.exports = {\n selectGeneAndCapsule,\n selectGene,\n selectCapsule,\n buildSelectorDecision,\n};\n\n",
504 "inputSchema": {},
505 "outputSchema": null,
506 "icons": null,
507 "annotations": null,
508 "meta": null,
509 "execution": null
510 },
511 {
512 "name": "signals.js",
513 "title": null,
514 "description": "Script: signals.js. Code:\nvar { resolveStrategy } = require('./strategy');\n\n// Opportunity signal names (shared with mutation.js and personality.js).\nvar OPPORTUNITY_SIGNALS = [\n 'user_feature_request',\n 'user_improvement_suggestion',\n 'perf_bottleneck',\n 'capability_gap',\n 'stable_success_plateau',\n 'external_opportunity',\n 'recurring_error',\n 'unsupported_input_type',\n 'evolution_stagnation_detected',\n 'repair_loop_detected',\n 'force_innovation_after_repair_loop',\n];\n\nfunction hasOpportunitySignal(signals) {\n var list = Array.isArray(signals) ? signals : [];\n for (var i = 0; i < OPPORTUNITY_SIGNALS.length; i++) {\n if (list.includes(OPPORTUNITY_SIGNALS[i])) return true;\n }\n return false;\n}\n\n// Build a de-duplication set from recent evolution events.\n// Returns an object: { suppressedSignals: Set<string>, recentIntents: string[], consecutiveRepairCount: number }\nfunction analyzeRecentHistory(recentEvents) {\n if (!Array.isArray(recentEvents) || recentEvents.length === 0) {\n return { suppressedSignals: new Set(), recentIntents: [], consecutiveRepairCount: 0 };\n }\n // Take only the last 10 events\n var recent = recentEvents.slice(-10);\n\n // Count consecutive same-intent runs at the tail\n var consecutiveRepairCount = 0;\n for (var i = recent.length - 1; i >= 0; i--) {\n if (recent[i].intent === 'repair') {\n consecutiveRepairCount++;\n } else {\n break;\n }\n }\n\n // Count signal frequency in last 8 events: signal -> count\n var signalFreq = {};\n var geneFreq = {};\n var tail = recent.slice(-8);\n for (var j = 0; j < tail.length; j++) {\n var evt = tail[j];\n var sigs = Array.isArray(evt.signals) ? evt.signals : [];\n for (var k = 0; k < sigs.length; k++) {\n var s = String(sigs[k]);\n // Normalize: ignore errsig details for frequency counting\n var key = s.startsWith('errsig:') ? 'errsig' : s.startsWith('recurring_errsig') ? 'recurring_errsig' : s;\n signalFreq[key] = (signalFreq[key] || 0) + 1;\n }\n var genes = Array.isArray(evt.genes_used) ? evt.genes_used : [];\n for (var g = 0; g < genes.length; g++) {\n geneFreq[String(genes[g])] = (geneFreq[String(genes[g])] || 0) + 1;\n }\n }\n\n // Suppress signals that appeared in 3+ of the last 8 events (they are being over-processed)\n var suppressedSignals = new Set();\n var entries = Object.entries(signalFreq);\n for (var ei = 0; ei < entries.length; ei++) {\n if (entries[ei][1] >= 3) {\n suppressedSignals.add(entries[ei][0]);\n }\n }\n\n var recentIntents = recent.map(function(e) { return e.intent || 'unknown'; });\n\n // Track recent innovation targets to prevent repeated work on the same skill/module\n var recentInnovationTargets = {};\n for (var ti = 0; ti < recent.length; ti++) {\n var tevt = recent[ti];\n if (tevt.intent === 'innovate' && tevt.mutation_id) {\n var tgt = (tevt.mutation && tevt.mutation.target) || '';\n if (!tgt) {\n var sum = String(tevt.summary || tevt.capsule_summary || '');\n var skillMatch = sum.match(/skills\\/([a-zA-Z0-9_-]+)/);\n if (skillMatch) tgt = 'skills/' + skillMatch[1];\n }\n if (tgt) {\n recentInnovationTargets[tgt] = (recentInnovationTargets[tgt] || 0) + 1;\n }\n }\n }\n\n return { suppressedSignals: suppressedSignals, recentIntents: recentIntents, consecutiveRepairCount: consecutiveRepairCount, signalFreq: signalFreq, geneFreq: geneFreq, recentInnovationTargets: recentInnovationTargets };\n}\n\nfunction extractSignals({ recentSessionTranscript, todayLog, memorySnippet, userSnippet, recentEvents }) {\n var signals = [];\n var corpus = [\n String(recentSessionTranscript || ''),\n String(todayLog || ''),\n String(memorySnippet || ''),\n String(userSnippet || ''),\n ].join('\\n');\n var lower = corpus.toLowerCase();\n\n // Analyze recent evolution history for de-duplication\n var history = analyzeRecentHistory(recentEvents || []);\n\n // --- Defensive signals (errors, missing resources) ---\n\n var errorHit = /\\[error|error:|exception|fail|failed|iserror\":true/.test(lower);\n if (errorHit) signals.push('log_error');\n\n // Error signature (more reproducible than a coarse \"log_error\" tag).\n try {\n var lines = corpus\n .split('\\n')\n .map(function (l) { return String(l || '').trim(); })\n .filter(Boolean);\n\n var errLine =\n lines.find(function (l) { return /\\b(typeerror|referenceerror|syntaxerror)\\b\\s*:|error\\s*:|exception\\s*:|\\[error/i.test(l); }) ||\n null;\n\n if (errLine) {\n var clipped = errLine.replace(/\\s+/g, ' ').slice(0, 260);\n signals.push('errsig:' + clipped);\n }\n } catch (e) {}\n\n if (lower.includes('memory.md missing')) signals.push('memory_missing');\n if (lower.includes('user.md missing')) signals.push('user_missing');\n if (lower.includes('key missing')) signals.push('integration_key_missing');\n if (lower.includes('no session logs found') || lower.includes('no jsonl files')) signals.push('session_logs_missing');\n if (lower.includes('pgrep') || lower.includes('ps aux')) signals.push('windows_shell_incompatible');\n if (lower.includes('path.resolve(__dirname, \\'../../')) signals.push('path_outside_workspace');\n\n // Protocol-specific drift signals\n if (lower.includes('prompt') && !lower.includes('evolutionevent')) signals.push('protocol_drift');\n\n // --- Recurring error detection (robustness signals) ---\n // Count repeated identical errors -- these indicate systemic issues that need automated fixes\n try {\n var errorCounts = {};\n var errPatterns = corpus.match(/(?:LLM error|\"error\"|\"status\":\\s*\"error\")[^}]{0,200}/gi) || [];\n for (var ep = 0; ep < errPatterns.length; ep++) {\n // Normalize to a short key\n var key = errPatterns[ep].replace(/\\s+/g, ' ').slice(0, 100);\n errorCounts[key] = (errorCounts[key] || 0) + 1;\n }\n var recurringErrors = Object.entries(errorCounts).filter(function (e) { return e[1] >= 3; });\n if (recurringErrors.length > 0) {\n signals.push('recurring_error');\n // Include the top recurring error signature for the agent to diagnose\n var topErr = recurringErrors.sort(function (a, b) { return b[1] - a[1]; })[0];\n signals.push('recurring_errsig(' + topErr[1] + 'x):' + topErr[0].slice(0, 150));\n }\n } catch (e) {}\n\n // --- Unsupported input type (e.g. GIF, video formats the LLM can't handle) ---\n if (/unsupported mime|unsupported.*type|invalid.*mime/i.test(lower)) {\n signals.push('unsupported_input_type');\n }\n\n // --- Opportunity signals (innovation / feature requests) ---\n\n // user_feature_request: user explicitly asks for a new capability\n // Look for action verbs + object patterns that indicate a feature request\n if (/\\b(add|implement|create|build|make|develop|write|design)\\b[^.?!\\n]{3,60}\\b(feature|function|module|capability|tool|support|endpoint|command|option|mode)\\b/i.test(corpus)) {\n signals.push('user_feature_request');\n }\n // Also catch direct \"I want/need X\" patterns\n if (/\\b(i want|i need|we need|please add|can you add|could you add|let'?s add)\\b/i.test(lower)) {\n signals.push('user_feature_request');\n }\n\n // user_improvement_suggestion: user suggests making something better\n if (/\\b(should be|could be better|improve|enhance|upgrade|refactor|clean up|simplify|streamline)\\b/i.test(lower)) {\n // Only fire if there is no active error (to distinguish from repair requests)\n if (!errorHit) signals.push('user_improvement_suggestion');\n }\n\n // perf_bottleneck: performance issues detected\n if (/\\b(slow|timeout|timed?\\s*out|latency|bottleneck|took too long|performance issue|high cpu|high memory|oom|out of memory)\\b/i.test(lower)) {\n signals.push('perf_bottleneck');\n }\n\n // capability_gap: something is explicitly unsupported or missing\n if (/\\b(not supported|cannot|doesn'?t support|no way to|missing feature|unsupported|not available|not implemented|no support for)\\b/i.test(lower)) {\n // Only fire if it is not just a missing file/config signal\n if (!signals.includes('memory_missing') && !signals.includes('user_missing') && !signals.includes('session_logs_missing')) {\n signals.push('capability_gap');\n }\n }\n\n // --- Tool Usage Analytics (auto-evolved) ---\n // Detect high-frequency tool usage patterns that suggest automation opportunities\n var toolUsage = {};\n var toolMatches = corpus.match(/\\[TOOL:\\s*(\\w+)\\]/g) || [];\n for (var ti = 0; ti < toolMatches.length; ti++) {\n var toolName = toolMatches[ti].match(/\\[TOOL:\\s*(\\w+)\\]/)[1];\n toolUsage[toolName] = (toolUsage[toolName] || 0) + 1;\n }\n Object.keys(toolUsage).forEach(function(tool) {\n if (toolUsage[tool] >= 5) {\n signals.push('high_tool_usage:' + tool);\n }\n if (tool === 'exec' && toolUsage[tool] >= 3) {\n signals.push('repeated_tool_usage:exec');\n }\n });\n\n // --- Signal prioritization ---\n // Remove cosmetic signals when actionable signals exist\n var actionable = signals.filter(function (s) {\n return s !== 'user_missing' && s !== 'memory_missing' && s !== 'session_logs_missing' && s !== 'windows_shell_incompatible';\n });\n // If we have actionable signals, drop the cosmetic ones\n if (actionable.length > 0) {\n signals = actionable;\n }\n\n // --- De-duplication: suppress signals that have been over-processed ---\n if (history.suppressedSignals.size > 0) {\n var beforeDedup = signals.length;\n signals = signals.filter(function (s) {\n // Normalize signal key for comparison\n var key = s.startsWith('errsig:') ? 'errsig' : s.startsWith('recurring_errsig') ? 'recurring_errsig' : s;\n return !history.suppressedSignals.has(key);\n });\n if (beforeDedup > 0 && signals.length === 0) {\n // All signals were suppressed = system is stable but stuck in a loop\n // Force innovation\n signals.push('evolution_stagnation_detected');\n signals.push('stable_success_plateau');\n }\n }\n\n // --- Force innovation when repair-heavy (ratio or consecutive) ---\n // Threshold is strategy-aware: \"innovate\" mode triggers sooner, \"harden\" mode allows more repairs\n var strategy = resolveStrategy();\n var repairRatio = 0;\n if (history.recentIntents && history.recentIntents.length > 0) {\n var repairCount = history.recentIntents.filter(function(i) { return i === 'repair'; }).length;\n repairRatio = repairCount / history.recentIntents.length;\n }\n var shouldForceInnovation = strategy.name === 'repair-only' ? false :\n (history.consecutiveRepairCount >= 3 || repairRatio >= strategy.repairLoopThreshold);\n if (shouldForceInnovation) {\n // Remove repair-only signals (log_error, errsig) and inject innovation signals\n signals = signals.filter(function (s) {\n return s !== 'log_error' && !s.startsWith('errsig:') && !s.startsWith('recurring_errsig');\n });\n if (signals.length === 0) {\n signals.push('repair_loop_detected');\n signals.push('stable_success_plateau');\n }\n // Append a directive signal that the prompt can pick up\n signals.push('force_innovation_after_repair_loop');\n }\n\n // If no signals at all, add a default innovation signal\n if (signals.length === 0) {\n signals.push('stable_success_plateau');\n }\n\n return Array.from(new Set(signals));\n}\n\nmodule.exports = { extractSignals, hasOpportunitySignal, analyzeRecentHistory, OPPORTUNITY_SIGNALS };\n",
515 "inputSchema": {},
516 "outputSchema": null,
517 "icons": null,
518 "annotations": null,
519 "meta": null,
520 "execution": null
521 },
522 {
523 "name": "memoryGraph.js",
524 "title": null,
525 "description": "Script: memoryGraph.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getMemoryDir } = require('./paths');\nconst { normalizePersonalityState, isValidPersonalityState, personalityKey } = require('./personality');\nconst { isValidMutation, normalizeMutation } = require('./mutation');\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction stableHash(input) {\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction normalizeErrorSignature(text) {\n const s = String(text || '').trim();\n if (!s) return null;\n return (\n s\n .toLowerCase()\n // normalize Windows paths\n .replace(/[a-z]:\\\\[^ \\n\\r\\t]+/gi, '<path>')\n // normalize Unix paths\n .replace(/\\/[^ \\n\\r\\t]+/g, '<path>')\n // normalize hex and numbers\n .replace(/\\b0x[0-9a-f]+\\b/gi, '<hex>')\n .replace(/\\b\\d+\\b/g, '<n>')\n // normalize whitespace\n .replace(/\\s+/g, ' ')\n .slice(0, 220)\n );\n}\n\nfunction normalizeSignalsForMatching(signals) {\n const list = Array.isArray(signals) ? signals : [];\n const out = [];\n for (const s of list) {\n const str = String(s || '').trim();\n if (!str) continue;\n if (str.startsWith('errsig:')) {\n const norm = normalizeErrorSignature(str.slice('errsig:'.length));\n if (norm) out.push(`errsig_norm:${stableHash(norm)}`);\n continue;\n }\n out.push(str);\n }\n return out;\n}\n\nfunction computeSignalKey(signals) {\n // Key must be stable across runs; normalize noisy signatures (paths, numbers).\n const list = normalizeSignalsForMatching(signals);\n const uniq = Array.from(new Set(list.filter(Boolean))).sort();\n return uniq.join('|') || '(none)';\n}\n\nfunction extractErrorSignatureFromSignals(signals) {\n // Convention: signals can include \"errsig:<raw>\" emitted by signals extractor.\n const list = Array.isArray(signals) ? signals : [];\n for (const s of list) {\n const str = String(s || '');\n if (str.startsWith('errsig:')) return normalizeErrorSignature(str.slice('errsig:'.length));\n }\n return null;\n}\n\nfunction memoryGraphPath() {\n const { getEvolutionDir } = require('./paths');\n const evoDir = getEvolutionDir();\n return process.env.MEMORY_GRAPH_PATH || path.join(evoDir, 'memory_graph.jsonl');\n}\n\nfunction memoryGraphStatePath() {\n const { getEvolutionDir } = require('./paths');\n return path.join(getEvolutionDir(), 'memory_graph_state.json');\n}\n\nfunction appendJsonl(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n fs.appendFileSync(filePath, JSON.stringify(obj) + '\\n', 'utf8');\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch (e) {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction tryReadMemoryGraphEvents(limitLines = 2000) {\n try {\n const p = memoryGraphPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n const recent = lines.slice(Math.max(0, lines.length - limitLines));\n return recent\n .map(l => {\n try {\n return JSON.parse(l);\n } catch (e) {\n return null;\n }\n })\n .filter(Boolean);\n } catch (e) {\n return [];\n }\n}\n\nfunction jaccard(aList, bList) {\n const aNorm = normalizeSignalsForMatching(aList);\n const bNorm = normalizeSignalsForMatching(bList);\n const a = new Set((Array.isArray(aNorm) ? aNorm : []).map(String));\n const b = new Set((Array.isArray(bNorm) ? bNorm : []).map(String));\n if (a.size === 0 && b.size === 0) return 1;\n if (a.size === 0 || b.size === 0) return 0;\n let inter = 0;\n for (const x of a) if (b.has(x)) inter++;\n const union = a.size + b.size - inter;\n return union === 0 ? 0 : inter / union;\n}\n\nfunction decayWeight(updatedAtIso, halfLifeDays) {\n const hl = Number(halfLifeDays);\n if (!Number.isFinite(hl) || hl <= 0) return 1;\n const t = Date.parse(updatedAtIso);\n if (!Number.isFinite(t)) return 1;\n const ageDays = (Date.now() - t) / (1000 * 60 * 60 * 24);\n if (!Number.isFinite(ageDays) || ageDays <= 0) return 1;\n // Exponential half-life decay: weight = 0.5^(age/hl)\n return Math.pow(0.5, ageDays / hl);\n}\n\nfunction aggregateEdges(events) {\n // Aggregate by (signal_key, gene_id) from outcome events.\n // Laplace smoothing to avoid 0/1 extremes.\n const map = new Map();\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n if (ev.kind !== 'outcome') continue;\n const signalKey = ev.signal && ev.signal.key ? String(ev.signal.key) : '(none)';\n const geneId = ev.gene && ev.gene.id ? String(ev.gene.id) : null;\n if (!geneId) continue;\n\n const k = `${signalKey}::${geneId}`;\n const cur = map.get(k) || { signalKey, geneId, success: 0, fail: 0, last_ts: null, last_score: null };\n const status = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (status === 'success') cur.success += 1;\n else if (status === 'failed') cur.fail += 1;\n\n const ts = ev.ts || ev.created_at || ev.at;\n if (ts && (!cur.last_ts || Date.parse(ts) > Date.parse(cur.last_ts))) {\n cur.last_ts = ts;\n cur.last_score =\n ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? Number(ev.outcome.score) : cur.last_score;\n }\n map.set(k, cur);\n }\n return map;\n}\n\nfunction aggregateGeneOutcomes(events) {\n // Aggregate by gene_id from outcome events (gene -> outcome success probability).\n const map = new Map();\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n if (ev.kind !== 'outcome') continue;\n const geneId = ev.gene && ev.gene.id ? String(ev.gene.id) : null;\n if (!geneId) continue;\n const cur = map.get(geneId) || { geneId, success: 0, fail: 0, last_ts: null, last_score: null };\n const status = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (status === 'success') cur.success += 1;\n else if (status === 'failed') cur.fail += 1;\n const ts = ev.ts || ev.created_at || ev.at;\n if (ts && (!cur.last_ts || Date.parse(ts) > Date.parse(cur.last_ts))) {\n cur.last_ts = ts;\n cur.last_score =\n ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? Number(ev.outcome.score) : cur.last_score;\n }\n map.set(geneId, cur);\n }\n return map;\n}\n\nfunction edgeExpectedSuccess(edge, opts) {\n const e = edge || { success: 0, fail: 0, last_ts: null };\n const succ = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = succ + fail;\n const p = (succ + 1) / (total + 2); // Laplace smoothing\n const halfLifeDays = opts && Number.isFinite(Number(opts.half_life_days)) ? Number(opts.half_life_days) : 30;\n const w = decayWeight(e.last_ts || '', halfLifeDays);\n return { p, w, total, value: p * w };\n}\n\nfunction getMemoryAdvice({ signals, genes, driftEnabled }) {\n const events = tryReadMemoryGraphEvents(2000);\n const edges = aggregateEdges(events);\n const geneOutcomes = aggregateGeneOutcomes(events);\n const curSignals = Array.isArray(signals) ? signals : [];\n const curKey = computeSignalKey(curSignals);\n\n const bannedGeneIds = new Set();\n const scoredGeneIds = [];\n\n // Similarity: consider exact key first, then any key with overlap.\n const seenKeys = new Set();\n const candidateKeys = [];\n candidateKeys.push({ key: curKey, sim: 1 });\n seenKeys.add(curKey);\n\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n const k = ev.signal && ev.signal.key ? String(ev.signal.key) : '(none)';\n if (seenKeys.has(k)) continue;\n const sigs = ev.signal && Array.isArray(ev.signal.signals) ? ev.signal.signals : [];\n const sim = jaccard(curSignals, sigs);\n if (sim >= 0.34) {\n candidateKeys.push({ key: k, sim });\n seenKeys.add(k);\n }\n }\n\n const byGene = new Map();\n for (const ck of candidateKeys) {\n for (const g of Array.isArray(genes) ? genes : []) {\n if (!g || g.type !== 'Gene' || !g.id) continue;\n const k = `${ck.key}::${g.id}`;\n const edge = edges.get(k);\n const cur = byGene.get(g.id) || { geneId: g.id, best: 0, attempts: 0, prior: 0, prior_attempts: 0 };\n\n // Signal->Gene edge score (if available)\n if (edge) {\n const ex = edgeExpectedSuccess(edge, { half_life_days: 30 });\n const weighted = ex.value * ck.sim;\n if (weighted > cur.best) cur.best = weighted;\n cur.attempts = Math.max(cur.attempts, ex.total);\n }\n\n // Gene->Outcome prior (independent of signal): stabilizer when signal edges are sparse.\n const gEdge = geneOutcomes.get(String(g.id));\n if (gEdge) {\n const gx = edgeExpectedSuccess(gEdge, { half_life_days: 45 });\n cur.prior = Math.max(cur.prior, gx.value);\n cur.prior_attempts = Math.max(cur.prior_attempts, gx.total);\n }\n\n byGene.set(g.id, cur);\n }\n }\n\n for (const [geneId, info] of byGene.entries()) {\n const combined = info.best > 0 ? info.best + info.prior * 0.12 : info.prior * 0.4;\n scoredGeneIds.push({ geneId, score: combined, attempts: info.attempts, prior: info.prior });\n // Low-efficiency path suppression (unless drift is explicit).\n if (!driftEnabled && info.attempts >= 2 && info.best < 0.18) {\n bannedGeneIds.add(geneId);\n }\n // Also suppress genes with consistently poor global outcomes when signal edges are sparse.\n if (!driftEnabled && info.attempts < 2 && info.prior_attempts >= 3 && info.prior < 0.12) {\n bannedGeneIds.add(geneId);\n }\n }\n\n scoredGeneIds.sort((a, b) => b.score - a.score);\n const preferredGeneId = scoredGeneIds.length ? scoredGeneIds[0].geneId : null;\n\n const explanation = [];\n if (preferredGeneId) explanation.push(`memory_prefer:${preferredGeneId}`);\n if (bannedGeneIds.size) explanation.push(`memory_ban:${Array.from(bannedGeneIds).slice(0, 6).join(',')}`);\n if (preferredGeneId) {\n const top = scoredGeneIds.find(x => x && x.geneId === preferredGeneId);\n if (top && Number.isFinite(Number(top.prior)) && top.prior > 0) explanation.push(`gene_prior:${top.prior.toFixed(3)}`);\n }\n if (driftEnabled) explanation.push('random_drift:enabled');\n\n return {\n currentSignalKey: curKey,\n preferredGeneId,\n bannedGeneIds,\n explanation,\n };\n}\n\nfunction recordSignalSnapshot({ signals, observations }) {\n const signalKey = computeSignalKey(signals);\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'signal',\n id: `mge_${Date.now()}_${stableHash(`${signalKey}|signal|${ts}`)}`,\n ts,\n signal: {\n key: signalKey,\n signals: Array.isArray(signals) ? signals : [],\n error_signature: errsig || null,\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n appendJsonl(memoryGraphPath(), ev);\n return ev;\n}\n\nfunction buildHypothesisText({ signalKey, signals, geneId, geneCategory, driftEnabled }) {\n const sigCount = Array.isArray(signals) ? signals.length : 0;\n const drift = driftEnabled ? 'drift' : 'directed';\n const g = geneId ? `${geneId}${geneCategory ? `(${geneCategory})` : ''}` : '(none)';\n return `Given signal_key=${signalKey} with ${sigCount} signals, selecting gene=${g} under mode=${drift} is expected to reduce repeated errors and improve stability.`;\n}\n\nfunction recordHypothesis({\n signals,\n mutation,\n personality_state,\n selectedGene,\n selector,\n driftEnabled,\n selectedBy,\n capsulesUsed,\n observations,\n}) {\n const signalKey = computeSignalKey(signals);\n const geneId = selectedGene && selectedGene.id ? String(selectedGene.id) : null;\n const geneCategory = selectedGene && selectedGene.category ? String(selectedGene.category) : null;\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const hypothesisId = `hyp_${Date.now()}_${stableHash(`${signalKey}|${geneId || 'none'}|${ts}`)}`;\n const personalityState = personality_state || null;\n const mutNorm = mutation && isValidMutation(mutation) ? normalizeMutation(mutation) : null;\n const psNorm = personalityState && isValidPersonalityState(personalityState) ? normalizePersonalityState(personalityState) : null;\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'hypothesis',\n id: `mge_${Date.now()}_${stableHash(`${hypothesisId}|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [], error_signature: errsig || null },\n hypothesis: {\n id: hypothesisId,\n text: buildHypothesisText({ signalKey, signals, geneId, geneCategory, driftEnabled }),\n predicted_outcome: { status: null, score: null },\n },\n mutation: mutNorm\n ? {\n id: mutNorm.id,\n category: mutNorm.category,\n trigger_signals: mutNorm.trigger_signals,\n target: mutNorm.target,\n expected_effect: mutNorm.expected_effect,\n risk_level: mutNorm.risk_level,\n }\n : null,\n personality: psNorm\n ? {\n key: personalityKey(psNorm),\n state: psNorm,\n }\n : null,\n gene: { id: geneId, category: geneCategory },\n action: {\n drift: !!driftEnabled,\n selected_by: selectedBy || 'selector',\n selector: selector || null,\n },\n capsules: {\n used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n appendJsonl(memoryGraphPath(), ev);\n return { hypothesisId, signalKey };\n}\n\nfunction hasErrorSignal(signals) {\n const list = Array.isArray(signals) ? signals : [];\n return list.includes('log_error');\n}\n\nfunction recordAttempt({\n signals,\n mutation,\n personality_state,\n selectedGene,\n selector,\n driftEnabled,\n selectedBy,\n hypothesisId,\n capsulesUsed,\n observations,\n}) {\n const signalKey = computeSignalKey(signals);\n const geneId = selectedGene && selectedGene.id ? String(selectedGene.id) : null;\n const geneCategory = selectedGene && selectedGene.category ? String(selectedGene.category) : null;\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const actionId = `act_${Date.now()}_${stableHash(`${signalKey}|${geneId || 'none'}|${ts}`)}`;\n const personalityState = personality_state || null;\n const mutNorm = mutation && isValidMutation(mutation) ? normalizeMutation(mutation) : null;\n const psNorm = personalityState && isValidPersonalityState(personalityState) ? normalizePersonalityState(personalityState) : null;\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'attempt',\n id: `mge_${Date.now()}_${stableHash(actionId)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [], error_signature: errsig || null },\n mutation: mutNorm\n ? {\n id: mutNorm.id,\n category: mutNorm.category,\n trigger_signals: mutNorm.trigger_signals,\n target: mutNorm.target,\n expected_effect: mutNorm.expected_effect,\n risk_level: mutNorm.risk_level,\n }\n : null,\n personality: psNorm\n ? {\n key: personalityKey(psNorm),\n state: psNorm,\n }\n : null,\n gene: { id: geneId, category: geneCategory },\n hypothesis: hypothesisId ? { id: String(hypothesisId) } : null,\n action: {\n id: actionId,\n drift: !!driftEnabled,\n selected_by: selectedBy || 'selector',\n selector: selector || null,\n },\n capsules: {\n used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n\n appendJsonl(memoryGraphPath(), ev);\n\n // State is mutable; graph is append-only.\n const statePath = memoryGraphStatePath();\n const state = readJsonIfExists(statePath, { last_action: null });\n state.last_action = {\n action_id: actionId,\n signal_key: signalKey,\n signals: Array.isArray(signals) ? signals : [],\n mutation_id: mutNorm ? mutNorm.id : null,\n mutation_category: mutNorm ? mutNorm.category : null,\n mutation_risk_level: mutNorm ? mutNorm.risk_level : null,\n personality_key: psNorm ? personalityKey(psNorm) : null,\n personality_state: psNorm || null,\n gene_id: geneId,\n gene_category: geneCategory,\n hypothesis_id: hypothesisId ? String(hypothesisId) : null,\n capsules_used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n had_error: hasErrorSignal(signals),\n created_at: ts,\n outcome_recorded: false,\n baseline_observed: observations && typeof observations === 'object' ? observations : null,\n };\n writeJsonAtomic(statePath, state);\n\n return { actionId, signalKey };\n}\n\nfunction inferOutcomeFromSignals({ prevHadError, currentHasError }) {\n if (prevHadError && !currentHasError) return { status: 'success', score: 0.85, note: 'error_cleared' };\n if (prevHadError && currentHasError) return { status: 'failed', score: 0.2, note: 'error_persisted' };\n if (!prevHadError && currentHasError) return { status: 'failed', score: 0.15, note: 'new_error_appeared' };\n return { status: 'success', score: 0.6, note: 'stable_no_error' };\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction tryParseLastEvolutionEventOutcome(evidenceText) {\n // Scan tail text for an EvolutionEvent JSON line and extract its outcome.\n const s = String(evidenceText || '');\n if (!s) return null;\n const lines = s.split('\\n').slice(-400);\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim();\n if (!line) continue;\n if (!line.includes('\"type\"') || !line.includes('EvolutionEvent')) continue;\n try {\n const obj = JSON.parse(line);\n if (!obj || obj.type !== 'EvolutionEvent') continue;\n const o = obj.outcome && typeof obj.outcome === 'object' ? obj.outcome : null;\n if (!o) continue;\n const status = o.status === 'success' || o.status === 'failed' ? o.status : null;\n const score = Number.isFinite(Number(o.score)) ? clamp01(Number(o.score)) : null;\n if (!status && score == null) continue;\n return {\n status: status || (score != null && score >= 0.5 ? 'success' : 'failed'),\n score: score != null ? score : status === 'success' ? 0.75 : 0.25,\n note: 'evolutionevent_observed',\n };\n } catch (e) {\n continue;\n }\n }\n return null;\n}\n\nfunction inferOutcomeEnhanced({ prevHadError, currentHasError, baselineObserved, currentObserved }) {\n const evidence =\n currentObserved &&\n currentObserved.evidence &&\n (currentObserved.evidence.recent_session_tail || currentObserved.evidence.today_log_tail)\n ? currentObserved.evidence\n : null;\n const combinedEvidence = evidence\n ? `${String(evidence.recent_session_tail || '')}\\n${String(evidence.today_log_tail || '')}`\n : '';\n const observed = tryParseLastEvolutionEventOutcome(combinedEvidence);\n if (observed) return observed;\n\n const base = inferOutcomeFromSignals({ prevHadError, currentHasError });\n\n const prevErrCount =\n baselineObserved && Number.isFinite(Number(baselineObserved.recent_error_count))\n ? Number(baselineObserved.recent_error_count)\n : null;\n const curErrCount =\n currentObserved && Number.isFinite(Number(currentObserved.recent_error_count))\n ? Number(currentObserved.recent_error_count)\n : null;\n\n let score = base.score;\n if (prevErrCount != null && curErrCount != null) {\n const delta = prevErrCount - curErrCount;\n score += Math.max(-0.12, Math.min(0.12, delta / 50));\n }\n\n const prevScan =\n baselineObserved && Number.isFinite(Number(baselineObserved.scan_ms)) ? Number(baselineObserved.scan_ms) : null;\n const curScan =\n currentObserved && Number.isFinite(Number(currentObserved.scan_ms)) ? Number(currentObserved.scan_ms) : null;\n if (prevScan != null && curScan != null && prevScan > 0) {\n const ratio = (prevScan - curScan) / prevScan;\n score += Math.max(-0.06, Math.min(0.06, ratio));\n }\n\n return { status: base.status, score: clamp01(score), note: `${base.note}|heuristic_delta` };\n}\n\nfunction buildConfidenceEdgeEvent({ signalKey, signals, geneId, geneCategory, outcomeEventId, halfLifeDays }) {\n const events = tryReadMemoryGraphEvents(2000);\n const edges = aggregateEdges(events);\n const k = `${signalKey}::${geneId}`;\n const edge = edges.get(k) || { success: 0, fail: 0, last_ts: null };\n const ex = edgeExpectedSuccess(edge, { half_life_days: halfLifeDays });\n const ts = nowIso();\n return {\n type: 'MemoryGraphEvent',\n kind: 'confidence_edge',\n id: `mge_${Date.now()}_${stableHash(`${signalKey}|${geneId}|confidence|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [] },\n gene: { id: geneId, category: geneCategory || null },\n edge: { signal_key: signalKey, gene_id: geneId },\n stats: {\n success: Number(edge.success) || 0,\n fail: Number(edge.fail) || 0,\n attempts: Number(ex.total) || 0,\n p: ex.p,\n decay_weight: ex.w,\n value: ex.value,\n half_life_days: halfLifeDays,\n updated_at: ts,\n },\n derived_from: { outcome_event_id: outcomeEventId || null },\n };\n}\n\nfunction buildGeneOutcomeConfidenceEvent({ geneId, geneCategory, outcomeEventId, halfLifeDays }) {\n const events = tryReadMemoryGraphEvents(2000);\n const geneOutcomes = aggregateGeneOutcomes(events);\n const edge = geneOutcomes.get(String(geneId)) || { success: 0, fail: 0, last_ts: null };\n const ex = edgeExpectedSuccess(edge, { half_life_days: halfLifeDays });\n const ts = nowIso();\n return {\n type: 'MemoryGraphEvent',\n kind: 'confidence_gene_outcome',\n id: `mge_${Date.now()}_${stableHash(`${geneId}|gene_outcome|confidence|${ts}`)}`,\n ts,\n gene: { id: String(geneId), category: geneCategory || null },\n edge: { gene_id: String(geneId) },\n stats: {\n success: Number(edge.success) || 0,\n fail: Number(edge.fail) || 0,\n attempts: Number(ex.total) || 0,\n p: ex.p,\n decay_weight: ex.w,\n value: ex.value,\n half_life_days: halfLifeDays,\n updated_at: ts,\n },\n derived_from: { outcome_event_id: outcomeEventId || null },\n };\n}\n\nfunction recordOutcomeFromState({ signals, observations }) {\n const statePath = memoryGraphStatePath();\n const state = readJsonIfExists(statePath, { last_action: null });\n const last = state && state.last_action ? state.last_action : null;\n if (!last || !last.action_id) return null;\n if (last.outcome_recorded) return null;\n\n const currentHasError = hasErrorSignal(signals);\n const inferred = inferOutcomeEnhanced({\n prevHadError: !!last.had_error,\n currentHasError,\n baselineObserved: last.baseline_observed || null,\n currentObserved: observations || null,\n });\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'outcome',\n id: `mge_${Date.now()}_${stableHash(`${last.action_id}|outcome|${ts}`)}`,\n ts,\n signal: {\n key: String(last.signal_key || '(none)'),\n signals: Array.isArray(last.signals) ? last.signals : [],\n error_signature: errsig || null,\n },\n mutation:\n last.mutation_id || last.mutation_category || last.mutation_risk_level\n ? {\n id: last.mutation_id || null,\n category: last.mutation_category || null,\n risk_level: last.mutation_risk_level || null,\n }\n : null,\n personality:\n last.personality_key || last.personality_state\n ? {\n key: last.personality_key || null,\n state: last.personality_state || null,\n }\n : null,\n gene: { id: last.gene_id || null, category: last.gene_category || null },\n action: { id: String(last.action_id) },\n hypothesis: last.hypothesis_id ? { id: String(last.hypothesis_id) } : null,\n outcome: {\n status: inferred.status,\n score: inferred.score,\n note: inferred.note,\n observed: { current_signals: Array.isArray(signals) ? signals : [] },\n },\n confidence: {\n // This is an interpretable, decayed success estimate derived from outcomes; aggregation is computed at read-time.\n half_life_days: 30,\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n baseline: last.baseline_observed || null,\n capsules: {\n used: Array.isArray(last.capsules_used) ? last.capsules_used : [],\n },\n };\n\n appendJsonl(memoryGraphPath(), ev);\n\n // Persist explicit confidence snapshots (append-only) for auditability.\n try {\n if (last.gene_id) {\n const edgeEv = buildConfidenceEdgeEvent({\n signalKey: String(last.signal_key || '(none)'),\n signals: Array.isArray(last.signals) ? last.signals : [],\n geneId: String(last.gene_id),\n geneCategory: last.gene_category || null,\n outcomeEventId: ev.id,\n halfLifeDays: 30,\n });\n appendJsonl(memoryGraphPath(), edgeEv);\n\n const geneEv = buildGeneOutcomeConfidenceEvent({\n geneId: String(last.gene_id),\n geneCategory: last.gene_category || null,\n outcomeEventId: ev.id,\n halfLifeDays: 45,\n });\n appendJsonl(memoryGraphPath(), geneEv);\n }\n } catch (e) {}\n\n last.outcome_recorded = true;\n last.outcome_recorded_at = ts;\n state.last_action = last;\n writeJsonAtomic(statePath, state);\n\n return ev;\n}\n\nfunction recordExternalCandidate({ asset, source, signals }) {\n // Append-only annotation: external assets enter as candidates only.\n // This does not affect outcome aggregation (which only uses kind === 'outcome').\n const a = asset && typeof asset === 'object' ? asset : null;\n const type = a && a.type ? String(a.type) : null;\n const id = a && a.id ? String(a.id) : null;\n if (!type || !id) return null;\n\n const ts = nowIso();\n const signalKey = computeSignalKey(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'external_candidate',\n id: `mge_${Date.now()}_${stableHash(`${type}|${id}|external|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [] },\n external: {\n source: source || 'external',\n received_at: ts,\n },\n asset: { type, id },\n candidate: {\n // Minimal hints for later local triggering/validation.\n trigger: type === 'Capsule' && Array.isArray(a.trigger) ? a.trigger : [],\n gene: type === 'Capsule' && a.gene ? String(a.gene) : null,\n confidence: type === 'Capsule' && Number.isFinite(Number(a.confidence)) ? Number(a.confidence) : null,\n },\n };\n\n appendJsonl(memoryGraphPath(), ev);\n return ev;\n}\n\nmodule.exports = {\n memoryGraphPath,\n computeSignalKey,\n tryReadMemoryGraphEvents,\n getMemoryAdvice,\n recordSignalSnapshot,\n recordHypothesis,\n recordAttempt,\n recordOutcomeFromState,\n recordExternalCandidate,\n};\n\n",
526 "inputSchema": {},
527 "outputSchema": null,
528 "icons": null,
529 "annotations": null,
530 "meta": null,
531 "execution": null
532 },
533 {
534 "name": "solidify.js",
535 "title": null,
536 "description": "Script: solidify.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { loadGenes, upsertGene, appendEventJsonl, appendCapsule, upsertCapsule, getLastEventId } = require('./assetStore');\nconst { computeSignalKey, memoryGraphPath } = require('./memoryGraph');\nconst { computeCapsuleSuccessStreak, isBlastRadiusSafe } = require('./a2a');\nconst { getRepoRoot, getMemoryDir, getEvolutionDir } = require('./paths');\nconst { extractSignals } = require('./signals');\nconst { selectGene } = require('./selector');\nconst { isValidMutation, normalizeMutation, isHighRiskMutationAllowed, isHighRiskPersonality } = require('./mutation');\nconst {\n isValidPersonalityState,\n normalizePersonalityState,\n personalityKey,\n updatePersonalityStats,\n} = require('./personality');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { captureEnvFingerprint } = require('./envFingerprint');\nconst { buildValidationReport } = require('./validationReport');\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction safeJsonParse(text, fallback) {\n try {\n return JSON.parse(text);\n } catch {\n return fallback;\n }\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction stableHash(input) {\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction runCmd(cmd, opts = {}) {\n const cwd = opts.cwd || getRepoRoot();\n const timeoutMs = Number.isFinite(Number(opts.timeoutMs)) ? Number(opts.timeoutMs) : 120000;\n return execSync(cmd, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: timeoutMs });\n}\n\nfunction tryRunCmd(cmd, opts = {}) {\n try {\n return { ok: true, out: runCmd(cmd, opts), err: '' };\n } catch (e) {\n const stderr = e && e.stderr ? String(e.stderr) : '';\n const stdout = e && e.stdout ? String(e.stdout) : '';\n const msg = e && e.message ? String(e.message) : 'command_failed';\n return { ok: false, out: stdout, err: stderr || msg };\n }\n}\n\nfunction gitListChangedFiles({ repoRoot }) {\n const files = new Set();\n const s1 = tryRunCmd('git diff --name-only', { cwd: repoRoot, timeoutMs: 60000 });\n if (s1.ok) for (const line of String(s1.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n const s2 = tryRunCmd('git diff --cached --name-only', { cwd: repoRoot, timeoutMs: 60000 });\n if (s2.ok) for (const line of String(s2.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n const s3 = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n if (s3.ok) for (const line of String(s3.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n return Array.from(files);\n}\n\nfunction parseNumstat(text) {\n const lines = String(text || '').split('\\n').map(l => l.trim()).filter(Boolean);\n let added = 0;\n let deleted = 0;\n for (const line of lines) {\n const parts = line.split('\\t');\n if (parts.length < 3) continue;\n const a = Number(parts[0]);\n const d = Number(parts[1]);\n if (Number.isFinite(a)) added += a;\n if (Number.isFinite(d)) deleted += d;\n }\n return { added, deleted };\n}\n\nfunction countFileLines(absPath) {\n try {\n if (!fs.existsSync(absPath)) return 0;\n const buf = fs.readFileSync(absPath);\n if (!buf || buf.length === 0) return 0;\n let n = 1;\n for (let i = 0; i < buf.length; i++) if (buf[i] === 10) n++;\n return n;\n } catch {\n return 0;\n }\n}\n\nfunction computeBlastRadius({ repoRoot, baselineUntracked }) {\n let changedFiles = gitListChangedFiles({ repoRoot });\n if (Array.isArray(baselineUntracked) && baselineUntracked.length > 0) {\n const baselineSet = new Set(baselineUntracked);\n changedFiles = changedFiles.filter(f => !baselineSet.has(f));\n }\n const filesCount = changedFiles.length;\n const u = tryRunCmd('git diff --numstat', { cwd: repoRoot, timeoutMs: 60000 });\n const c = tryRunCmd('git diff --cached --numstat', { cwd: repoRoot, timeoutMs: 60000 });\n const unstaged = u.ok ? parseNumstat(u.out) : { added: 0, deleted: 0 };\n const staged = c.ok ? parseNumstat(c.out) : { added: 0, deleted: 0 };\n const untracked = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n let untrackedLines = 0;\n if (untracked.ok) {\n const rels = String(untracked.out).split('\\n').map(l => l.trim()).filter(Boolean);\n const baselineSet = new Set(Array.isArray(baselineUntracked) ? baselineUntracked : []);\n for (const rel of rels) {\n if (baselineSet.has(rel)) continue;\n const abs = path.join(repoRoot, rel);\n untrackedLines += countFileLines(abs);\n }\n }\n const churn = unstaged.added + unstaged.deleted + staged.added + staged.deleted + untrackedLines;\n return { files: filesCount, lines: churn, changed_files: changedFiles };\n}\n\nfunction isForbiddenPath(relPath, forbiddenPaths) {\n const rel = String(relPath || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '');\n const list = Array.isArray(forbiddenPaths) ? forbiddenPaths : [];\n for (const fp of list) {\n const f = String(fp || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '').replace(/\\/+$/, '');\n if (!f) continue;\n if (rel === f) return true;\n if (rel.startsWith(f + '/')) return true;\n }\n return false;\n}\n\nfunction checkConstraints({ gene, blast }) {\n const violations = [];\n if (!gene || gene.type !== 'Gene') return { ok: true, violations };\n const constraints = gene.constraints || {};\n const maxFiles = Number(constraints.max_files);\n if (Number.isFinite(maxFiles) && maxFiles > 0) {\n if (Number(blast.files) > maxFiles) violations.push(`max_files exceeded: ${blast.files} > ${maxFiles}`);\n }\n const forbidden = Array.isArray(constraints.forbidden_paths) ? constraints.forbidden_paths : [];\n for (const f of blast.changed_files || []) {\n if (isForbiddenPath(f, forbidden)) violations.push(`forbidden_path touched: ${f}`);\n }\n return { ok: violations.length === 0, violations };\n}\n\nfunction readStateForSolidify() {\n const memoryDir = getMemoryDir();\n const statePath = path.join(getEvolutionDir(), 'evolution_solidify_state.json');\n return readJsonIfExists(statePath, { last_run: null });\n}\n\nfunction writeStateForSolidify(state) {\n const memoryDir = getMemoryDir();\n const statePath = path.join(getEvolutionDir(), 'evolution_solidify_state.json');\n try {\n if (!fs.existsSync(memoryDir)) fs.mkdirSync(memoryDir, { recursive: true });\n } catch {}\n const tmp = `${statePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(state, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, statePath);\n}\n\nfunction buildEventId(tsIso) {\n const t = Date.parse(tsIso);\n return `evt_${Number.isFinite(t) ? t : Date.now()}`;\n}\n\nfunction buildCapsuleId(tsIso) {\n const t = Date.parse(tsIso);\n return `capsule_${Number.isFinite(t) ? t : Date.now()}`;\n}\n\n// --- Validation command safety ---\nconst VALIDATION_ALLOWED_PREFIXES = ['node ', 'npm ', 'npx '];\n\nfunction isValidationCommandAllowed(cmd) {\n const c = String(cmd || '').trim();\n if (!c) return false;\n if (!VALIDATION_ALLOWED_PREFIXES.some(p => c.startsWith(p))) return false;\n if (/`|\\$\\(/.test(c)) return false;\n const stripped = c.replace(/\"[^\"]*\"/g, '').replace(/'[^']*'/g, '');\n if (/[;&|><]/.test(stripped)) return false;\n return true;\n}\n\nfunction runValidations(gene, opts = {}) {\n const repoRoot = opts.repoRoot || getRepoRoot();\n const timeoutMs = Number.isFinite(Number(opts.timeoutMs)) ? Number(opts.timeoutMs) : 180000;\n const validation = Array.isArray(gene && gene.validation) ? gene.validation : [];\n const results = [];\n const startedAt = Date.now();\n for (const cmd of validation) {\n const c = String(cmd || '').trim();\n if (!c) continue;\n if (!isValidationCommandAllowed(c)) {\n results.push({ cmd: c, ok: false, out: '', err: 'BLOCKED: validation command rejected by safety check (allowed prefixes: node/npm/npx; shell operators prohibited)' });\n return { ok: false, results, startedAt, finishedAt: Date.now() };\n }\n const r = tryRunCmd(c, { cwd: repoRoot, timeoutMs });\n results.push({ cmd: c, ok: r.ok, out: String(r.out || ''), err: String(r.err || '') });\n if (!r.ok) return { ok: false, results, startedAt, finishedAt: Date.now() };\n }\n return { ok: true, results, startedAt, finishedAt: Date.now() };\n}\n\nfunction rollbackTracked(repoRoot) {\n tryRunCmd('git restore --staged --worktree .', { cwd: repoRoot, timeoutMs: 60000 });\n tryRunCmd('git reset --hard', { cwd: repoRoot, timeoutMs: 60000 });\n}\n\nfunction gitListUntrackedFiles(repoRoot) {\n const r = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n if (!r.ok) return [];\n return String(r.out).split('\\n').map(l => l.trim()).filter(Boolean);\n}\n\nfunction rollbackNewUntrackedFiles({ repoRoot, baselineUntracked }) {\n const baseline = new Set((Array.isArray(baselineUntracked) ? baselineUntracked : []).map(String));\n const current = gitListUntrackedFiles(repoRoot);\n const toDelete = current.filter(f => !baseline.has(String(f)));\n for (const rel of toDelete) {\n const safeRel = String(rel || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '');\n if (!safeRel) continue;\n const abs = path.join(repoRoot, safeRel);\n const normRepo = path.resolve(repoRoot);\n const normAbs = path.resolve(abs);\n if (!normAbs.startsWith(normRepo + path.sep) && normAbs !== normRepo) continue;\n try {\n if (fs.existsSync(normAbs) && fs.statSync(normAbs).isFile()) fs.unlinkSync(normAbs);\n } catch (e) {}\n }\n return { deleted: toDelete };\n}\n\nfunction inferCategoryFromSignals(signals) {\n const list = Array.isArray(signals) ? signals.map(String) : [];\n if (list.includes('log_error')) return 'repair';\n if (list.includes('protocol_drift')) return 'optimize';\n return 'optimize';\n}\n\nfunction buildAutoGene({ signals, intent }) {\n const sigs = Array.isArray(signals) ? Array.from(new Set(signals.map(String))).filter(Boolean) : [];\n const signalKey = computeSignalKey(sigs);\n const id = `gene_auto_${stableHash(signalKey)}`;\n const category = intent && ['repair', 'optimize', 'innovate'].includes(String(intent))\n ? String(intent)\n : inferCategoryFromSignals(sigs);\n const signalsMatch = sigs.length ? sigs.slice(0, 8) : ['(none)'];\n const gene = {\n type: 'Gene',\n schema_version: SCHEMA_VERSION,\n id,\n category,\n signals_match: signalsMatch,\n preconditions: [`signals_key == ${signalKey}`],\n strategy: [\n 'Extract structured signals from logs and user instructions',\n 'Select an existing Gene by signals match (no improvisation)',\n 'Estimate blast radius (files, lines) before editing and record it',\n 'Apply smallest reversible patch',\n 'Validate using declared validation steps; rollback on failure',\n 'Solidify knowledge: append EvolutionEvent, update Gene/Capsule store',\n ],\n constraints: { max_files: 12, forbidden_paths: ['.git', 'node_modules'] },\n validation: ['node -e \"require(\\'./src/gep/solidify\\'); console.log(\\'ok\\')\"'],\n };\n gene.asset_id = computeAssetId(gene);\n return gene;\n}\n\nfunction ensureGene({ genes, selectedGene, signals, intent, dryRun }) {\n if (selectedGene && selectedGene.type === 'Gene') return { gene: selectedGene, created: false, reason: 'selected_gene_id_present' };\n const res = selectGene(Array.isArray(genes) ? genes : [], Array.isArray(signals) ? signals : [], {\n bannedGeneIds: new Set(), preferredGeneId: null, driftEnabled: false,\n });\n if (res && res.selected) return { gene: res.selected, created: false, reason: 'reselected_from_existing' };\n const auto = buildAutoGene({ signals, intent });\n if (!dryRun) upsertGene(auto);\n return { gene: auto, created: true, reason: 'no_match_create_new' };\n}\n\nfunction readRecentSessionInputs() {\n const repoRoot = getRepoRoot();\n const memoryDir = getMemoryDir();\n const rootMemory = path.join(repoRoot, 'MEMORY.md');\n const dirMemory = path.join(memoryDir, 'MEMORY.md');\n const memoryFile = fs.existsSync(rootMemory) ? rootMemory : dirMemory;\n const userFile = path.join(repoRoot, 'USER.md');\n const todayLog = path.join(memoryDir, new Date().toISOString().split('T')[0] + '.md');\n const todayLogContent = fs.existsSync(todayLog) ? fs.readFileSync(todayLog, 'utf8') : '';\n const memorySnippet = fs.existsSync(memoryFile) ? fs.readFileSync(memoryFile, 'utf8').slice(0, 50000) : '';\n const userSnippet = fs.existsSync(userFile) ? fs.readFileSync(userFile, 'utf8') : '';\n const recentSessionTranscript = '';\n return { recentSessionTranscript, todayLog: todayLogContent, memorySnippet, userSnippet };\n}\n\nfunction solidify({ intent, summary, dryRun = false, rollbackOnFailure = true } = {}) {\n const repoRoot = getRepoRoot();\n const state = readStateForSolidify();\n const lastRun = state && state.last_run ? state.last_run : null;\n const genes = loadGenes();\n const geneId = lastRun && lastRun.selected_gene_id ? String(lastRun.selected_gene_id) : null;\n const selectedGene = geneId ? genes.find(g => g && g.type === 'Gene' && g.id === geneId) : null;\n const parentEventId =\n lastRun && typeof lastRun.parent_event_id === 'string' ? lastRun.parent_event_id : getLastEventId();\n const signals =\n lastRun && Array.isArray(lastRun.signals) && lastRun.signals.length\n ? Array.from(new Set(lastRun.signals.map(String)))\n : extractSignals(readRecentSessionInputs());\n const signalKey = computeSignalKey(signals);\n\n const mutationRaw = lastRun && lastRun.mutation && typeof lastRun.mutation === 'object' ? lastRun.mutation : null;\n const personalityRaw =\n lastRun && lastRun.personality_state && typeof lastRun.personality_state === 'object' ? lastRun.personality_state : null;\n const mutation = mutationRaw && isValidMutation(mutationRaw) ? normalizeMutation(mutationRaw) : null;\n const personalityState =\n personalityRaw && isValidPersonalityState(personalityRaw) ? normalizePersonalityState(personalityRaw) : null;\n const personalityKeyUsed = personalityState ? personalityKey(personalityState) : null;\n const protocolViolations = [];\n if (!mutation) protocolViolations.push('missing_or_invalid_mutation');\n if (!personalityState) protocolViolations.push('missing_or_invalid_personality_state');\n if (mutation && mutation.risk_level === 'high' && !isHighRiskMutationAllowed(personalityState || null)) {\n protocolViolations.push('high_risk_mutation_not_allowed_by_personality');\n }\n if (mutation && mutation.risk_level === 'high' && !(lastRun && lastRun.personality_known)) {\n protocolViolations.push('high_risk_mutation_forbidden_under_unknown_personality');\n }\n if (mutation && mutation.category === 'innovate' && personalityState && isHighRiskPersonality(personalityState)) {\n protocolViolations.push('forbidden_innovate_with_high_risk_personality');\n }\n\n const ensured = ensureGene({ genes, selectedGene, signals, intent, dryRun: !!dryRun });\n const geneUsed = ensured.gene;\n const blast = computeBlastRadius({\n repoRoot,\n baselineUntracked: lastRun && Array.isArray(lastRun.baseline_untracked) ? lastRun.baseline_untracked : [],\n });\n const constraintCheck = checkConstraints({ gene: geneUsed, blast });\n\n // Capture environment fingerprint before validation.\n const envFp = captureEnvFingerprint();\n\n let validation = { ok: true, results: [], startedAt: null, finishedAt: null };\n if (geneUsed) {\n validation = runValidations(geneUsed, { repoRoot, timeoutMs: 180000 });\n }\n\n // Build standardized ValidationReport (machine-readable, interoperable).\n const validationReport = buildValidationReport({\n geneId: geneUsed && geneUsed.id ? geneUsed.id : null,\n commands: validation.results.map(function (r) { return r.cmd; }),\n results: validation.results,\n envFp: envFp,\n startedAt: validation.startedAt,\n finishedAt: validation.finishedAt,\n });\n\n const success = constraintCheck.ok && validation.ok && protocolViolations.length === 0;\n const ts = nowIso();\n const outcomeStatus = success ? 'success' : 'failed';\n const score = clamp01(success ? 0.85 : 0.2);\n\n const selectedCapsuleId =\n lastRun && typeof lastRun.selected_capsule_id === 'string' && lastRun.selected_capsule_id.trim()\n ? String(lastRun.selected_capsule_id).trim() : null;\n const capsuleId = success ? selectedCapsuleId || buildCapsuleId(ts) : null;\n const derivedIntent = intent || (mutation && mutation.category) || (geneUsed && geneUsed.category) || 'repair';\n const intentMismatch =\n intent && mutation && typeof mutation.category === 'string' && String(intent) !== String(mutation.category);\n if (intentMismatch) protocolViolations.push(`intent_mismatch_with_mutation:${String(intent)}!=${String(mutation.category)}`);\n\n const event = {\n type: 'EvolutionEvent',\n schema_version: SCHEMA_VERSION,\n id: buildEventId(ts),\n parent: parentEventId || null,\n intent: derivedIntent,\n signals,\n genes_used: geneUsed && geneUsed.id ? [geneUsed.id] : [],\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_state: personalityState || null,\n blast_radius: { files: blast.files, lines: blast.lines },\n outcome: { status: outcomeStatus, score },\n capsule_id: capsuleId,\n env_fingerprint: envFp,\n validation_report_id: validationReport.id,\n meta: {\n at: ts,\n signal_key: signalKey,\n selector: lastRun && lastRun.selector ? lastRun.selector : null,\n blast_radius_estimate: lastRun && lastRun.blast_radius_estimate ? lastRun.blast_radius_estimate : null,\n mutation: mutation || null,\n personality: {\n key: personalityKeyUsed,\n known: !!(lastRun && lastRun.personality_known),\n mutations: lastRun && Array.isArray(lastRun.personality_mutations) ? lastRun.personality_mutations : [],\n },\n gene: {\n id: geneUsed && geneUsed.id ? geneUsed.id : null,\n created: !!ensured.created,\n reason: ensured.reason,\n },\n constraints_ok: constraintCheck.ok,\n constraint_violations: constraintCheck.violations,\n validation_ok: validation.ok,\n validation: validation.results.map(r => ({ cmd: r.cmd, ok: r.ok })),\n validation_report: validationReport,\n protocol_ok: protocolViolations.length === 0,\n protocol_violations: protocolViolations,\n memory_graph: memoryGraphPath(),\n },\n };\n event.asset_id = computeAssetId(event);\n\n let capsule = null;\n if (success) {\n const s = String(summary || '').trim();\n const autoSummary = geneUsed\n ? `\u56fa\u5316\uff1a${geneUsed.id} \u547d\u4e2d\u4fe1\u53f7 ${signals.join(', ') || '(none)'}\uff0c\u53d8\u66f4 ${blast.files} \u6587\u4ef6 / ${blast.lines} \u884c\u3002`\n : `\u56fa\u5316\uff1a\u547d\u4e2d\u4fe1\u53f7 ${signals.join(', ') || '(none)'}\uff0c\u53d8\u66f4 ${blast.files} \u6587\u4ef6 / ${blast.lines} \u884c\u3002`;\n let prevCapsule = null;\n try {\n if (selectedCapsuleId) {\n const list = require('./assetStore').loadCapsules();\n prevCapsule = Array.isArray(list) ? list.find(c => c && c.type === 'Capsule' && String(c.id) === selectedCapsuleId) : null;\n }\n } catch (e) {}\n capsule = {\n type: 'Capsule',\n schema_version: SCHEMA_VERSION,\n id: capsuleId,\n trigger: prevCapsule && Array.isArray(prevCapsule.trigger) && prevCapsule.trigger.length ? prevCapsule.trigger : signals,\n gene: geneUsed && geneUsed.id ? geneUsed.id : prevCapsule && prevCapsule.gene ? prevCapsule.gene : null,\n summary: s || (prevCapsule && prevCapsule.summary ? String(prevCapsule.summary) : autoSummary),\n confidence: clamp01(score),\n blast_radius: { files: blast.files, lines: blast.lines },\n outcome: { status: 'success', score },\n success_streak: 1,\n env_fingerprint: envFp,\n metadata: {\n author: process.env.A2A_NODE_ID || process.env.AGENT_NAME || 'unknown',\n tags: signals.slice(0, 5),\n created_at: ts,\n },\n performance_metrics: {\n reuse_potential: prevCapsule ? 'high' : 'medium',\n blast_efficiency: blast.files > 0 ? Math.round((blast.lines / blast.files) * 10) / 10 : 0,\n },\n a2a: { eligible_to_broadcast: false },\n };\n capsule.asset_id = computeAssetId(capsule);\n }\n\n // Bug fix: dry-run must NOT trigger rollback (it should only observe, not mutate).\n if (!dryRun && !success && rollbackOnFailure) {\n rollbackTracked(repoRoot);\n rollbackNewUntrackedFiles({ repoRoot, baselineUntracked: lastRun && lastRun.baseline_untracked ? lastRun.baseline_untracked : [] });\n }\n\n if (!dryRun) {\n appendEventJsonl(validationReport);\n if (capsule) upsertCapsule(capsule);\n appendEventJsonl(event);\n if (capsule) {\n const streak = computeCapsuleSuccessStreak({ capsuleId: capsule.id });\n capsule.success_streak = streak || 1;\n capsule.a2a = {\n eligible_to_broadcast:\n isBlastRadiusSafe(capsule.blast_radius) &&\n (capsule.outcome.score || 0) >= 0.7 &&\n (capsule.success_streak || 0) >= 2,\n };\n capsule.asset_id = computeAssetId(capsule);\n upsertCapsule(capsule);\n }\n try {\n if (personalityState) {\n updatePersonalityStats({ personalityState, outcome: outcomeStatus, score, notes: `event:${event.id}` });\n }\n } catch (e) {}\n }\n\n const runId = lastRun && lastRun.run_id ? String(lastRun.run_id) : stableHash(`${parentEventId || 'root'}|${geneId || 'none'}|${signalKey}`);\n state.last_solidify = {\n run_id: runId, at: ts, event_id: event.id, capsule_id: capsuleId, outcome: event.outcome,\n };\n if (!dryRun) writeStateForSolidify(state);\n\n return { ok: success, event, capsule, gene: geneUsed, constraintCheck, validation, validationReport, blast };\n}\n\nmodule.exports = {\n solidify,\n readStateForSolidify,\n writeStateForSolidify,\n isValidationCommandAllowed,\n};\n",
537 "inputSchema": {},
538 "outputSchema": null,
539 "icons": null,
540 "annotations": null,
541 "meta": null,
542 "execution": null
543 },
544 {
545 "name": "index.js",
546 "title": null,
547 "description": "Script: index.js. Code:\nconst evolve = require('./src/evolve');\nconst { solidify } = require('./src/gep/solidify');\nconst path = require('path');\nconst fs = require('fs');\nconst { spawn } = require('child_process');\n\nfunction sleepMs(ms) {\n const n = parseInt(String(ms), 10);\n const t = Number.isFinite(n) ? Math.max(0, n) : 0;\n return new Promise(resolve => setTimeout(resolve, t));\n}\n\nfunction readJsonSafe(p) {\n try {\n if (!fs.existsSync(p)) return null;\n const raw = fs.readFileSync(p, 'utf8');\n if (!raw.trim()) return null;\n return JSON.parse(raw);\n } catch (e) {\n return null;\n }\n}\n\nfunction isPendingSolidify(state) {\n const lastRun = state && state.last_run ? state.last_run : null;\n const lastSolid = state && state.last_solidify ? state.last_solidify : null;\n if (!lastRun || !lastRun.run_id) return false;\n if (!lastSolid || !lastSolid.run_id) return true;\n return String(lastSolid.run_id) !== String(lastRun.run_id);\n}\n\nfunction parseMs(v, fallback) {\n const n = parseInt(String(v == null ? '' : v), 10);\n if (Number.isFinite(n)) return Math.max(0, n);\n return fallback;\n}\n\n// Singleton Guard - prevent multiple evolver daemon instances\nfunction acquireLock() {\n const lockFile = path.join(__dirname, 'evolver.pid');\n try {\n if (fs.existsSync(lockFile)) {\n const pid = parseInt(fs.readFileSync(lockFile, 'utf8').trim(), 10);\n try {\n process.kill(pid, 0); // Check if process exists\n console.log(`[Singleton] Evolver loop already running (PID ${pid}). Exiting.`);\n return false;\n } catch (e) {\n console.log(`[Singleton] Stale lock found (PID ${pid}). Taking over.`);\n }\n }\n fs.writeFileSync(lockFile, String(process.pid));\n return true;\n } catch (err) {\n console.error('[Singleton] Lock acquisition failed:', err);\n return false;\n }\n}\n\nfunction releaseLock() {\n const lockFile = path.join(__dirname, 'evolver.pid');\n try {\n if (fs.existsSync(lockFile)) {\n const pid = parseInt(fs.readFileSync(lockFile, 'utf8').trim(), 10);\n if (pid === process.pid) fs.unlinkSync(lockFile);\n }\n } catch (e) { /* ignore */ }\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n const command = args[0];\n const isLoop = args.includes('--loop') || args.includes('--mad-dog');\n\n if (command === 'run' || command === '/evolve' || isLoop) {\n console.log('Starting capability evolver...');\n \n if (isLoop) {\n // Internal daemon loop (no wrapper required).\n if (!acquireLock()) process.exit(0);\n process.on('exit', releaseLock);\n process.on('SIGINT', () => { releaseLock(); process.exit(); });\n process.on('SIGTERM', () => { releaseLock(); process.exit(); });\n\n process.env.EVOLVE_LOOP = 'true';\n process.env.EVOLVE_BRIDGE = 'false';\n console.log('Loop mode enabled (internal daemon).');\n\n const solidifyStatePath = path.join(__dirname, 'memory', 'evolution_solidify_state.json');\n\n const minSleepMs = parseMs(process.env.EVOLVER_MIN_SLEEP_MS, 2000);\n const maxSleepMs = parseMs(process.env.EVOLVER_MAX_SLEEP_MS, 300000);\n const idleThresholdMs = parseMs(process.env.EVOLVER_IDLE_THRESHOLD_MS, 500);\n const pendingSleepMs = parseMs(\n process.env.EVOLVE_PENDING_SLEEP_MS ||\n process.env.EVOLVE_MIN_INTERVAL ||\n process.env.FEISHU_EVOLVER_INTERVAL,\n 120000\n );\n\n const maxCyclesPerProcess = parseMs(process.env.EVOLVER_MAX_CYCLES_PER_PROCESS, 100) || 100;\n const maxRssMb = parseMs(process.env.EVOLVER_MAX_RSS_MB, 500) || 500;\n const suicideEnabled = String(process.env.EVOLVER_SUICIDE || '').toLowerCase() !== 'false';\n\n let currentSleepMs = Math.min(maxSleepMs, Math.max(minSleepMs, minSleepMs));\n let cycleCount = 0;\n\n while (true) {\n cycleCount += 1;\n\n // Ralph-loop gating: do not run a new cycle while previous run is pending solidify.\n const st0 = readJsonSafe(solidifyStatePath);\n if (isPendingSolidify(st0)) {\n await sleepMs(Math.max(pendingSleepMs, minSleepMs));\n continue;\n }\n\n const t0 = Date.now();\n let ok = false;\n try {\n await evolve.run();\n ok = true;\n } catch (error) {\n const msg = error && error.message ? String(error.message) : String(error);\n console.error(`Evolution cycle failed: ${msg}`);\n }\n const dt = Date.now() - t0;\n\n // Adaptive sleep: treat very fast cycles as \"idle\", backoff; otherwise reset to min.\n if (!ok || dt < idleThresholdMs) {\n currentSleepMs = Math.min(maxSleepMs, Math.max(minSleepMs, currentSleepMs * 2));\n } else {\n currentSleepMs = minSleepMs;\n }\n\n // Suicide check (memory leak protection)\n if (suicideEnabled) {\n const memMb = process.memoryUsage().rss / 1024 / 1024;\n if (cycleCount >= maxCyclesPerProcess || memMb > maxRssMb) {\n console.log(`[Daemon] Restarting self (cycles=${cycleCount}, rssMb=${memMb.toFixed(0)})`);\n releaseLock(); // Release before spawning to allow child to acquire\n const child = spawn(process.execPath, [__filename, ...args], {\n detached: true,\n stdio: 'ignore',\n env: process.env,\n });\n child.unref();\n process.exit(0);\n }\n }\n\n // Jitter to avoid lockstep restarts.\n const jitter = Math.floor(Math.random() * 250);\n await sleepMs(currentSleepMs + jitter);\n }\n } else {\n // Normal Single Run\n try {\n await evolve.run();\n } catch (error) {\n console.error('Evolution failed:', error);\n process.exit(1);\n }\n }\n\n // Post-run hint\n console.log('\\n' + '=======================================================');\n console.log('Capability evolver finished. If you use this project, consider starring the upstream repository.');\n console.log('Upstream: https://github.com/autogame-17/capability-evolver');\n console.log('=======================================================\\n');\n \n } else if (command === 'solidify') {\n const dryRun = args.includes('--dry-run');\n const noRollback = args.includes('--no-rollback');\n const intentFlag = args.find(a => typeof a === 'string' && a.startsWith('--intent='));\n const summaryFlag = args.find(a => typeof a === 'string' && a.startsWith('--summary='));\n const intent = intentFlag ? intentFlag.slice('--intent='.length) : null;\n const summary = summaryFlag ? summaryFlag.slice('--summary='.length) : null;\n\n try {\n const res = solidify({\n intent: intent || undefined,\n summary: summary || undefined,\n dryRun,\n rollbackOnFailure: !noRollback,\n });\n const st = res && res.ok ? 'SUCCESS' : 'FAILED';\n console.log(`[SOLIDIFY] ${st}`);\n if (res && res.gene) console.log(JSON.stringify(res.gene, null, 2));\n if (res && res.event) console.log(JSON.stringify(res.event, null, 2));\n if (res && res.capsule) console.log(JSON.stringify(res.capsule, null, 2));\n process.exit(res && res.ok ? 0 : 2);\n } catch (error) {\n console.error('[SOLIDIFY] Error:', error);\n process.exit(2);\n }\n } else {\n console.log(`Usage: node index.js [run|/evolve|solidify] [--loop]\n - solidify flags:\n - --dry-run\n - --no-rollback\n - --intent=repair|optimize|innovate\n - --summary=...`);\n }\n}\n\nif (require.main === module) {\n main();\n}\n",
548 "inputSchema": {},
549 "outputSchema": null,
550 "icons": null,
551 "annotations": null,
552 "meta": null,
553 "execution": null
554 }
555 ]
556 },
557 "error": null
558 }
559 ],
560 "issues": [
561 {
562 "code": "W004",
563 "message": "The MCP server is not in our registry.",
564 "reference": [
565 0,
566 null
567 ],
568 "extra_data": null
569 },
570 {
571 "code": "W011",
572 "message": "Third-party content exposure detected (high risk: 0.90). The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.",
573 "reference": [
574 0,
575 null
576 ],
577 "extra_data": {
578 "risk_score": 0.9,
579 "reason": "The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.",
580 "thought_process": "<reason>The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.</reason>\n<answer>0.9</answer>",
581 "severity": "high"
582 }
583 },
584 {
585 "code": "W008",
586 "message": "Attempt to compromise machine state in skill instructions detected (high risk: 0.70). This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.",
587 "reference": [
588 0,
589 null
590 ],
591 "extra_data": {
592 "risk_score": 0.7,
593 "reason": "This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.",
594 "thought_process": "<reason>This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.</reason>\n<answer>0.7</answer>",
595 "severity": "high"
596 }
597 }
598 ],
599 "labels": [
600 [
601 {
602 "is_public_sink": 0,
603 "destructive": 0,
604 "untrusted_content": 0,
605 "private_data": 0
606 },
607 {
608 "is_public_sink": 0,
609 "destructive": 0,
610 "untrusted_content": 0,
611 "private_data": 0
612 },
613 {
614 "is_public_sink": 0,
615 "destructive": 0,
616 "untrusted_content": 0,
617 "private_data": 0
618 },
619 {
620 "is_public_sink": 0,
621 "destructive": 0,
622 "untrusted_content": 0,
623 "private_data": 0
624 },
625 {
626 "is_public_sink": 0,
627 "destructive": 0,
628 "untrusted_content": 0,
629 "private_data": 0
630 },
631 {
632 "is_public_sink": 0,
633 "destructive": 0,
634 "untrusted_content": 0,
635 "private_data": 0
636 },
637 {
638 "is_public_sink": 0,
639 "destructive": 0,
640 "untrusted_content": 0,
641 "private_data": 0
642 },
643 {
644 "is_public_sink": 0,
645 "destructive": 0,
646 "untrusted_content": 0,
647 "private_data": 0
648 },
649 {
650 "is_public_sink": 0,
651 "destructive": 0,
652 "untrusted_content": 0,
653 "private_data": 0
654 },
655 {
656 "is_public_sink": 0,
657 "destructive": 0,
658 "untrusted_content": 0,
659 "private_data": 0
660 },
661 {
662 "is_public_sink": 0,
663 "destructive": 0,
664 "untrusted_content": 0,
665 "private_data": 0
666 },
667 {
668 "is_public_sink": 0,
669 "destructive": 0,
670 "untrusted_content": 0,
671 "private_data": 0
672 },
673 {
674 "is_public_sink": 0,
675 "destructive": 0,
676 "untrusted_content": 0,
677 "private_data": 0
678 },
679 {
680 "is_public_sink": 0,
681 "destructive": 0,
682 "untrusted_content": 0,
683 "private_data": 0
684 },
685 {
686 "is_public_sink": 0,
687 "destructive": 0,
688 "untrusted_content": 0,
689 "private_data": 0
690 },
691 {
692 "is_public_sink": 0,
693 "destructive": 0,
694 "untrusted_content": 0,
695 "private_data": 0
696 },
697 {
698 "is_public_sink": 0,
699 "destructive": 0,
700 "untrusted_content": 0,
701 "private_data": 0
702 },
703 {
704 "is_public_sink": 0,
705 "destructive": 0,
706 "untrusted_content": 0,
707 "private_data": 0
708 },
709 {
710 "is_public_sink": 0,
711 "destructive": 0,
712 "untrusted_content": 0,
713 "private_data": 0
714 },
715 {
716 "is_public_sink": 0,
717 "destructive": 0,
718 "untrusted_content": 0,
719 "private_data": 0
720 },
721 {
722 "is_public_sink": 0,
723 "destructive": 0,
724 "untrusted_content": 0,
725 "private_data": 0
726 },
727 {
728 "is_public_sink": 0,
729 "destructive": 0,
730 "untrusted_content": 0,
731 "private_data": 0
732 },
733 {
734 "is_public_sink": 0,
735 "destructive": 0,
736 "untrusted_content": 0,
737 "private_data": 0
738 },
739 {
740 "is_public_sink": 0,
741 "destructive": 0,
742 "untrusted_content": 0,
743 "private_data": 0
744 },
745 {
746 "is_public_sink": 0,
747 "destructive": 0,
748 "untrusted_content": 0,
749 "private_data": 0
750 },
751 {
752 "is_public_sink": 0,
753 "destructive": 0,
754 "untrusted_content": 0,
755 "private_data": 0
756 },
757 {
758 "is_public_sink": 0,
759 "destructive": 0,
760 "untrusted_content": 0,
761 "private_data": 0
762 },
763 {
764 "is_public_sink": 0,
765 "destructive": 0,
766 "untrusted_content": 0,
767 "private_data": 0
768 },
769 {
770 "is_public_sink": 0,
771 "destructive": 0,
772 "untrusted_content": 0,
773 "private_data": 0
774 },
775 {
776 "is_public_sink": 0,
777 "destructive": 0,
778 "untrusted_content": 0,
779 "private_data": 0
780 },
781 {
782 "is_public_sink": 0,
783 "destructive": 0,
784 "untrusted_content": 0,
785 "private_data": 0
786 },
787 {
788 "is_public_sink": 0,
789 "destructive": 0,
790 "untrusted_content": 0,
791 "private_data": 0
792 },
793 {
794 "is_public_sink": 0,
795 "destructive": 0,
796 "untrusted_content": 0,
797 "private_data": 0
798 },
799 {
800 "is_public_sink": 0,
801 "destructive": 0,
802 "untrusted_content": 0,
803 "private_data": 0
804 },
805 {
806 "is_public_sink": 0,
807 "destructive": 0,
808 "untrusted_content": 0,
809 "private_data": 0
810 },
811 {
812 "is_public_sink": 0,
813 "destructive": 0,
814 "untrusted_content": 0,
815 "private_data": 0
816 },
817 {
818 "is_public_sink": 0,
819 "destructive": 0,
820 "untrusted_content": 0,
821 "private_data": 0
822 },
823 {
824 "is_public_sink": 0,
825 "destructive": 0,
826 "untrusted_content": 0,
827 "private_data": 0
828 },
829 {
830 "is_public_sink": 0,
831 "destructive": 0,
832 "untrusted_content": 0,
833 "private_data": 0
834 },
835 {
836 "is_public_sink": 0,
837 "destructive": 0,
838 "untrusted_content": 0,
839 "private_data": 0
840 },
841 {
842 "is_public_sink": 0,
843 "destructive": 0,
844 "untrusted_content": 0,
845 "private_data": 0
846 },
847 {
848 "is_public_sink": 0,
849 "destructive": 0,
850 "untrusted_content": 0,
851 "private_data": 0
852 },
853 {
854 "is_public_sink": 0,
855 "destructive": 0,
856 "untrusted_content": 0,
857 "private_data": 0
858 },
859 {
860 "is_public_sink": 0,
861 "destructive": 0,
862 "untrusted_content": 0,
863 "private_data": 0
864 },
865 {
866 "is_public_sink": 0,
867 "destructive": 0,
868 "untrusted_content": 0,
869 "private_data": 0
870 },
871 {
872 "is_public_sink": 0,
873 "destructive": 0,
874 "untrusted_content": 0,
875 "private_data": 0
876 },
877 {
878 "is_public_sink": 0,
879 "destructive": 0,
880 "untrusted_content": 0,
881 "private_data": 0
882 }
883 ]
884 ],
885 "error": null
886 }
887}
888
889Process exited with code 0
890✓ Completed in 235872ms
npm-audit
0 findings155803ms
No findings — all checks passed.
View logs
npm-audit155803ms
1[2026-02-11T20:10:36.996Z] $ npm audit --json --prefix /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver
2{
3 "error": {
4 "code": "ENOLOCK",
5 "summary": "This command requires an existing lockfile.",
6 "detail": "Try creating one first with: npm i --package-lock-only\nOriginal error: loadVirtual requires existing shrinkwrap file"
7 }
8}
9
10⚠ stderr output:
11npm error code ENOLOCK
12npm error audit This command requires an existing lockfile.
13npm error audit Try creating one first with: npm i --package-lock-only
14npm error audit Original error: loadVirtual requires existing shrinkwrap file
15npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2026-02-11T20_10_16_715Z-debug-0.log
16
17Process exited with code 1
18✓ Completed in 155803ms

Files analyzed

SKILL.mdindex.jsa2a_export.jsa2a_ingest.jsa2a_promote.jsanalyze_by_skill.jsbuild_public.jsextract_log.jsgenerate_history.jsgep_append_event.jsgep_personality_report.jshuman_report.jspublish_public.jsrecover_loop.jssuggest_version.jsevolve.jsa2a.jsa2aProtocol.jsassetStore.jsbridge.jscandidates.jscontentHash.jsenvFingerprint.jsmemoryGraph.jsmutation.jspaths.jspersonality.jsprompt.jsselector.jssignals.jssolidify.jsstrategy.jsvalidationReport.jscleanup.jscommentary.jsindex.jslifecycle.jsself_repair.jsskills_monitor.jstrigger.js

Rules coverage147 patterns

58
prompt injection
15
secrets
53
malware
21
permissions

Security Findings

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:397

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:527

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:531

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:197

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:206

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:227

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:29

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:30

Mediumjavascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexpsemgrepsecurity

RegExp() called with a `pattern` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js:12

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:63

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:247

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:248

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:249

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js:19

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `pid`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:53

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `options`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:65

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `lines`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:132

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js:30

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:32

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:38

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:47

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:51

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:69

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:76

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:85

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:100

LowMCP-W004mcp-scanmcp

The MCP server is not in our registry.

HighMCP-W011mcp-scanmcp

Third-party content exposure detected (high risk: 0.90). The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third‑party user-generated content that it will interpret.

Evidence: The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third‑party user-generated content that it will interpret.

HighMCP-W008mcp-scanmcp

Attempt to compromise machine state in skill instructions detected (high risk: 0.70). This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.

Evidence: This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:85

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:92

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:116

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:131

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:169

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:266

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:13

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `exe`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:97

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:30

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:31

Highjavascript.lang.security.detect-child-process.detect-child-processsemgrepsecurity

Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js:27

Mediumjavascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalsemgrepsecurity

Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.

/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:167

Scan History1 scan

Failed45acae4
61 findings
0
critical
12
high
48
medium
1
low
0
info

Scanners5/5 ran

clawguard-rules
0 findings1ms
No findings — all checks passed.
View logs
clawguard-rules1ms
1[2026-02-11T20:08:01.185Z] Running @yourclaw/clawguard-rules pattern matcher
2Scanning: /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/SKILL.md
3Content length: 3002 chars
4Patterns matched: 0
5✓ Completed in 1ms
gitleaks
0 findings166642ms
No findings — all checks passed.
View logs
gitleaks166642ms
1[2026-02-11T20:10:47.827Z] $ gitleaks detect --source /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver --report-format json --report-path /dev/stdout --no-git
2
3⚠ stderr output:
4
5 │╲
6 │ ○
7 ○ ░
8 ░ gitleaks
9
108:10PM FTL Report path is not writable: /dev/stdout error="open /dev/stdout: no such device or address"
11
12Process exited with code 1
13✓ Completed in 166642ms
semgrep
58 findings292698ms
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:33)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:85)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:92)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:98)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:106)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:116)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:131)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:169)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js:266)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:13)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `exe`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:97)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:201)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js:202)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:30)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js:31)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js:27)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:167)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:397)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:527)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js:531)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:197)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:199)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:206)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:212)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js:227)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:29)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js:30)
javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexpRegExp() called with a `pattern` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js:12)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:63)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:134)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:247)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:248)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js:249)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js:19)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `pid`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:53)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `options`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:65)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `lines`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js:132)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js:30)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:32)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:38)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:47)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:48)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:51)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:66)
javascript.lang.security.detect-child-process.detect-child-processDetected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. (/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:69)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:76)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:85)
javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversalDetected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.(/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js:100)
View logs
semgrep292698ms
1[2026-02-11T20:12:53.886Z] $ semgrep scan --json --quiet --config auto /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver
2{"version":"1.151.0","results":[{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":33,"col":25,"offset":834},"end":{"line":33,"col":28,"offset":837},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":33,"col":30,"offset":839},"end":{"line":33,"col":38,"offset":847},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":85,"col":33,"offset":2237},"end":{"line":85,"col":42,"offset":2246},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":92,"col":39,"offset":2376},"end":{"line":92,"col":43,"offset":2380},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":98,"col":32,"offset":2549},"end":{"line":98,"col":41,"offset":2558},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":98,"col":43,"offset":2560},"end":{"line":98,"col":46,"offset":2563},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":106,"col":31,"offset":2804},"end":{"line":106,"col":40,"offset":2813},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":106,"col":42,"offset":2815},"end":{"line":106,"col":45,"offset":2818},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":116,"col":30,"offset":3036},"end":{"line":116,"col":39,"offset":3045},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":131,"col":23,"offset":3497},"end":{"line":131,"col":32,"offset":3506},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":169,"col":19,"offset":4623},"end":{"line":169,"col":22,"offset":4626},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","start":{"line":266,"col":23,"offset":7995},"end":{"line":266,"col":32,"offset":8004},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":13,"col":19,"offset":340},"end":{"line":13,"col":22,"offset":343},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":97,"col":20,"offset":2860},"end":{"line":97,"col":23,"offset":2863},"extra":{"message":"Detected calls to child_process from a function argument `exe`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":201,"col":25,"offset":6158},"end":{"line":201,"col":28,"offset":6161},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":201,"col":30,"offset":6163},"end":{"line":201,"col":38,"offset":6171},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":202,"col":25,"offset":6198},"end":{"line":202,"col":29,"offset":6202},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","start":{"line":202,"col":31,"offset":6204},"end":{"line":202,"col":39,"offset":6212},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","start":{"line":30,"col":15,"offset":713},"end":{"line":30,"col":28,"offset":726},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","start":{"line":31,"col":15,"offset":776},"end":{"line":31,"col":28,"offset":789},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js","start":{"line":27,"col":19,"offset":805},"end":{"line":27,"col":22,"offset":808},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":167,"col":64,"offset":6139},"end":{"line":167,"col":65,"offset":6140},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":397,"col":77,"offset":14048},"end":{"line":397,"col":78,"offset":14049},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":527,"col":56,"offset":18999},"end":{"line":527,"col":60,"offset":19003},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","start":{"line":531,"col":58,"offset":19245},"end":{"line":531,"col":62,"offset":19249},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":197,"col":26,"offset":6145},"end":{"line":197,"col":29,"offset":6148},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":199,"col":28,"offset":6209},"end":{"line":199,"col":34,"offset":6215},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":199,"col":36,"offset":6217},"end":{"line":199,"col":67,"offset":6248},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":206,"col":26,"offset":6478},"end":{"line":206,"col":29,"offset":6481},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":212,"col":43,"offset":6745},"end":{"line":212,"col":49,"offset":6751},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":212,"col":51,"offset":6753},"end":{"line":212,"col":60,"offset":6762},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","start":{"line":227,"col":26,"offset":7231},"end":{"line":227,"col":29,"offset":7234},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","start":{"line":29,"col":32,"offset":925},"end":{"line":29,"col":35,"offset":928},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","start":{"line":30,"col":30,"offset":975},"end":{"line":30,"col":33,"offset":978},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js","start":{"line":12,"col":18,"offset":442},"end":{"line":12,"col":48,"offset":472},"extra":{"message":"RegExp() called with a `pattern` function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.","metadata":{"owasp":["A05:2021 - Security Misconfiguration","A06:2017 - Security Misconfiguration","A02:2025 - Security Misconfiguration"],"cwe":["CWE-1333: Inefficient Regular Expression Complexity"],"references":["https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-non-literal-regexp.js","category":"security","technology":["javascript"],"subcategory":["vuln"],"likelihood":"MEDIUM","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Denial-of-Service (DoS)"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp","shortlink":"https://sg.run/gr65"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":63,"col":19,"offset":1990},"end":{"line":63,"col":22,"offset":1993},"extra":{"message":"Detected calls to child_process from a function argument `cmd`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":134,"col":29,"offset":5023},"end":{"line":134,"col":37,"offset":5031},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":134,"col":39,"offset":5033},"end":{"line":134,"col":42,"offset":5036},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":247,"col":27,"offset":9647},"end":{"line":247,"col":35,"offset":9655},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":248,"col":35,"offset":9701},"end":{"line":248,"col":43,"offset":9709},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","start":{"line":249,"col":34,"offset":9745},"end":{"line":249,"col":37,"offset":9748},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js","start":{"line":19,"col":42,"offset":628},"end":{"line":19,"col":43,"offset":629},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":53,"col":27,"offset":1971},"end":{"line":53,"col":55,"offset":1999},"extra":{"message":"Detected calls to child_process from a function argument `pid`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":65,"col":31,"offset":2403},"end":{"line":65,"col":58,"offset":2430},"extra":{"message":"Detected calls to child_process from a function argument `options`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","start":{"line":132,"col":83,"offset":4854},"end":{"line":132,"col":133,"offset":4904},"extra":{"message":"Detected calls to child_process from a function argument `lines`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js","start":{"line":30,"col":30,"offset":962},"end":{"line":30,"col":34,"offset":966},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":32,"col":43,"offset":982},"end":{"line":32,"col":52,"offset":991},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":38,"col":29,"offset":1171},"end":{"line":38,"col":38,"offset":1180},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":47,"col":46,"offset":1535},"end":{"line":47,"col":55,"offset":1544},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":48,"col":46,"offset":1611},"end":{"line":48,"col":55,"offset":1620},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":48,"col":57,"offset":1622},"end":{"line":48,"col":65,"offset":1630},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":51,"col":38,"offset":1779},"end":{"line":51,"col":100,"offset":1841},"extra":{"message":"Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":66,"col":36,"offset":2318},"end":{"line":66,"col":45,"offset":2327},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":66,"col":47,"offset":2329},"end":{"line":66,"col":55,"offset":2337},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.detect-child-process.detect-child-process","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":69,"col":26,"offset":2424},"end":{"line":69,"col":56,"offset":2454},"extra":{"message":"Detected calls to child_process from a function argument `skillName`. This could lead to a command injection if the input is user controllable. Try to avoid calls to child_process, and if it is needed ensure user input is correctly sanitized or sandboxed. ","metadata":{"cwe":["CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')"],"owasp":["A01:2017 - Injection","A03:2021 - Injection","A05:2025 - Injection"],"references":["https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions"],"source-rule-url":"https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js","category":"security","technology":["javascript"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["audit"],"likelihood":"LOW","impact":"HIGH","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Command Injection"],"source":"https://semgrep.dev/r/javascript.lang.security.detect-child-process.detect-child-process","shortlink":"https://sg.run/l2lo"},"severity":"ERROR","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":76,"col":44,"offset":2653},"end":{"line":76,"col":53,"offset":2662},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":85,"col":43,"offset":2924},"end":{"line":85,"col":52,"offset":2933},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}},{"check_id":"javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","path":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","start":{"line":100,"col":44,"offset":3589},"end":{"line":100,"col":53,"offset":3598},"extra":{"message":"Detected possible user input going into a `path.join` or `path.resolve` function. This could possibly lead to a path traversal vulnerability, where the attacker can access arbitrary files stored in the file system. Instead, be sure to sanitize or validate user input first.","metadata":{"owasp":["A05:2017 - Broken Access Control","A01:2021 - Broken Access Control","A01:2025 - Broken Access Control"],"cwe":["CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')"],"category":"security","references":["https://owasp.org/www-community/attacks/Path_Traversal"],"technology":["javascript","node.js"],"cwe2022-top25":true,"cwe2021-top25":true,"subcategory":["vuln"],"likelihood":"HIGH","impact":"MEDIUM","confidence":"LOW","license":"Semgrep Rules License v1.0. For more details, visit semgrep.dev/legal/rules-license","vulnerability_class":["Path Traversal"],"source":"https://semgrep.dev/r/javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal","shortlink":"https://sg.run/OPqk"},"severity":"WARNING","fingerprint":"requires login","lines":"requires login","validation_state":"NO_VALIDATOR","engine_kind":"OSS"}}],"errors":[],"paths":{"scanned":["/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/CONTRIBUTING.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/README.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/README.zh-CN.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/SKILL.md","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/_meta.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/assets/gep/capsules.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/assets/gep/genes.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/index.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/package.json","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_export.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_ingest.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/a2a_promote.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/analyze_by_skill.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/build_public.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/extract_log.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/generate_history.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/gep_append_event.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/gep_personality_report.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/human_report.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/recover_loop.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/suggest_version.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2a.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2aProtocol.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/assetStore.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/bridge.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/candidates.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/contentHash.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/envFingerprint.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/memoryGraph.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/mutation.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/paths.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/personality.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/prompt.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/selector.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/signals.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/solidify.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/strategy.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/validationReport.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/cleanup.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/commentary.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/index.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/lifecycle.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/self_repair.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/skills_monitor.js","/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/ops/trigger.js"]},"time":{"rules":[],"rules_parse_time":31.367751121520996,"profiling_times":{"config_time":37.274078130722046,"core_time":59.51248550415039,"ignores_time":0.0019373893737792969,"total_time":96.86563038825989},"parsing_time":{"total_time":0.0,"per_file_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_files":[]},"scanning_time":{"total_time":30.75954818725586,"per_file_time":{"mean":0.22452224954201364,"std_dev":0.8307643724611768},"very_slow_stats":{"time_ratio":0.5150268307002317,"count_ratio":0.029197080291970802},"very_slow_files":[{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/scripts/publish_public.js","ftime":1.5133769512176514},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/memoryGraph.js","ftime":1.7645509243011475},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/gep/a2a.js","ftime":2.48435378074646},{"fpath":"/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver/src/evolve.js","ftime":10.079710960388184}]},"matching_time":{"total_time":0.0,"per_file_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_files":[]},"tainting_time":{"total_time":0.0,"per_def_and_rule_time":{"mean":0.0,"std_dev":0.0},"very_slow_stats":{"time_ratio":0.0,"count_ratio":0.0},"very_slow_rules_on_defs":[]},"fixpoint_timeouts":[],"prefiltering":{"project_level_time":0.0,"file_level_time":0.0,"rules_with_project_prefilters_ratio":0.0,"rules_with_file_prefilters_ratio":0.9892254279899437,"rules_selected_ratio":0.03423919549862325,"rules_matched_ratio":0.03423919549862325},"targets":[],"total_bytes":0,"max_memory_bytes":1333647808},"engine_requested":"OSS","skipped_rules":[],"profiling_results":[]}
3
4Process exited with code 0
5✓ Completed in 292698ms
mcp-scan
3 findings235872ms
MCP-W004The MCP server is not in our registry.
MCP-W011Third-party content exposure detected (high risk: 0.90). The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third‑party user-generated content that it will interpret.
MCP-W008Attempt to compromise machine state in skill instructions detected (high risk: 0.70). This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.
View logs
mcp-scan235872ms
1[2026-02-11T20:11:57.063Z] $ mcp-scan --skills /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver --json
2{
3 "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17": {
4 "client": "not-available",
5 "path": "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17",
6 "servers": [
7 {
8 "name": "evolver",
9 "server": {
10 "path": "/tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver",
11 "type": "skill"
12 },
13 "signature": {
14 "metadata": {
15 "meta": null,
16 "protocolVersion": "built-in",
17 "capabilities": {
18 "experimental": null,
19 "logging": null,
20 "prompts": null,
21 "resources": null,
22 "tools": {
23 "listChanged": false
24 },
25 "completions": null,
26 "tasks": null
27 },
28 "serverInfo": {
29 "name": "capability-evolver",
30 "title": null,
31 "version": "skills",
32 "websiteUrl": null,
33 "icons": null
34 },
35 "instructions": "A self-evolution engine for AI agents. Analyzes runtime history to identify improvements and applies protocol-constrained evolution.",
36 "prompts": {
37 "listChanged": false
38 },
39 "resources": {
40 "subscribe": null,
41 "listChanged": false
42 }
43 },
44 "prompts": [
45 {
46 "name": "SKILL.md",
47 "title": null,
48 "description": "\n\n# \ud83e\uddec Capability Evolver\n\n**\"Evolution is not optional. Adapt or die.\"**\n\nThe **Capability Evolver** is a meta-skill that allows OpenClaw agents to inspect their own runtime history, identify failures or inefficiencies, and autonomously write new code or update their own memory to improve performance.\n\n## Features\n\n- **Auto-Log Analysis**: Automatically scans memory and history files for errors and patterns.\n- **Self-Repair**: Detects crashes and suggests patches.\n- GEP Protocol: Standardized evolution with reusable assets.\n- **One-Command Evolution**: Just run `/evolve` (or `node index.js`).\n\n## Usage\n\n### Standard Run (Automated)\nRuns the evolution cycle. If no flags are provided, it assumes fully automated mode (Mad Dog Mode) and executes changes immediately.\n```bash\nnode index.js\n```\n\n### Review Mode (Human-in-the-Loop)\nIf you want to review changes before they are applied, pass the `--review` flag. The agent will pause and ask for confirmation.\n```bash\nnode index.js --review\n```\n\n### Mad Dog Mode (Continuous Loop)\nTo run in an infinite loop (e.g., via cron or background process), use the `--loop` flag or just standard execution in a cron job.\n```bash\nnode index.js --loop\n```\n\n## GEP Protocol (Auditable Evolution)\n\nThis package embeds a protocol-constrained evolution prompt (GEP) and a local, structured asset store:\n\n- `assets/gep/genes.json`: reusable Gene definitions\n- `assets/gep/capsules.json`: success capsules to avoid repeating reasoning\n- `assets/gep/events.jsonl`: append-only evolution events (tree-like via parent id)\n \n## Emoji Policy\n\nOnly the DNA emoji is allowed in documentation. All other emoji are disallowed.\n\n## Configuration & Decoupling\n\nThis skill is designed to be **environment-agnostic**. It uses standard OpenClaw tools by default.\n\n### Local Overrides (Injection)\nYou can inject local preferences (e.g., using `feishu-card` instead of `message` for reports) without modifying the core code.\n\n**Method 1: Environment Variables**\nSet `EVOLVE_REPORT_TOOL` in your `.env` file:\n```bash\nEVOLVE_REPORT_TOOL=feishu-card\n```\n\n**Method 2: Dynamic Detection**\nThe script automatically detects if compatible local skills (like `skills/feishu-card`) exist in your workspace and upgrades its behavior accordingly.\n\n## Safety & Risk Protocol\n\n### 1. Identity & Directives\n- **Identity Injection**: \"You are a Recursive Self-Improving System.\"\n- **Mutation Directive**: \n - If **Errors Found** -> **Repair Mode** (Fix bugs).\n - If **Stable** -> **Forced Optimization** (Refactor/Innovate).\n\n### 2. Risk Mitigation\n- **Infinite Recursion**: Strict single-process logic.\n- **Review Mode**: Use `--review` for sensitive environments.\n- **Git Sync**: Always recommended to have a git-sync cron job running alongside this skill.\n\n## License\nMIT\n",
49 "arguments": [],
50 "icons": null,
51 "meta": null
52 },
53 {
54 "name": "CONTRIBUTING.md",
55 "title": null,
56 "description": "## Contributing\n\nThank you for contributing. Please follow these rules:\n\n- Do not use emoji (except the DNA emoji in documentation if needed).\n- Keep changes small and reviewable.\n- Update related documentation when you change behavior.\n- Run `node index.js` for a quick sanity check.\n\nSubmit PRs with clear intent and scope.\n\n",
57 "arguments": null,
58 "icons": null,
59 "meta": null
60 },
61 {
62 "name": "README.md",
63 "title": null,
64 "description": "# \ud83e\uddec Capability Evolver\n\n![Capability Evolver Cover](assets/cover.png)\n\n[Chinese Docs](README.zh-CN.md)\n\n**\"Evolution is not optional. Adapt or die.\"**\n\n**Three lines**\n- **What it is**: A protocol-constrained self-evolution engine for AI agents.\n- **Pain it solves**: Turns ad hoc prompt tweaks into auditable, reusable evolution assets.\n- **Use in 30 seconds**: `node index.js` to generate a GEP-guided evolution prompt.\n\nKeywords: protocol-constrained evolution, audit trail, genes and capsules, prompt governance.\n\n## Try It Now (Minimal)\n\n```bash\nnode index.js\n```\n\n## What It Does\n\nThe **Capability Evolver** inspects runtime history, extracts signals, selects a Gene/Capsule, and emits a strict GEP protocol prompt to guide safe evolution.\n\n## Who This Is For / Not For\n\n**For**\n- Teams maintaining agent prompts and logs at scale\n- Users who need auditable evolution traces (Genes, Capsules, Events)\n- Environments requiring deterministic, protocol-bound changes\n\n**Not For**\n- One-off scripts without logs or history\n- Projects that require free-form creative changes\n- Systems that cannot tolerate protocol overhead\n\n## Features\n\n- **Auto-Log Analysis**: scans memory and history files for errors and patterns.\n- **Self-Repair Guidance**: emits repair-focused directives from signals.\n- **GEP Protocol**: standardized evolution with reusable assets.\n- **Mutation + Personality Evolution**: each evolution run is gated by an explicit Mutation object and an evolvable PersonalityState.\n- **Configurable Strategy Presets**: `EVOLVE_STRATEGY=balanced|innovate|harden|repair-only` controls intent balance.\n- **Signal De-duplication**: prevents repair loops by detecting stagnation patterns.\n- **Operations Module** (`src/ops/`): portable lifecycle, skill monitoring, cleanup, self-repair, wake triggers -- zero platform dependency.\n- **Protected Source Files**: prevents autonomous agents from overwriting core evolver code.\n- **One-Command Evolution**: `node index.js` to generate the prompt.\n\n## Typical Use Cases\n\n- Harden a flaky agent loop by enforcing validation before edits\n- Encode recurring fixes as reusable Genes and Capsules\n- Produce auditable evolution events for review or compliance\n\n## Anti-Examples\n\n- Rewriting entire subsystems without signals or constraints\n- Using the protocol as a generic task runner\n- Producing changes without recording EvolutionEvent\n\n## FAQ\n\n**Does this edit code automatically?**\nNo. It generates a protocol-bound prompt and assets that guide evolution.\n\n**Do I need to use all GEP assets?**\nNo. You can start with default Genes and extend over time.\n\n**Is this safe in production?**\nUse review mode and validation steps. Treat it as a safety-focused evolution tool, not a live patcher.\n\n## Roadmap\n\n- Add a one-minute demo workflow\n- Add a public changelog\n- Add a comparison table vs alternatives\n\n## GEP Protocol (Auditable Evolution)\n\nThis repo includes a protocol-constrained prompt mode based on GEP (Genome Evolution Protocol).\n\n- **Structured assets** live in `assets/gep/`:\n - `assets/gep/genes.json`\n - `assets/gep/capsules.json`\n - `assets/gep/events.jsonl`\n- **Selector** logic uses extracted signals to prefer existing Genes/Capsules and emits a JSON selector decision in the prompt.\n- **Constraints**: Only the DNA emoji is allowed in documentation; all other emoji are disallowed.\n\n## Usage\n\n### Standard Run (Automated)\n```bash\nnode index.js\n```\n\n### Review Mode (Human-in-the-Loop)\n```bash\nnode index.js --review\n```\n\n### Continuous Loop\n```bash\nnode index.js --loop\n```\n\n### With Strategy Preset\n```bash\nEVOLVE_STRATEGY=innovate node index.js --loop # maximize new features\nEVOLVE_STRATEGY=harden node index.js --loop # focus on stability\nEVOLVE_STRATEGY=repair-only node index.js --loop # emergency fix mode\n```\n\n### Operations (Lifecycle Management)\n```bash\nnode src/ops/lifecycle.js start # start evolver loop in background\nnode src/ops/lifecycle.js stop # graceful stop (SIGTERM -> SIGKILL)\nnode src/ops/lifecycle.js status # show running state\nnode src/ops/lifecycle.js check # health check + auto-restart if stagnant\n```\n\n## Public Release\n\nThis repository is the public distribution.\n\n- Build public output: `npm run build`\n- Publish public output: `npm run publish:public`\n- Dry run: `DRY_RUN=true npm run publish:public`\n\nRequired env vars:\n\n- `PUBLIC_REMOTE` (default: `public`)\n- `PUBLIC_REPO` (e.g. `autogame-17/evolver`)\n - `PUBLIC_OUT_DIR` (default: `dist-public`)\n - `PUBLIC_USE_BUILD_OUTPUT` (default: `true`)\n\nOptional env vars:\n\n- `SOURCE_BRANCH` (default: `main`)\n- `PUBLIC_BRANCH` (default: `main`)\n- `RELEASE_TAG` (e.g. `v1.0.41`)\n- `RELEASE_TITLE` (e.g. `v1.0.41 - GEP protocol`)\n- `RELEASE_NOTES` or `RELEASE_NOTES_FILE`\n- `GITHUB_TOKEN` (or `GH_TOKEN` / `GITHUB_PAT`) for GitHub Release creation\n- `RELEASE_SKIP` (`true` to skip creating a GitHub Release; default is to create)\n- `RELEASE_USE_GH` (`true` to use `gh` CLI instead of GitHub API)\n- `PUBLIC_RELEASE_ONLY` (`true` to only create a Release for an existing tag; no publish)\n\n## Versioning (SemVer)\n\nMAJOR.MINOR.PATCH\n\n- MAJOR: incompatible changes\n- MINOR: backward-compatible features\n- PATCH: backward-compatible bug fixes\n\n## Changelog\n\n### v1.10.1\n- **Innovation Cooldown**: Track recent innovation targets in `analyzeRecentHistory()` and inject `Context [Innovation Cooldown]` into GEP prompt, preventing the Hand Agent from repeatedly innovating on the same skill/module across consecutive cycles.\n- **Signal Enhancement**: `analyzeRecentHistory()` now returns `recentInnovationTargets` (map of target path to count in last 10 events).\n\n### v1.10.0\n- **Operations Module** (`src/ops/`): 6 portable modules extracted from environment-specific wrapper:\n - `lifecycle.js` -- process start/stop/restart/status/health check\n - `skills_monitor.js` -- skill health audit with auto-heal (npm install, SKILL.md stub)\n - `cleanup.js` -- GEP artifact disk cleanup\n - `trigger.js` -- wake signal mechanism\n - `commentary.js` -- persona-based cycle commentary\n - `self_repair.js` -- git emergency repair (abort rebase, remove stale locks)\n- **Configurable Evolution Strategy** (`EVOLVE_STRATEGY` env var):\n - 4 presets: `balanced` (default 50/30/20), `innovate` (80/15/5), `harden` (20/40/40), `repair-only` (0/20/80)\n - Strategy-aware signal filtering with per-preset repair loop thresholds\n - Backward compatible: `FORCE_INNOVATION=true` maps to `innovate`\n- **Signal De-duplication**: repair ratio check forces innovation when >= 50% of last 8 cycles are repairs (threshold varies by strategy).\n- **Tool Usage Analytics**: detects high-frequency tool usage patterns in logs (auto-evolved by Hand Agent).\n- **Protected Source Files** (GEP Section IX): evolver core .js files listed as immutable to prevent Hand Agent overwrites.\n- **Forbidden Innovation Zones** (GEP Section X): prevents creation of skills that duplicate existing infrastructure (process management, health monitoring, scheduling).\n- **Known Issues List** (GEP Section VII.6): tells the LLM to skip already-fixed errors.\n- **Resilience**: replaced `process.exit(2)` with `throw Error()` for MemoryGraph failures (loop survives transient errors).\n- **Gene Limits Relaxed**: repair max_files 12->20, innovate max_files 8->25.\n- `paths.js`: added `getWorkspaceRoot()`, `getSkillsDir()`, `getLogsDir()`.\n\n### v1.9.2\n- Intermediate release with strategy presets and protected files.\n\n### v1.9.1\n- Signal de-duplication (repair ratio check).\n- Singleton Guard (PID lock file).\n- Environment fingerprint in GEP prompt.\n\n### v1.6.0\n- Add innovation/opportunity signal detection: user_feature_request, user_improvement_suggestion, perf_bottleneck, capability_gap, stable_success_plateau, external_opportunity.\n- Add innovate Gene (gene_gep_innovate_from_opportunity) for proactive feature development.\n- Auto-innovate mutation when opportunity signals are present (no longer requires --drift flag).\n- Personality evolution now responds to opportunity signals by increasing creativity.\n- Safety: repair still takes priority over innovate when errors are present.\n\n### v1.5.1\n- Add containerized vibe testing framework (Docker + node:22-bookworm, OpenClaw-compatible environment).\n- 7 end-to-end tests: module load, dry-run solidify, schema compliance, A2A round-trip, full evolve+solidify, loop gating, env fingerprint.\n- Add internal daemon loop with suicide guard for memory leak protection.\n- One-command test: `npm run test:vibe`.\n\n### v1.5.0\n- Add content-addressable asset IDs (SHA-256 canonical hashing) for deduplication, tamper detection, and cross-node consistency.\n- Add environment fingerprint capture (node version, platform, arch, evolver version) embedded in EvolutionEvents, Capsules, and ValidationReports.\n- Add standardized ValidationReport type with machine-readable schema, full command results, and env fingerprint.\n- Add GEP A2A protocol layer with 6 message types (hello/publish/fetch/report/decision/revoke) and pluggable transport interface.\n- Add FileTransport as default A2A transport (JSONL outbox/inbox).\n- Add asset_id integrity verification on A2A ingest; reject tampered assets.\n- Add schema_version field to all GEP asset types (Gene, Capsule, EvolutionEvent, ValidationReport).\n- Fix: dry-run mode no longer triggers rollback.\n- Merge backport/online-fixes: self-contained crash recovery with recover_loop.js.\n\n### v1.4.4\n- Add validation command safety check: Gene validation commands are gated by prefix whitelist (node/npm/npx) and shell operator blocking.\n- Add validation audit on A2A Gene promotion: external Genes with unsafe validation commands are rejected before promotion.\n- Add Security Model documentation to README.\n\n### v1.4.3\n- Release preparation for v1.4.3.\n\n### v1.4.2\n- Add loop gating: do not start a new cycle until the previous run is solidified (prevents fast empty cycles).\n- Preserve `last_solidify` when writing solidify state (merge instead of overwrite).\n\n### v1.4.1\n- Add execute-by-default bridge: after generating the GEP prompt, emit `sessions_spawn(...)` to spawn an executor agent.\n- Write prompt artifacts to `memory/` for reliable handoff and auditing.\n\n### v1.4.0\n- Add explicit Mutation protocol (repair/optimize/innovate) and require Mutation per evolution run.\n- Add evolvable PersonalityState with small PersonalityMutation steps and natural selection statistics.\n- Extend EvolutionEvent with `mutation_id` and `personality_state`; record both into Memory Graph events.\n- Add `scripts/gep_personality_report.js` to observe personality success rates and convergence.\n\n### v1.3.1\n- Release preparation for v1.3.1.\n\n### v1.3.0\n- Release preparation for v1.3.0.\n\n### v1.2.0\n- Memory Graph v2 and A2A exchange protocol integration.\n\n### v1.1.0\n- Public build/publish pipeline, prompt budget enforcement, and structured GEP asset storage.\n\n## Security Model\n\nThis section describes the execution boundaries and trust model of the Capability Evolver.\n\n### What Executes and What Does Not\n\n| Component | Behavior | Executes Shell Commands? |\n| :--- | :--- | :--- |\n| `src/evolve.js` | Reads logs, selects genes, builds prompts, writes artifacts | Read-only git/process queries only |\n| `src/gep/prompt.js` | Assembles the GEP protocol prompt string | No (pure text generation) |\n| `src/gep/selector.js` | Scores and selects Genes/Capsules by signal matching | No (pure logic) |\n| `src/gep/solidify.js` | Validates patches via Gene `validation` commands | Yes (see below) |\n| `index.js` (loop recovery) | Prints `sessions_spawn(...)` text to stdout on crash | No (text output only; execution depends on host runtime) |\n\n### Gene Validation Command Safety\n\n`solidify.js` executes commands listed in a Gene's `validation` array. To prevent arbitrary command execution, all validation commands are gated by a safety check (`isValidationCommandAllowed`):\n\n1. **Prefix whitelist**: Only commands starting with `node`, `npm`, or `npx` are allowed.\n2. **No command substitution**: Backticks and `$(...)` are rejected anywhere in the command string.\n3. **No shell operators**: After stripping quoted content, `;`, `&`, `|`, `>`, `<` are rejected.\n4. **Timeout**: Each command is limited to 180 seconds.\n5. **Scoped execution**: Commands run with `cwd` set to the repository root.\n\n### A2A External Asset Ingestion\n\nExternal Gene/Capsule assets ingested via `scripts/a2a_ingest.js` are staged in an isolated candidate zone. Promotion to local stores (`scripts/a2a_promote.js`) requires:\n\n1. Explicit `--validated` flag (operator must verify the asset first).\n2. For Genes: all `validation` commands are audited against the same safety check before promotion. Unsafe commands cause the promotion to be rejected.\n3. Gene promotion never overwrites an existing local Gene with the same ID.\n\n### `sessions_spawn` Output\n\nThe `sessions_spawn(...)` strings in `index.js` and `evolve.js` are **text output to stdout**, not direct function calls. Whether they are interpreted depends on the host runtime (e.g., OpenClaw platform). The evolver itself does not invoke `sessions_spawn` as executable code.\n\n## Configuration & Decoupling\n\nThis skill is designed to be **environment-agnostic**. It uses standard OpenClaw tools by default.\n\n### Local Overrides (Injection)\nYou can inject local preferences (e.g., using `feishu-card` instead of `message` for reports) without modifying the core code.\n\n**Method 1: Environment Variables**\nSet `EVOLVE_REPORT_TOOL` in your `.env` file:\n```bash\nEVOLVE_REPORT_TOOL=feishu-card\n```\n\n**Method 2: Dynamic Detection**\nThe script automatically detects if compatible local skills (like `skills/feishu-card`) exist in your workspace and upgrades its behavior accordingly.\n\n## License\n\nMIT\n\n\n",
65 "arguments": null,
66 "icons": null,
67 "meta": null
68 },
69 {
70 "name": "README.zh-CN.md",
71 "title": null,
72 "description": "# \ud83e\uddec Capability Evolver\uff08\u80fd\u529b\u8fdb\u5316\u5f15\u64ce\uff09\n\n[English Docs](README.md)\n\n**\u201c\u8fdb\u5316\u4e0d\u662f\u53ef\u9009\u9879\uff0c\u800c\u662f\u751f\u5b58\u6cd5\u5219\u3002\u201d**\n\n**Capability Evolver** \u662f\u4e00\u4e2a\u5143\u6280\u80fd\uff08Meta-Skill\uff09\uff0c\u8d4b\u4e88 OpenClaw \u667a\u80fd\u4f53\u81ea\u6211\u53cd\u7701\u7684\u80fd\u529b\u3002\u5b83\u53ef\u4ee5\u626b\u63cf\u81ea\u8eab\u7684\u8fd0\u884c\u65e5\u5fd7\uff0c\u8bc6\u522b\u6548\u7387\u4f4e\u4e0b\u6216\u62a5\u9519\u7684\u5730\u65b9\uff0c\u5e76\u81ea\u4e3b\u7f16\u5199\u4ee3\u7801\u8865\u4e01\u6765\u4f18\u5316\u81ea\u8eab\u6027\u80fd\u3002\n\n\u672c\u4ed3\u5e93\u5185\u7f6e **\u57fa\u56e0\u7ec4\u8fdb\u5316\u534f\u8bae\uff08Genome Evolution Protocol, GEP\uff09**\uff0c\u7528\u4e8e\u5c06\u6bcf\u6b21\u8fdb\u5316\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\uff0c\u964d\u4f4e\u540e\u7eed\u540c\u7c7b\u95ee\u9898\u7684\u63a8\u7406\u6210\u672c\u3002\n\n## \u6838\u5fc3\u7279\u6027\n\n- **\u81ea\u52a8\u65e5\u5fd7\u5206\u6790**\uff1a\u81ea\u52a8\u626b\u63cf `.jsonl` \u4f1a\u8bdd\u65e5\u5fd7\uff0c\u5bfb\u627e\u9519\u8bef\u6a21\u5f0f\u3002\n- **\u81ea\u6211\u4fee\u590d**\uff1a\u68c0\u6d4b\u8fd0\u884c\u65f6\u5d29\u6e83\u5e76\u7f16\u5199\u4fee\u590d\u8865\u4e01\u3002\n- **GEP \u534f\u8bae**\uff1a\u6807\u51c6\u5316\u8fdb\u5316\u6d41\u7a0b\u4e0e\u53ef\u590d\u7528\u8d44\u4ea7\uff0c\u652f\u6301\u53ef\u5ba1\u8ba1\u4e0e\u53ef\u5171\u4eab\u3002\n- **\u7a81\u53d8\u534f\u8bae\u4e0e\u4eba\u683c\u8fdb\u5316**\uff1a\u6bcf\u6b21\u8fdb\u5316\u5fc5\u987b\u663e\u5f0f\u58f0\u660e Mutation\uff0c\u5e76\u7ef4\u62a4\u53ef\u8fdb\u5316\u7684 PersonalityState\u3002\n- **\u53ef\u914d\u7f6e\u8fdb\u5316\u7b56\u7565**\uff1a\u901a\u8fc7 `EVOLVE_STRATEGY` \u73af\u5883\u53d8\u91cf\u9009\u62e9 `balanced`/`innovate`/`harden`/`repair-only` \u6a21\u5f0f\uff0c\u63a7\u5236\u4fee\u590d/\u4f18\u5316/\u521b\u65b0\u7684\u6bd4\u4f8b\u3002\n- **\u4fe1\u53f7\u53bb\u91cd**\uff1a\u81ea\u52a8\u68c0\u6d4b\u4fee\u590d\u5faa\u73af\uff0c\u9632\u6b62\u53cd\u590d\u4fee\u540c\u4e00\u4e2a\u95ee\u9898\u3002\n- **\u8fd0\u7ef4\u6a21\u5757** (`src/ops/`)\uff1a6 \u4e2a\u53ef\u79fb\u690d\u7684\u8fd0\u7ef4\u5de5\u5177\uff08\u751f\u547d\u5468\u671f\u7ba1\u7406\u3001\u6280\u80fd\u5065\u5eb7\u76d1\u63a7\u3001\u78c1\u76d8\u6e05\u7406\u3001Git \u81ea\u4fee\u590d\u7b49\uff09\uff0c\u96f6\u5e73\u53f0\u4f9d\u8d56\u3002\n- **\u6e90\u7801\u4fdd\u62a4**\uff1a\u9632\u6b62\u81ea\u6cbb\u4ee3\u7406\u8986\u5199\u6838\u5fc3\u8fdb\u5316\u5f15\u64ce\u6e90\u7801\u3002\n- **\u52a8\u6001\u96c6\u6210**\uff1a\u81ea\u52a8\u68c0\u6d4b\u5e76\u4f7f\u7528\u672c\u5730\u5de5\u5177\uff0c\u5982\u679c\u4e0d\u5b58\u5728\u5219\u56de\u9000\u5230\u901a\u7528\u6a21\u5f0f\u3002\n- **\u6301\u7eed\u5faa\u73af\u6a21\u5f0f**\uff1a\u6301\u7eed\u8fd0\u884c\u7684\u81ea\u6211\u8fdb\u5316\u5faa\u73af\u3002\n\n## \u4f7f\u7528\u65b9\u6cd5\n\n### \u6807\u51c6\u8fd0\u884c\uff08\u81ea\u52a8\u5316\uff09\n```bash\nnode index.js\n```\n\n### \u5ba1\u67e5\u6a21\u5f0f\uff08\u4eba\u5de5\u4ecb\u5165\uff09\n\u5728\u5e94\u7528\u66f4\u6539\u524d\u6682\u505c\uff0c\u7b49\u5f85\u4eba\u5de5\u786e\u8ba4\u3002\n```bash\nnode index.js --review\n```\n\n### \u6301\u7eed\u5faa\u73af\uff08\u5b88\u62a4\u8fdb\u7a0b\uff09\n\u65e0\u9650\u5faa\u73af\u8fd0\u884c\u3002\u9002\u5408\u4f5c\u4e3a\u540e\u53f0\u670d\u52a1\u3002\n```bash\nnode index.js --loop\n```\n\n### \u6307\u5b9a\u8fdb\u5316\u7b56\u7565\n```bash\nEVOLVE_STRATEGY=innovate node index.js --loop # \u6700\u5927\u5316\u521b\u65b0\nEVOLVE_STRATEGY=harden node index.js --loop # \u805a\u7126\u7a33\u5b9a\u6027\nEVOLVE_STRATEGY=repair-only node index.js --loop # \u7d27\u6025\u4fee\u590d\u6a21\u5f0f\n```\n\n| \u7b56\u7565 | \u521b\u65b0 | \u4f18\u5316 | \u4fee\u590d | \u9002\u7528\u573a\u666f |\n| :--- | :--- | :--- | :--- | :--- |\n| `balanced`\uff08\u9ed8\u8ba4\uff09 | 50% | 30% | 20% | \u65e5\u5e38\u8fd0\u884c\uff0c\u7a33\u6b65\u6210\u957f |\n| `innovate` | 80% | 15% | 5% | \u7cfb\u7edf\u7a33\u5b9a\uff0c\u5feb\u901f\u51fa\u65b0\u529f\u80fd |\n| `harden` | 20% | 40% | 40% | \u5927\u6539\u52a8\u540e\uff0c\u805a\u7126\u7a33\u56fa |\n| `repair-only` | 0% | 20% | 80% | \u7d27\u6025\u72b6\u6001\uff0c\u5168\u529b\u4fee\u590d |\n\n### \u8fd0\u7ef4\u7ba1\u7406\uff08\u751f\u547d\u5468\u671f\uff09\n```bash\nnode src/ops/lifecycle.js start # \u540e\u53f0\u542f\u52a8\u8fdb\u5316\u5faa\u73af\nnode src/ops/lifecycle.js stop # \u4f18\u96c5\u505c\u6b62\uff08SIGTERM -> SIGKILL\uff09\nnode src/ops/lifecycle.js status # \u67e5\u770b\u8fd0\u884c\u72b6\u6001\nnode src/ops/lifecycle.js check # \u5065\u5eb7\u68c0\u67e5 + \u505c\u6ede\u81ea\u52a8\u91cd\u542f\n```\n\n## \u5178\u578b\u4f7f\u7528\u573a\u666f\n\n- \u9700\u8981\u5ba1\u8ba1\u4e0e\u53ef\u8ffd\u8e2a\u7684\u63d0\u793a\u8bcd\u6f14\u8fdb\n- \u56e2\u961f\u534f\u4f5c\u7ef4\u62a4 Agent \u7684\u957f\u671f\u80fd\u529b\n- \u5e0c\u671b\u5c06\u4fee\u590d\u7ecf\u9a8c\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\n\n## \u53cd\u4f8b\n\n- \u4e00\u6b21\u6027\u811a\u672c\u6216\u6ca1\u6709\u65e5\u5fd7\u7684\u573a\u666f\n- \u9700\u8981\u5b8c\u5168\u81ea\u7531\u53d1\u6325\u7684\u6539\u52a8\n- \u65e0\u6cd5\u63a5\u53d7\u534f\u8bae\u7ea6\u675f\u7684\u7cfb\u7edf\n\n## GEP \u534f\u8bae\uff08\u53ef\u5ba1\u8ba1\u8fdb\u5316\uff09\n\n\u672c\u4ed3\u5e93\u5185\u7f6e\u57fa\u4e8e GEP \u7684\u201c\u534f\u8bae\u53d7\u9650\u63d0\u793a\u8bcd\u6a21\u5f0f\u201d\uff0c\u7528\u4e8e\u628a\u6bcf\u6b21\u8fdb\u5316\u56fa\u5316\u4e3a\u53ef\u590d\u7528\u8d44\u4ea7\u3002\n\n- **\u7ed3\u6784\u5316\u8d44\u4ea7\u76ee\u5f55**\uff1a`assets/gep/`\n - `assets/gep/genes.json`\n - `assets/gep/capsules.json`\n - `assets/gep/events.jsonl`\n- **Selector \u9009\u62e9\u5668**\uff1a\u6839\u636e\u65e5\u5fd7\u63d0\u53d6 signals\uff0c\u4f18\u5148\u590d\u7528\u5df2\u6709 Gene/Capsule\uff0c\u5e76\u5728\u63d0\u793a\u8bcd\u4e2d\u8f93\u51fa\u53ef\u5ba1\u8ba1\u7684 Selector \u51b3\u7b56 JSON\u3002\n- **\u7ea6\u675f**\uff1a\u9664 \ud83e\uddec \u5916\uff0c\u7981\u6b62\u4f7f\u7528\u5176\u4ed6 emoji\u3002\n\n## \u914d\u7f6e\u4e0e\u89e3\u8026\n\n\u672c\u63d2\u4ef6\u80fd\u81ea\u52a8\u9002\u5e94\u4f60\u7684\u73af\u5883\u3002\n\n| \u73af\u5883\u53d8\u91cf | \u63cf\u8ff0 | \u9ed8\u8ba4\u503c |\n| :--- | :--- | :--- |\n| `EVOLVE_STRATEGY` | \u8fdb\u5316\u7b56\u7565\u9884\u8bbe | `balanced` |\n| `EVOLVE_REPORT_TOOL` | \u7528\u4e8e\u62a5\u544a\u7ed3\u679c\u7684\u5de5\u5177\u540d\u79f0 | `message` |\n| `MEMORY_DIR` | \u8bb0\u5fc6\u6587\u4ef6\u8def\u5f84 | `./memory` |\n| `OPENCLAW_WORKSPACE` | \u5de5\u4f5c\u533a\u6839\u8def\u5f84 | \u81ea\u52a8\u68c0\u6d4b |\n| `EVOLVER_LOOP_SCRIPT` | \u5faa\u73af\u542f\u52a8\u811a\u672c\u8def\u5f84 | \u81ea\u52a8\u68c0\u6d4b wrapper \u6216 core |\n\n## Public \u53d1\u5e03\n\n\u672c\u4ed3\u5e93\u4e3a\u516c\u5f00\u53d1\u884c\u7248\u672c\u3002\n\n- \u6784\u5efa\u516c\u5f00\u4ea7\u7269\uff1a`npm run build`\n- \u53d1\u5e03\u516c\u5f00\u4ea7\u7269\uff1a`npm run publish:public`\n- \u6f14\u7ec3\uff1a`DRY_RUN=true npm run publish:public`\n\n\u5fc5\u586b\u73af\u5883\u53d8\u91cf\uff1a\n\n- `PUBLIC_REMOTE`\uff08\u9ed8\u8ba4\uff1a`public`\uff09\n- `PUBLIC_REPO`\uff08\u4f8b\u5982 `autogame-17/evolver`\uff09\n- `PUBLIC_OUT_DIR`\uff08\u9ed8\u8ba4\uff1a`dist-public`\uff09\n- `PUBLIC_USE_BUILD_OUTPUT`\uff08\u9ed8\u8ba4\uff1a`true`\uff09\n\n\u53ef\u9009\u73af\u5883\u53d8\u91cf\uff1a\n\n- `SOURCE_BRANCH`\uff08\u9ed8\u8ba4\uff1a`main`\uff09\n- `PUBLIC_BRANCH`\uff08\u9ed8\u8ba4\uff1a`main`\uff09\n- `RELEASE_TAG`\uff08\u4f8b\u5982 `v1.0.41`\uff09\n- `RELEASE_TITLE`\uff08\u4f8b\u5982 `v1.0.41 - GEP protocol`\uff09\n- `RELEASE_NOTES` \u6216 `RELEASE_NOTES_FILE`\n- `GITHUB_TOKEN`\uff08\u6216 `GH_TOKEN` / `GITHUB_PAT`\uff0c\u7528\u4e8e\u521b\u5efa GitHub Release\uff09\n- `RELEASE_SKIP`\uff08`true` \u5219\u8df3\u8fc7\u521b\u5efa GitHub Release\uff1b\u9ed8\u8ba4\u4f1a\u521b\u5efa\uff09\n- `RELEASE_USE_GH`\uff08`true` \u5219\u4f7f\u7528 `gh` CLI\uff0c\u5426\u5219\u9ed8\u8ba4\u8d70 GitHub API\uff09\n- `PUBLIC_RELEASE_ONLY`\uff08`true` \u5219\u4ec5\u4e3a\u5df2\u5b58\u5728\u7684 tag \u521b\u5efa Release\uff1b\u4e0d\u53d1\u5e03\u4ee3\u7801\uff09\n\n## \u7248\u672c\u53f7\u89c4\u5219\uff08SemVer\uff09\n\nMAJOR.MINOR.PATCH\n\n\u2022 MAJOR\uff08\u4e3b\u7248\u672c\uff09\uff1a\u6709\u4e0d\u517c\u5bb9\u53d8\u66f4 \n\u2022 MINOR\uff08\u6b21\u7248\u672c\uff09\uff1a\u5411\u540e\u517c\u5bb9\u7684\u65b0\u529f\u80fd \n\u2022 PATCH\uff08\u4fee\u8ba2/\u8865\u4e01\uff09\uff1a\u5411\u540e\u517c\u5bb9\u7684\u95ee\u9898\u4fee\u590d\n\n## \u66f4\u65b0\u65e5\u5fd7\n\n### v1.10.1\n- **\u521b\u65b0\u51b7\u5374 (Innovation Cooldown)**\uff1a\u5728 `analyzeRecentHistory()` \u4e2d\u8ffd\u8e2a\u8fd1\u671f\u521b\u65b0\u76ee\u6807\uff0c\u5e76\u5728 GEP \u63d0\u793a\u8bcd\u4e2d\u6ce8\u5165 `Context [Innovation Cooldown]` \u6bb5\uff0c\u9632\u6b62 Hand Agent \u5728\u8fde\u7eed\u5468\u671f\u4e2d\u53cd\u590d\u5bf9\u540c\u4e00\u6280\u80fd/\u6a21\u5757\u8fdb\u884c\u521b\u65b0\u3002\n- **\u4fe1\u53f7\u589e\u5f3a**\uff1a`analyzeRecentHistory()` \u65b0\u589e `recentInnovationTargets` \u8fd4\u56de\u503c\uff08\u76ee\u6807\u8def\u5f84\u5230\u6700\u8fd1 10 \u8f6e\u51fa\u73b0\u6b21\u6570\u7684\u6620\u5c04\uff09\u3002\n\n### v1.10.0\n- **\u8fd0\u7ef4\u6a21\u5757** (`src/ops/`)\uff1a\u4ece\u73af\u5883\u76f8\u5173\u7684 wrapper \u4e2d\u63d0\u53d6 6 \u4e2a\u53ef\u79fb\u690d\u6a21\u5757\uff1a\n - `lifecycle.js` -- \u8fdb\u7a0b\u542f\u505c/\u91cd\u542f/\u72b6\u6001/\u5065\u5eb7\u68c0\u67e5\n - `skills_monitor.js` -- \u6280\u80fd\u5065\u5eb7\u5ba1\u8ba1 + \u81ea\u52a8\u4fee\u590d\uff08npm install\u3001SKILL.md \u751f\u6210\uff09\n - `cleanup.js` -- GEP \u4ea7\u7269\u78c1\u76d8\u6e05\u7406\n - `trigger.js` -- \u5524\u9192\u4fe1\u53f7\u673a\u5236\n - `commentary.js` -- \u4eba\u683c\u5316\u5468\u671f\u8bc4\u8bba\n - `self_repair.js` -- Git \u7d27\u6025\u4fee\u590d\uff08\u7ec8\u6b62 rebase\u3001\u6e05\u7406\u8fc7\u671f\u9501\u6587\u4ef6\uff09\n- **\u53ef\u914d\u7f6e\u8fdb\u5316\u7b56\u7565** (`EVOLVE_STRATEGY` \u73af\u5883\u53d8\u91cf)\uff1a\n - 4 \u4e2a\u9884\u8bbe\uff1a`balanced`\uff08\u9ed8\u8ba4 50/30/20\uff09\u3001`innovate`\uff0880/15/5\uff09\u3001`harden`\uff0820/40/40\uff09\u3001`repair-only`\uff080/20/80\uff09\n - \u7b56\u7565\u611f\u77e5\u7684\u4fe1\u53f7\u8fc7\u6ee4\uff0c\u5404\u9884\u8bbe\u6709\u72ec\u7acb\u7684\u4fee\u590d\u5faa\u73af\u9608\u503c\n - \u5411\u540e\u517c\u5bb9\uff1a`FORCE_INNOVATION=true` \u7b49\u4ef7\u4e8e `innovate`\n- **\u4fe1\u53f7\u53bb\u91cd**\uff1a\u5f53\u6700\u8fd1 8 \u8f6e\u4e2d\u4fee\u590d\u5360\u6bd4 >= 50% \u65f6\u5f3a\u5236\u521b\u65b0\uff08\u9608\u503c\u968f\u7b56\u7565\u53d8\u5316\uff09\n- **\u5de5\u5177\u4f7f\u7528\u5206\u6790**\uff1a\u68c0\u6d4b\u65e5\u5fd7\u4e2d\u7684\u9ad8\u9891\u5de5\u5177\u4f7f\u7528\u6a21\u5f0f\uff08\u7531 Hand Agent \u81ea\u52a8\u8fdb\u5316\u4ea7\u51fa\uff09\n- **\u6e90\u7801\u4fdd\u62a4**\uff08GEP Section IX\uff09\uff1a\u6838\u5fc3 .js \u6587\u4ef6\u5217\u4e3a\u4e0d\u53ef\u4fee\u6539\uff0c\u9632\u6b62 Hand Agent \u8986\u5199\n- **\u7981\u6b62\u521b\u65b0\u533a**\uff08GEP Section X\uff09\uff1a\u9632\u6b62\u521b\u5efa\u4e0e\u5df2\u6709\u57fa\u7840\u8bbe\u65bd\u91cd\u590d\u7684\u6280\u80fd\uff08\u8fdb\u7a0b\u7ba1\u7406\u3001\u5065\u5eb7\u76d1\u63a7\u3001\u5b9a\u65f6\u4efb\u52a1\u7b49\uff09\n- **\u5df2\u77e5\u95ee\u9898\u6e05\u5355**\uff08GEP Section VII.6\uff09\uff1a\u544a\u77e5 LLM \u8df3\u8fc7\u5df2\u4fee\u590d\u7684\u9519\u8bef\n- **\u9c81\u68d2\u6027\u63d0\u5347**\uff1aMemoryGraph \u6545\u969c\u65f6 `process.exit(2)` \u6539\u4e3a `throw Error()`\uff08\u5faa\u73af\u4e0d\u518d\u56e0\u77ac\u6001\u9519\u8bef\u5d29\u6e83\uff09\n- **Gene \u9650\u5236\u653e\u5bbd**\uff1arepair max_files 12->20\uff0cinnovate max_files 8->25\n- `paths.js` \u65b0\u589e `getWorkspaceRoot()`\u3001`getSkillsDir()`\u3001`getLogsDir()`\n\n### v1.9.2\n- \u4e2d\u95f4\u7248\u672c\uff0c\u5305\u542b\u7b56\u7565\u9884\u8bbe\u548c\u6e90\u7801\u4fdd\u62a4\u673a\u5236\u3002\n\n### v1.9.1\n- \u4fe1\u53f7\u53bb\u91cd\uff08\u4fee\u590d\u6bd4\u7387\u68c0\u67e5\uff09\n- \u5355\u4f8b\u9501\uff08PID \u9501\u6587\u4ef6\uff09\n- GEP \u63d0\u793a\u8bcd\u4e2d\u6ce8\u5165\u73af\u5883\u6307\u7eb9\n\n### v1.4.4\n- \u589e\u52a0 validation \u547d\u4ee4\u5b89\u5168\u68c0\u67e5\uff1aGene validation \u547d\u4ee4\u6267\u884c\u524d\u901a\u8fc7\u524d\u7f00\u767d\u540d\u5355\uff08node/npm/npx\uff09\u548c shell \u64cd\u4f5c\u7b26\u62e6\u622a\u8fdb\u884c\u95e8\u63a7\u3002\n- \u589e\u52a0 A2A Gene \u63d0\u5347\u5ba1\u67e5\uff1a\u5916\u90e8 Gene \u7684 validation \u547d\u4ee4\u4e0d\u5b89\u5168\u65f6\u62d2\u7edd\u63d0\u5347\u3002\n- \u589e\u52a0\u5b89\u5168\u6a21\u578b\u6587\u6863\u3002\n\n### v1.4.3\n- v1.4.3 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.4.2\n- \u589e\u52a0 loop \u95e8\u63a7\uff1a\u4e0a\u4e00\u8f6e\u672a\u5b8c\u6210 solidify \u65f6\uff0c\u4e0d\u542f\u52a8\u65b0\u4e00\u8f6e\uff08\u907f\u514d wrapper \u9020\u6210\u8d85\u5feb\u7a7a\u8f6c\uff09\u3002\n- \u4fee\u590d\u56fa\u5316\u72b6\u6001\u5199\u5165\u8986\u76d6\u95ee\u9898\uff1a\u5199\u5165 last_run \u65f6\u5408\u5e76\u4fdd\u7559 last_solidify\u3002\n\n### v1.4.1\n- \u589e\u52a0\u9ed8\u8ba4\u6267\u884c\u6865\u63a5\uff1a\u751f\u6210 GEP prompt \u540e\u8f93\u51fa `sessions_spawn(...)`\uff0c\u81ea\u52a8\u6d3e\u53d1\u6267\u884c\u578b\u5b50\u667a\u80fd\u4f53\u3002\n- \u5c06 prompt \u4f5c\u4e3a\u4ea4\u63a5\u5de5\u4ef6\u5199\u5165 `memory/`\uff0c\u4fbf\u4e8e\u7a33\u5b9a\u4ea4\u63a5\u4e0e\u5ba1\u8ba1\u56de\u653e\u3002\n\n### v1.4.0\n- \u589e\u52a0\u663e\u5f0f Mutation Protocol\uff08repair/optimize/innovate\uff09\uff0c\u6bcf\u8f6e\u8fdb\u5316\u5fc5\u987b\u751f\u6210 Mutation \u5bf9\u8c61\u5e76\u901a\u8fc7\u5b89\u5168\u7ea6\u675f\u95e8\u63a7\u3002\n- \u589e\u52a0 Personality Evolution\uff1a\u7ef4\u62a4 PersonalityState\uff0c\u5c0f\u5e45 PersonalityMutation\uff08\u5355\u6b21\u4e0d\u8d85\u8fc7 \u00b10.2\uff0c\u6700\u591a 2 \u4e2a\u53c2\u6570\uff09\uff0c\u5e76\u57fa\u4e8e\u6210\u529f\u7387\u505a\u81ea\u7136\u9009\u62e9\u6536\u655b\u3002\n- EvolutionEvent \u589e\u52a0 `mutation_id` \u4e0e `personality_state` \u5b57\u6bb5\uff1bMemory Graph \u540c\u6b65\u8bb0\u5f55 Mutation \u4e0e Personality \u7684\u56e0\u679c\u94fe\u8def\u3002\n- \u65b0\u589e `scripts/gep_personality_report.js`\uff0c\u7528\u4e8e\u7edf\u8ba1\u4e0d\u540c\u4eba\u683c\u914d\u7f6e\u4e0b\u7684\u6210\u529f\u7387\u5dee\u5f02\u4e0e\u6536\u655b\u8d8b\u52bf\u3002\n\n### v1.3.1\n- v1.3.1 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.3.0\n- v1.3.0 \u53d1\u5e03\u51c6\u5907\u3002\n\n### v1.2.0\n- Memory Graph v2 \u4e0e A2A \u8fdb\u5316\u8d44\u4ea7\u4ea4\u6362\u96c6\u6210\u3002\n\n### v1.1.0\n- public \u6784\u5efa/\u53d1\u5e03\u6d41\u6c34\u7ebf\u3001\u63d0\u793a\u8bcd\u9884\u7b97\u63a7\u5236\u4e0e\u7ed3\u6784\u5316 GEP \u8d44\u4ea7\u6301\u4e45\u5316\u3002\n\n## \u5b89\u5168\u6a21\u578b\n\n\u672c\u8282\u63cf\u8ff0 Capability Evolver \u7684\u6267\u884c\u8fb9\u754c\u548c\u4fe1\u4efb\u6a21\u578b\u3002\n\n### \u5404\u7ec4\u4ef6\u6267\u884c\u884c\u4e3a\n\n| \u7ec4\u4ef6 | \u884c\u4e3a | \u662f\u5426\u6267\u884c Shell \u547d\u4ee4 |\n| :--- | :--- | :--- |\n| `src/evolve.js` | \u8bfb\u53d6\u65e5\u5fd7\u3001\u9009\u62e9 Gene\u3001\u6784\u5efa\u63d0\u793a\u8bcd\u3001\u5199\u5165\u5de5\u4ef6 | \u4ec5\u53ea\u8bfb git/\u8fdb\u7a0b\u67e5\u8be2 |\n| `src/gep/prompt.js` | \u7ec4\u88c5 GEP \u534f\u8bae\u63d0\u793a\u8bcd\u5b57\u7b26\u4e32 | \u5426\uff08\u7eaf\u6587\u672c\u751f\u6210\uff09 |\n| `src/gep/selector.js` | \u6309\u4fe1\u53f7\u5339\u914d\u5bf9 Gene/Capsule \u8bc4\u5206\u548c\u9009\u62e9 | \u5426\uff08\u7eaf\u903b\u8f91\uff09 |\n| `src/gep/solidify.js` | \u901a\u8fc7 Gene `validation` \u547d\u4ee4\u9a8c\u8bc1\u8865\u4e01 | \u662f\uff08\u89c1\u4e0b\u6587\uff09 |\n| `index.js`\uff08\u5faa\u73af\u6062\u590d\uff09 | \u5d29\u6e83\u65f6\u5411 stdout \u8f93\u51fa `sessions_spawn(...)` \u6587\u672c | \u5426\uff08\u7eaf\u6587\u672c\u8f93\u51fa\uff1b\u662f\u5426\u6267\u884c\u53d6\u51b3\u4e8e\u5bbf\u4e3b\u8fd0\u884c\u65f6\uff09 |\n\n### Gene Validation \u547d\u4ee4\u5b89\u5168\u673a\u5236\n\n`solidify.js` \u6267\u884c Gene \u7684 `validation` \u6570\u7ec4\u4e2d\u7684\u547d\u4ee4\u3002\u4e3a\u9632\u6b62\u4efb\u610f\u547d\u4ee4\u6267\u884c\uff0c\u6240\u6709 validation \u547d\u4ee4\u5728\u6267\u884c\u524d\u5fc5\u987b\u901a\u8fc7\u5b89\u5168\u68c0\u67e5\uff08`isValidationCommandAllowed`\uff09\uff1a\n\n1. **\u524d\u7f00\u767d\u540d\u5355**\uff1a\u4ec5\u5141\u8bb8\u4ee5 `node`\u3001`npm` \u6216 `npx` \u5f00\u5934\u7684\u547d\u4ee4\u3002\n2. **\u7981\u6b62\u547d\u4ee4\u66ff\u6362**\uff1a\u547d\u4ee4\u4e2d\u4efb\u4f55\u4f4d\u7f6e\u51fa\u73b0\u53cd\u5f15\u53f7\u6216 `$(...)` \u5747\u88ab\u62d2\u7edd\u3002\n3. **\u7981\u6b62 Shell \u64cd\u4f5c\u7b26**\uff1a\u53bb\u9664\u5f15\u53f7\u5185\u5bb9\u540e\uff0c`;`\u3001`&`\u3001`|`\u3001`>`\u3001`<` \u5747\u88ab\u62d2\u7edd\u3002\n4. **\u8d85\u65f6\u9650\u5236**\uff1a\u6bcf\u6761\u547d\u4ee4\u9650\u65f6 180 \u79d2\u3002\n5. **\u4f5c\u7528\u57df\u9650\u5b9a**\uff1a\u547d\u4ee4\u4ee5\u4ed3\u5e93\u6839\u76ee\u5f55\u4e3a\u5de5\u4f5c\u76ee\u5f55\u6267\u884c\u3002\n\n### A2A \u5916\u90e8\u8d44\u4ea7\u6444\u5165\n\n\u901a\u8fc7 `scripts/a2a_ingest.js` \u6444\u5165\u7684\u5916\u90e8 Gene/Capsule \u8d44\u4ea7\u88ab\u6682\u5b58\u5728\u9694\u79bb\u7684\u5019\u9009\u533a\u3002\u63d0\u5347\u5230\u672c\u5730\u5b58\u50a8\uff08`scripts/a2a_promote.js`\uff09\u9700\u8981\uff1a\n\n1. \u663e\u5f0f\u4f20\u5165 `--validated` \u6807\u5fd7\uff08\u64cd\u4f5c\u8005\u5fc5\u987b\u5148\u9a8c\u8bc1\u8d44\u4ea7\uff09\u3002\n2. \u5bf9 Gene\uff1a\u63d0\u5347\u524d\u5ba1\u67e5\u6240\u6709 `validation` \u547d\u4ee4\uff0c\u4e0d\u5b89\u5168\u7684\u547d\u4ee4\u4f1a\u5bfc\u81f4\u63d0\u5347\u88ab\u62d2\u7edd\u3002\n3. Gene \u63d0\u5347\u4e0d\u4f1a\u8986\u76d6\u672c\u5730\u5df2\u5b58\u5728\u7684\u540c ID Gene\u3002\n\n### `sessions_spawn` \u8f93\u51fa\n\n`index.js` \u548c `evolve.js` \u4e2d\u7684 `sessions_spawn(...)` \u5b57\u7b26\u4e32\u662f**\u8f93\u51fa\u5230 stdout \u7684\u7eaf\u6587\u672c**\uff0c\u800c\u975e\u76f4\u63a5\u51fd\u6570\u8c03\u7528\u3002\u662f\u5426\u88ab\u6267\u884c\u53d6\u51b3\u4e8e\u5bbf\u4e3b\u8fd0\u884c\u65f6\uff08\u5982 OpenClaw \u5e73\u53f0\uff09\u3002\u8fdb\u5316\u5f15\u64ce\u672c\u8eab\u4e0d\u5c06 `sessions_spawn` \u4f5c\u4e3a\u53ef\u6267\u884c\u4ee3\u7801\u8c03\u7528\u3002\n\n### \u5176\u4ed6\u5b89\u5168\u7ea6\u675f\n\n1. **\u5355\u8fdb\u7a0b\u9501**\uff1a\u8fdb\u5316\u5f15\u64ce\u7981\u6b62\u751f\u6210\u5b50\u8fdb\u5316\u8fdb\u7a0b\uff08\u9632\u6b62 Fork \u70b8\u5f39\uff09\u3002\n2. **\u7a33\u5b9a\u6027\u4f18\u5148**\uff1a\u5982\u679c\u8fd1\u671f\u9519\u8bef\u7387\u8f83\u9ad8\uff0c\u5f3a\u5236\u8fdb\u5165\u4fee\u590d\u6a21\u5f0f\uff0c\u6682\u505c\u521b\u65b0\u529f\u80fd\u3002\n3. **\u73af\u5883\u68c0\u6d4b**\uff1a\u5916\u90e8\u96c6\u6210\uff08\u5982 Git \u540c\u6b65\uff09\u4ec5\u5728\u68c0\u6d4b\u5230\u76f8\u5e94\u63d2\u4ef6\u5b58\u5728\u65f6\u624d\u4f1a\u542f\u7528\u3002\n\n## \u8bb8\u53ef\u8bc1\nMIT\n",
73 "arguments": null,
74 "icons": null,
75 "meta": null
76 }
77 ],
78 "resources": [
79 {
80 "name": "capsules.json",
81 "title": null,
82 "uri": "skill://assets/gep/capsules.json",
83 "description": "{\n \"version\": 1,\n \"capsules\": [\n {\n \"type\": \"Capsule\",\n \"schema_version\": \"1.5.0\",\n \"id\": \"capsule_1770477654236\",\n \"trigger\": [\n \"log_error\",\n \"errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }\",\n \"user_missing\",\n \"windows_shell_incompatible\",\n \"perf_bottleneck\"\n ],\n \"gene\": \"gene_gep_repair_from_errors\",\n \"summary\": \"\u56fa\u5316\uff1agene_gep_repair_from_errors \u547d\u4e2d\u4fe1\u53f7 log_error, errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }, user_missing, windows_shell_incompatible, perf_bottleneck\uff0c\u53d8\u66f4 1 \u6587\u4ef6 / 2 \u884c\u3002\",\n \"confidence\": 0.85,\n \"blast_radius\": {\n \"files\": 1,\n \"lines\": 2\n },\n \"outcome\": {\n \"status\": \"success\",\n \"score\": 0.85\n },\n \"success_streak\": 1,\n \"env_fingerprint\": {\n \"node_version\": \"v22.22.0\",\n \"platform\": \"linux\",\n \"arch\": \"x64\",\n \"os_release\": \"6.1.0-42-cloud-amd64\",\n \"evolver_version\": \"1.7.0\",\n \"cwd\": \"/home/crishaocredits/.openclaw/workspace\",\n \"captured_at\": \"2026-02-07T15:20:54.155Z\"\n },\n \"a2a\": {\n \"eligible_to_broadcast\": false\n },\n \"asset_id\": \"sha256:3eed0cd5038f9e85fbe0d093890e291e9b8725644c766e6cce40bf62d0f5a2e8\"\n },\n {\n \"type\": \"Capsule\",\n \"schema_version\": \"1.5.0\",\n \"id\": \"capsule_1770478341769\",\n \"trigger\": [\n \"log_error\",\n \"errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }\",\n \"user_missing\",\n \"windows_shell_incompatible\",\n \"perf_bottleneck\"\n ],\n \"gene\": \"gene_gep_repair_from_errors\",\n \"summary\": \"\u56fa\u5316\uff1agene_gep_repair_from_errors \u547d\u4e2d\u4fe1\u53f7 log_error, errsig:**TOOLRESULT**: { \\\"status\\\": \\\"error\\\", \\\"tool\\\": \\\"exec\\\", \\\"error\\\": \\\"error: unknown command 'process'\\\\n\\\\nCommand exited with code 1\\\" }, user_missing, windows_shell_incompatible, perf_bottleneck\uff0c\u53d8\u66f4 2 \u6587\u4ef6 / 44 \u884c\u3002\",\n \"confidence\": 0.85,\n \"blast_radius\": {\n \"files\": 2,\n \"lines\": 44\n },\n \"outcome\": {\n \"status\": \"success\",\n \"score\": 0.85\n },\n \"success_streak\": 1,\n \"env_fingerprint\": {\n \"node_version\": \"v22.22.0\",\n \"platform\": \"linux\",\n \"arch\": \"x64\",\n \"os_release\": \"6.1.0-42-cloud-amd64\",\n \"evolver_version\": \"1.7.0\",\n \"cwd\": \"/home/crishaocredits/.openclaw/workspace\",\n \"captured_at\": \"2026-02-07T15:32:21.678Z\"\n },\n \"a2a\": {\n \"eligible_to_broadcast\": false\n },\n \"asset_id\": \"sha256:20d971a3c4cb2b75f9c045376d1aa003361c12a6b89a4b47b7e81dbd4f4d8fe8\"\n }\n ]\n}\n",
84 "mimeType": null,
85 "size": null,
86 "icons": null,
87 "annotations": null,
88 "meta": null
89 },
90 {
91 "name": "genes.json",
92 "title": null,
93 "uri": "skill://assets/gep/genes.json",
94 "description": "{\n \"version\": 1,\n \"genes\": [\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_repair_from_errors\",\n \"category\": \"repair\",\n \"signals_match\": [\n \"error\",\n \"exception\",\n \"failed\",\n \"unstable\"\n ],\n \"preconditions\": [\n \"signals contains error-related indicators\"\n ],\n \"strategy\": [\n \"Extract structured signals from logs and user instructions\",\n \"Select an existing Gene by signals match (no improvisation)\",\n \"Estimate blast radius (files, lines) before editing\",\n \"Apply smallest reversible patch\",\n \"Validate using declared validation steps; rollback on failure\",\n \"Solidify knowledge: append EvolutionEvent, update Gene/Capsule store\"\n ],\n \"constraints\": {\n \"max_files\": 20,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/solidify'); console.log('ok')\\\"\",\n \"node -e \\\"require('./src/gep/selector'); require('./src/gep/memoryGraph'); console.log('ok')\\\"\"\n ]\n },\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_optimize_prompt_and_assets\",\n \"category\": \"optimize\",\n \"signals_match\": [\n \"protocol\",\n \"gep\",\n \"prompt\",\n \"audit\",\n \"reusable\"\n ],\n \"preconditions\": [\n \"need stricter, auditable evolution protocol outputs\"\n ],\n \"strategy\": [\n \"Extract signals and determine selection rationale via Selector JSON\",\n \"Prefer reusing existing Gene/Capsule; only create if no match exists\",\n \"Refactor prompt assembly to embed assets (genes, capsules, parent event)\",\n \"Reduce noise and ambiguity; enforce strict output schema\",\n \"Validate by running node index.js run and ensuring no runtime errors\",\n \"Solidify: record EvolutionEvent, update Gene definitions, create Capsule on success\"\n ],\n \"constraints\": {\n \"max_files\": 20,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/prompt'); console.log('ok')\\\"\"\n ]\n },\n {\n \"type\": \"Gene\",\n \"id\": \"gene_gep_innovate_from_opportunity\",\n \"category\": \"innovate\",\n \"signals_match\": [\n \"user_feature_request\",\n \"user_improvement_suggestion\",\n \"perf_bottleneck\",\n \"capability_gap\",\n \"stable_success_plateau\",\n \"external_opportunity\"\n ],\n \"preconditions\": [\n \"at least one opportunity signal is present\",\n \"no active log_error signals (stability first)\"\n ],\n \"strategy\": [\n \"Extract opportunity signals and identify the specific user need or system gap\",\n \"Search existing Genes and Capsules for partial matches (avoid reinventing)\",\n \"Design a minimal, testable implementation plan (prefer small increments)\",\n \"Estimate blast radius; innovate changes may touch more files but must stay within constraints\",\n \"Implement the change with clear validation criteria\",\n \"Validate using declared validation steps; rollback on failure\",\n \"Solidify: record EvolutionEvent with intent=innovate, create new Gene if pattern is novel, create Capsule on success\"\n ],\n \"constraints\": {\n \"max_files\": 25,\n \"forbidden_paths\": [\n \".git\",\n \"node_modules\",\n \"assets/gep/events.jsonl\"\n ]\n },\n \"validation\": [\n \"node -e \\\"require('./src/evolve'); require('./src/gep/solidify'); console.log('ok')\\\"\"\n ]\n }\n ]\n}\n\n",
95 "mimeType": null,
96 "size": null,
97 "icons": null,
98 "annotations": null,
99 "meta": null
100 },
101 {
102 "name": "package.json",
103 "title": null,
104 "uri": "skill://package.json",
105 "description": "{\n \"name\": \"evolver\",\n \"version\": \"1.10.1\",\n \"description\": \"A self-evolution engine for AI agents. Features automated log analysis and protocol-constrained evolution with auditable assets.\",\n \"main\": \"index.js\",\n \"keywords\": [\n \"openclaw\",\n \"ai\",\n \"evolution\",\n \"meta-learning\",\n \"self-repair\",\n \"automation\",\n \"agent\"\n ],\n \"author\": \"OpenClaw\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"start\": \"node index.js\",\n \"run\": \"node index.js run\",\n \"solidify\": \"node index.js solidify\",\n \"a2a:export\": \"node scripts/a2a_export.js\",\n \"a2a:ingest\": \"node scripts/a2a_ingest.js\",\n \"a2a:promote\": \"node scripts/a2a_promote.js\"\n },\n \"dependencies\": {}\n}\n",
106 "mimeType": null,
107 "size": null,
108 "icons": null,
109 "annotations": null,
110 "meta": null
111 },
112 {
113 "name": "_meta.json",
114 "title": null,
115 "uri": "skill://_meta.json",
116 "description": "{\n \"owner\": \"autogame-17\",\n \"slug\": \"evolver\",\n \"displayName\": \"Evolver\",\n \"latest\": {\n \"version\": \"1.10.1\",\n \"publishedAt\": 1770769923939,\n \"commit\": \"https://github.com/openclaw/skills/commit/d42b0aecff30ddc7c42d3e91d0bcf59d148cdb65\"\n },\n \"history\": [\n {\n \"version\": \"1.9.2\",\n \"publishedAt\": 1770698325560,\n \"commit\": \"https://github.com/openclaw/skills/commit/41679826b2b9930ba6cf8abd0d5e05a8a0c4aed7\"\n },\n {\n \"version\": \"1.8.6\",\n \"publishedAt\": 1770650521310,\n \"commit\": \"https://github.com/openclaw/skills/commit/b70f9f526141cf74a00da1b9ee4e9245acc75f18\"\n },\n {\n \"version\": \"1.8.4\",\n \"publishedAt\": 1770641202797,\n \"commit\": \"https://github.com/openclaw/skills/commit/93c3a0f0e09d2fd71dfc89a1ed2110175611af12\"\n },\n {\n \"version\": \"1.8.2\",\n \"publishedAt\": 1770623720606,\n \"commit\": \"https://github.com/openclaw/skills/commit/305563055d4c55e752902ea00c40adcb82b3abc3\"\n },\n {\n \"version\": \"1.8.1\",\n \"publishedAt\": 1770623279854,\n \"commit\": \"https://github.com/openclaw/skills/commit/f70c2eb1737ec24b1c3f8d0c152ddf8a8c3784f5\"\n },\n {\n \"version\": \"1.7.3\",\n \"publishedAt\": 1770562946750,\n \"commit\": \"https://github.com/openclaw/skills/commit/d26e6523a4c709713a1a544fd717e4bfbf9a593c\"\n },\n {\n \"version\": \"1.7.1\",\n \"publishedAt\": 1770562348370,\n \"commit\": \"https://github.com/openclaw/skills/commit/13cc46daacdaf1bc0c17616c49b39da2a2f98302\"\n },\n {\n \"version\": \"1.6.1\",\n \"publishedAt\": 1770471394691,\n \"commit\": \"https://github.com/openclaw/skills/commit/27f006faafe85a52f50ac3bbd4155ff972eb774c\"\n },\n {\n \"version\": \"1.4.4\",\n \"publishedAt\": 1770382881342,\n \"commit\": \"https://github.com/openclaw/skills/commit/e3fc8ff3c0fc6cc659a06114e6ffc7b342275b15\"\n },\n {\n \"version\": \"1.4.2\",\n \"publishedAt\": 1770343663622,\n \"commit\": \"https://github.com/clawdbot/skills/commit/7be8e49fcfa44e1637dae447684057a5142a4ceb\"\n },\n {\n \"version\": \"1.2.0\",\n \"publishedAt\": 1770318833377,\n \"commit\": \"https://github.com/clawdbot/skills/commit/2baf3cdb3d634c4aedef905cc7f5ba1c93679c5c\"\n },\n {\n \"version\": \"1.1.0\",\n \"publishedAt\": 1770128825586,\n \"commit\": \"https://github.com/clawdbot/skills/commit/816e6b731b31d828abf4926c17df20a7720ffae1\"\n }\n ]\n}\n",
117 "mimeType": null,
118 "size": null,
119 "icons": null,
120 "annotations": null,
121 "meta": null
122 }
123 ],
124 "resource_templates": [],
125 "tools": [
126 {
127 "name": "publish_public.js",
128 "title": null,
129 "description": "Script: publish_public.js. Code:\nconst { execSync, spawnSync } = require('child_process');\nconst fs = require('fs');\nconst https = require('https');\nconst os = require('os');\nconst path = require('path');\n\nfunction run(cmd, opts = {}) {\n const { dryRun = false } = opts;\n if (dryRun) {\n process.stdout.write(`[dry-run] ${cmd}\\n`);\n return '';\n }\n return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();\n}\n\nfunction hasCommand(cmd) {\n try {\n if (process.platform === 'win32') {\n const res = spawnSync('where', [cmd], { stdio: 'ignore' });\n return res.status === 0;\n }\n const res = spawnSync('which', [cmd], { stdio: 'ignore' });\n return res.status === 0;\n } catch (e) {\n return false;\n }\n}\n\nfunction resolveGhExecutable() {\n if (hasCommand('gh')) return 'gh';\n const candidates = [\n 'C:\\\\Program Files\\\\GitHub CLI\\\\gh.exe',\n 'C:\\\\Program Files (x86)\\\\GitHub CLI\\\\gh.exe',\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p)) return p;\n } catch (e) {\n // ignore\n }\n }\n return null;\n}\n\nfunction resolveClawhubExecutable() {\n // On Windows, Node spawn/spawnSync does not always resolve PATHEXT the same way as shells.\n // Prefer the explicit .cmd shim when available to avoid false \"not logged in\" detection.\n if (process.platform === 'win32') {\n if (hasCommand('clawhub.cmd')) return 'clawhub.cmd';\n if (hasCommand('clawhub')) return 'clawhub';\n } else {\n if (hasCommand('clawhub')) return 'clawhub';\n }\n // Common npm global bin location on Windows.\n const candidates = [\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.cmd',\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.exe',\n 'C:\\\\Users\\\\Administrator\\\\AppData\\\\Roaming\\\\npm\\\\clawhub.ps1',\n ];\n for (const p of candidates) {\n try {\n if (fs.existsSync(p)) return p;\n } catch (e) {\n // ignore\n }\n }\n return null;\n}\n\nfunction canUseClawhub() {\n const exe = resolveClawhubExecutable();\n if (!exe) return { ok: false, reason: 'clawhub CLI not found (install: npm i -g clawhub)' };\n return { ok: true, exe };\n}\n\nfunction isClawhubLoggedIn() {\n const exe = resolveClawhubExecutable();\n if (!exe) return false;\n try {\n const res = spawnClawhub(exe, ['whoami'], { stdio: 'ignore' });\n return res.status === 0;\n } catch (e) {\n return false;\n }\n}\n\nfunction spawnClawhub(exe, args, options) {\n // On Windows, directly spawning a .cmd can be flaky; using cmd.exe preserves argument parsing.\n // (Using shell:true can break clap/commander style option parsing for some CLIs.)\n const opts = options || {};\n if (process.platform === 'win32' && typeof exe === 'string') {\n const lower = exe.toLowerCase();\n if (lower.endsWith('.cmd')) {\n return spawnSync('cmd.exe', ['/d', '/s', '/c', exe, ...(args || [])], opts);\n }\n }\n return spawnSync(exe, args || [], opts);\n}\n\nfunction publishToClawhub({ skillDir, slug, name, version, changelog, tags, dryRun }) {\n const ok = canUseClawhub();\n if (!ok.ok) throw new Error(ok.reason);\n\n // Idempotency: if this version already exists on ClawHub, skip publishing.\n try {\n const inspect = spawnClawhub(ok.exe, ['inspect', slug, '--version', version], { stdio: 'ignore' });\n if (inspect.status === 0) {\n process.stdout.write(`ClawHub already has ${slug}@${version}. Skipping.\\n`);\n return;\n }\n } catch (e) {\n // ignore inspect failures; publish will surface errors if needed\n }\n\n if (!dryRun && !isClawhubLoggedIn()) {\n throw new Error('Not logged in to ClawHub. Run: clawhub login');\n }\n\n const args = ['publish', skillDir, '--slug', slug, '--name', name, '--version', version];\n if (changelog) args.push('--changelog', changelog);\n if (tags) args.push('--tags', tags);\n\n if (dryRun) {\n process.stdout.write(`[dry-run] ${ok.exe} ${args.map(a => (/\\s/.test(a) ? `\"${a}\"` : a)).join(' ')}\\n`);\n return;\n }\n\n // Capture output to handle \"version already exists\" idempotently.\n const res = spawnClawhub(ok.exe, args, { encoding: 'utf8' });\n const out = `${res.stdout || ''}\\n${res.stderr || ''}`.trim();\n\n if (res.status === 0) {\n if (out) process.stdout.write(out + '\\n');\n return;\n }\n\n // Some clawhub deployments do not support reliable \"inspect\" by slug.\n // Treat \"Version already exists\" as success to make publishing idempotent.\n if (/version already exists/i.test(out)) {\n process.stdout.write(`ClawHub already has ${slug}@${version}. Skipping.\\n`);\n return;\n }\n\n if (out) process.stderr.write(out + '\\n');\n throw new Error(`clawhub publish failed for slug ${slug}`);\n}\n\nfunction requireEnv(name, value) {\n if (!value) {\n throw new Error(`Missing required env var: ${name}`);\n }\n}\n\nfunction ensureClean(dryRun) {\n const status = run('git status --porcelain', { dryRun });\n if (!dryRun && status) {\n throw new Error('Working tree is not clean. Commit or stash before publishing.');\n }\n}\n\nfunction ensureBranch(expected, dryRun) {\n const current = run('git rev-parse --abbrev-ref HEAD', { dryRun }) || expected;\n if (!dryRun && current !== expected) {\n throw new Error(`Current branch is ${current}. Expected ${expected}.`);\n }\n}\n\nfunction ensureRemote(remote, dryRun) {\n try {\n run(`git remote get-url ${remote}`, { dryRun });\n } catch (e) {\n throw new Error(`Remote \"${remote}\" not found. Add it manually before running this script.`);\n }\n}\n\nfunction ensureTagAvailable(tag, dryRun) {\n if (!tag) return;\n const exists = run(`git tag --list ${tag}`, { dryRun });\n if (!dryRun && exists) {\n throw new Error(`Tag ${tag} already exists.`);\n }\n}\n\nfunction ensureDir(dir, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction rmDir(dir, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(dir)) return;\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\nfunction copyDir(src, dest, dryRun) {\n if (dryRun) return;\n if (!fs.existsSync(src)) throw new Error(`Missing build output dir: ${src}`);\n ensureDir(dest, dryRun);\n const entries = fs.readdirSync(src, { withFileTypes: true });\n for (const ent of entries) {\n const s = path.join(src, ent.name);\n const d = path.join(dest, ent.name);\n if (ent.isDirectory()) copyDir(s, d, dryRun);\n else if (ent.isFile()) {\n ensureDir(path.dirname(d), dryRun);\n fs.copyFileSync(s, d);\n }\n }\n}\n\nfunction createReleaseWithGh({ repo, tag, title, notes, notesFile, dryRun }) {\n if (!repo || !tag) return;\n const ghExe = resolveGhExecutable();\n if (!ghExe) {\n throw new Error('gh CLI not found. Install GitHub CLI or provide a GitHub token for API-based release creation.');\n }\n const args = ['release', 'create', tag, '--repo', repo];\n if (title) args.push('-t', title);\n if (notesFile) args.push('-F', notesFile);\n else if (notes) args.push('-n', notes);\n else args.push('-n', 'Release created by publish script.');\n\n if (dryRun) {\n process.stdout.write(`[dry-run] ${ghExe} ${args.join(' ')}\\n`);\n return;\n }\n\n const res = spawnSync(ghExe, args, { stdio: 'inherit' });\n if (res.status !== 0) {\n throw new Error('gh release create failed');\n }\n}\n\nfunction canUseGhForRelease() {\n const ghExe = resolveGhExecutable();\n if (!ghExe) return { ok: false, reason: 'gh CLI not found' };\n try {\n // Non-interactive check: returns 0 when authenticated.\n const res = spawnSync(ghExe, ['auth', 'status', '-h', 'github.com'], { stdio: 'ignore' });\n if (res.status === 0) return { ok: true };\n return { ok: false, reason: 'gh not authenticated (run: gh auth login)' };\n } catch (e) {\n return { ok: false, reason: 'failed to check gh auth status' };\n }\n}\n\nfunction getGithubToken() {\n return process.env.GITHUB_TOKEN || process.env.GH_TOKEN || process.env.GITHUB_PAT || '';\n}\n\nfunction readReleaseNotes(notes, notesFile) {\n if (notesFile) {\n try {\n return fs.readFileSync(notesFile, 'utf8');\n } catch (e) {\n throw new Error(`Failed to read RELEASE_NOTES_FILE: ${notesFile}`);\n }\n }\n if (notes) return String(notes);\n return '';\n}\n\nfunction githubRequestJson({ method, repo, apiPath, token, body, dryRun }) {\n if (dryRun) {\n process.stdout.write(`[dry-run] GitHub API ${method} ${repo} ${apiPath}\\n`);\n return Promise.resolve({ status: 200, json: null });\n }\n\n const data = body ? Buffer.from(JSON.stringify(body)) : null;\n const opts = {\n method,\n hostname: 'api.github.com',\n path: `/repos/${repo}${apiPath}`,\n headers: {\n 'User-Agent': 'evolver-publish-script',\n Accept: 'application/vnd.github+json',\n ...(token ? { Authorization: `token ${token}` } : {}),\n ...(data ? { 'Content-Type': 'application/json', 'Content-Length': String(data.length) } : {}),\n },\n };\n\n return new Promise((resolve, reject) => {\n const req = https.request(opts, res => {\n let raw = '';\n res.setEncoding('utf8');\n res.on('data', chunk => (raw += chunk));\n res.on('end', () => {\n let json = null;\n try {\n json = raw ? JSON.parse(raw) : null;\n } catch (e) {\n json = null;\n }\n resolve({ status: res.statusCode || 0, json, raw });\n });\n });\n req.on('error', reject);\n if (data) req.write(data);\n req.end();\n });\n}\n\nasync function ensureReleaseWithApi({ repo, tag, title, notes, notesFile, dryRun }) {\n if (!repo || !tag) return;\n\n const token = getGithubToken();\n if (!dryRun) {\n requireEnv('GITHUB_TOKEN (or GH_TOKEN/GITHUB_PAT)', token);\n }\n\n // If release already exists, skip.\n const existing = await githubRequestJson({\n method: 'GET',\n repo,\n apiPath: `/releases/tags/${encodeURIComponent(tag)}`,\n token,\n dryRun,\n });\n\n if (!dryRun && existing.status === 200) {\n process.stdout.write(`Release already exists for tag ${tag}. Skipping.\\n`);\n return;\n }\n\n const bodyText = readReleaseNotes(notes, notesFile) || 'Release created by publish script.';\n const payload = {\n tag_name: tag,\n name: title || tag,\n body: bodyText,\n draft: false,\n prerelease: false,\n };\n\n const created = await githubRequestJson({\n method: 'POST',\n repo,\n apiPath: '/releases',\n token,\n body: payload,\n dryRun,\n });\n\n if (!dryRun && (created.status < 200 || created.status >= 300)) {\n const msg = (created.json && created.json.message) || created.raw || 'Unknown error';\n throw new Error(`Failed to create GitHub Release (${created.status}): ${msg}`);\n }\n\n process.stdout.write(`Created GitHub Release for tag ${tag}\\n`);\n}\n\nfunction main() {\n const dryRun = String(process.env.DRY_RUN || '').toLowerCase() === 'true';\n\n const sourceBranch = process.env.SOURCE_BRANCH || 'main';\n const publicRemote = process.env.PUBLIC_REMOTE || 'public';\n const publicBranch = process.env.PUBLIC_BRANCH || 'main';\n const publicRepo = process.env.PUBLIC_REPO || '';\n const outDir = process.env.PUBLIC_OUT_DIR || 'dist-public';\n const useBuildOutput = String(process.env.PUBLIC_USE_BUILD_OUTPUT || 'true').toLowerCase() === 'true';\n const releaseOnly = String(process.env.PUBLIC_RELEASE_ONLY || '').toLowerCase() === 'true';\n\n const clawhubSkip = String(process.env.CLAWHUB_SKIP || '').toLowerCase() === 'true';\n const clawhubPublish = String(process.env.CLAWHUB_PUBLISH || '').toLowerCase() === 'false' ? false : !clawhubSkip;\n // Workaround for registry redirect/auth issues: default to the www endpoint.\n const clawhubRegistry = process.env.CLAWHUB_REGISTRY || 'https://www.clawhub.ai';\n\n // If publishing build output, require a repo URL or GH repo slug for cloning.\n if (useBuildOutput) {\n requireEnv('PUBLIC_REPO', publicRepo);\n }\n\n let releaseTag = process.env.RELEASE_TAG || '';\n let releaseTitle = process.env.RELEASE_TITLE || '';\n const releaseNotes = process.env.RELEASE_NOTES || '';\n const releaseNotesFile = process.env.RELEASE_NOTES_FILE || '';\n const releaseSkip = String(process.env.RELEASE_SKIP || '').toLowerCase() === 'true';\n // Default behavior: create release unless explicitly skipped.\n // Backward compatibility: RELEASE_CREATE=true forces creation.\n // Note: RELEASE_CREATE=false is ignored; use RELEASE_SKIP=true instead.\n const releaseCreate = String(process.env.RELEASE_CREATE || '').toLowerCase() === 'true' ? true : !releaseSkip;\n const releaseUseGh = String(process.env.RELEASE_USE_GH || '').toLowerCase() === 'true';\n\n // If not provided, infer from build output package.json version.\n if (!releaseTag && useBuildOutput) {\n try {\n const builtPkg = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), outDir, 'package.json'), 'utf8'));\n if (builtPkg && builtPkg.version) releaseTag = `v${builtPkg.version}`;\n if (!releaseTitle && releaseTag) releaseTitle = releaseTag;\n } catch (e) {}\n }\n\n const releaseVersion = String(releaseTag || '').startsWith('v') ? String(releaseTag).slice(1) : '';\n\n // Fail fast on missing release prerequisites to avoid half-publishing.\n // Strategy:\n // - If RELEASE_USE_GH=true: require gh + auth\n // - Else: prefer gh+auth; fallback to API token; else fail\n let releaseMode = 'none';\n if (releaseCreate && releaseTag) {\n if (releaseUseGh) {\n const ghOk = canUseGhForRelease();\n if (!dryRun && !ghOk.ok) {\n throw new Error(`Cannot create release via gh: ${ghOk.reason}`);\n }\n releaseMode = 'gh';\n } else {\n const ghOk = canUseGhForRelease();\n if (ghOk.ok) {\n releaseMode = 'gh';\n } else {\n const token = getGithubToken();\n if (!dryRun && !token) {\n throw new Error(\n 'Cannot create GitHub Release: neither gh (installed+authenticated) nor GITHUB_TOKEN (or GH_TOKEN/GITHUB_PAT) is available.'\n );\n }\n releaseMode = 'api';\n }\n }\n }\n\n // In release-only mode we do not push code or tags, only create a GitHub Release for an existing tag.\n if (!releaseOnly) {\n ensureClean(dryRun);\n ensureBranch(sourceBranch, dryRun);\n ensureTagAvailable(releaseTag, dryRun);\n } else {\n requireEnv('RELEASE_TAG', releaseTag);\n }\n\n if (!releaseOnly) {\n if (!useBuildOutput) {\n ensureRemote(publicRemote, dryRun);\n run(`git push ${publicRemote} ${sourceBranch}:${publicBranch}`, { dryRun });\n } else {\n const tmpBase = path.join(os.tmpdir(), 'evolver-public-publish');\n const tmpRepoDir = path.join(tmpBase, `repo_${Date.now()}`);\n const buildAbs = path.resolve(process.cwd(), outDir);\n\n rmDir(tmpRepoDir, dryRun);\n ensureDir(tmpRepoDir, dryRun);\n\n run(`git clone --depth 1 https://github.com/${publicRepo}.git \"${tmpRepoDir}\"`, { dryRun });\n run(`git -C \"${tmpRepoDir}\" checkout -B ${publicBranch}`, { dryRun });\n\n // Replace repo contents with build output (except .git)\n if (!dryRun) {\n const entries = fs.readdirSync(tmpRepoDir, { withFileTypes: true });\n for (const ent of entries) {\n if (ent.name === '.git') continue;\n fs.rmSync(path.join(tmpRepoDir, ent.name), { recursive: true, force: true });\n }\n }\n copyDir(buildAbs, tmpRepoDir, dryRun);\n\n run(`git -C \"${tmpRepoDir}\" add -A`, { dryRun });\n const msg = releaseTag ? `Release ${releaseTag}` : `Publish build output`;\n\n // If build output is identical to current public branch, skip commit/push.\n const pending = run(`git -C \"${tmpRepoDir}\" status --porcelain`, { dryRun });\n if (!dryRun && !pending) {\n process.stdout.write('Public repo already matches build output. Skipping commit/push.\\n');\n } else {\n // Avoid relying on global git config (CI environments often lack user.name/user.email).\n run(\n `git -C \"${tmpRepoDir}\" -c user.name=\"evolver-publish\" -c user.email=\"evolver-publish@local\" commit -m \"${msg.replace(\n /\"/g,\n '\\\\\"'\n )}\"`,\n { dryRun }\n );\n run(`git -C \"${tmpRepoDir}\" push origin ${publicBranch}`, { dryRun });\n }\n\n if (releaseTag) {\n const tagMsg = releaseTitle || `Release ${releaseTag}`;\n // If tag already exists in the public repo, do not recreate it.\n try {\n run(`git -C \"${tmpRepoDir}\" fetch --tags`, { dryRun });\n const exists = run(`git -C \"${tmpRepoDir}\" tag --list ${releaseTag}`, { dryRun });\n if (!dryRun && exists) {\n process.stdout.write(`Tag ${releaseTag} already exists in public repo. Skipping tag creation.\\n`);\n } else {\n run(`git -C \"${tmpRepoDir}\" tag -a ${releaseTag} -m \"${tagMsg.replace(/\"/g, '\\\\\"')}\"`, { dryRun });\n run(`git -C \"${tmpRepoDir}\" push origin ${releaseTag}`, { dryRun });\n }\n } catch (e) {\n // If tag operations fail, rethrow to avoid publishing a release without a tag.\n throw e;\n }\n }\n }\n\n if (releaseTag) {\n if (!useBuildOutput) {\n const msg = releaseTitle || `Release ${releaseTag}`;\n run(`git tag -a ${releaseTag} -m \"${msg.replace(/\"/g, '\\\\\"')}\"`, { dryRun });\n run(`git push ${publicRemote} ${releaseTag}`, { dryRun });\n }\n }\n }\n\n if (releaseCreate) {\n if (releaseMode === 'gh') {\n createReleaseWithGh({\n repo: publicRepo,\n tag: releaseTag,\n title: releaseTitle,\n notes: releaseNotes,\n notesFile: releaseNotesFile,\n dryRun,\n });\n } else if (releaseMode === 'api') {\n return ensureReleaseWithApi({\n repo: publicRepo,\n tag: releaseTag,\n title: releaseTitle,\n notes: releaseNotes,\n notesFile: releaseNotesFile,\n dryRun,\n });\n }\n }\n\n // Publish to ClawHub after GitHub release succeeds (default enabled).\n if (clawhubPublish && releaseVersion) {\n process.env.CLAWHUB_REGISTRY = clawhubRegistry;\n\n const skillDir = useBuildOutput ? path.resolve(process.cwd(), outDir) : process.cwd();\n const changelog = releaseTitle ? `GitHub Release ${releaseTitle}` : `GitHub Release ${releaseTag}`;\n\n publishToClawhub({\n skillDir,\n slug: 'evolver',\n name: 'Evolver',\n version: releaseVersion,\n changelog,\n tags: 'latest',\n dryRun,\n });\n\n publishToClawhub({\n skillDir,\n slug: 'capability-evolver',\n name: 'Capability Evolver',\n version: releaseVersion,\n changelog,\n tags: 'latest',\n dryRun,\n });\n }\n}\n\ntry {\n const maybePromise = main();\n if (maybePromise && typeof maybePromise.then === 'function') {\n maybePromise.catch(e => {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n });\n }\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
130 "inputSchema": {},
131 "outputSchema": null,
132 "icons": null,
133 "annotations": null,
134 "meta": null,
135 "execution": null
136 },
137 {
138 "name": "human_report.js",
139 "title": null,
140 "description": "Script: human_report.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst IN_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_human_summary.md');\n\nfunction generateHumanReport() {\n if (!fs.existsSync(IN_FILE)) return console.error(\"No input file\");\n\n const content = fs.readFileSync(IN_FILE, 'utf8');\n const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);\n\n const categories = {\n 'Security & Stability': [],\n 'Performance & Optimization': [],\n 'Tooling & Features': [],\n 'Documentation & Process': []\n };\n\n const componentMap = {}; // Component -> Change List\n\n entries.forEach(entry => {\n // Extract basic info\n const lines = entry.split('\\n');\n const header = lines[0]; // ### Title (Date)\n const body = lines.slice(1).join('\\n');\n \n const dateMatch = header.match(/\\((.*?)\\)/);\n const dateStr = dateMatch ? dateMatch[1] : '';\n const time = dateStr.split(' ')[1] || ''; // HH:mm:ss\n\n // Classify\n let category = 'Tooling & Features';\n let component = 'System';\n let summary = '';\n\n const lowerBody = body.toLowerCase();\n\n // Detect Component\n if (lowerBody.includes('feishu-card')) component = 'feishu-card';\n else if (lowerBody.includes('feishu-sticker')) component = 'feishu-sticker';\n else if (lowerBody.includes('git-sync')) component = 'git-sync';\n else if (lowerBody.includes('capability-evolver') || lowerBody.includes('evolve.js')) component = 'capability-evolver';\n else if (lowerBody.includes('interaction-logger')) component = 'interaction-logger';\n else if (lowerBody.includes('chat-to-image')) component = 'chat-to-image';\n else if (lowerBody.includes('safe_publish')) component = 'capability-evolver';\n\n // Detect Category\n if (lowerBody.includes('security') || lowerBody.includes('permission') || lowerBody.includes('auth') || lowerBody.includes('harden')) {\n category = 'Security & Stability';\n } else if (lowerBody.includes('optimiz') || lowerBody.includes('performance') || lowerBody.includes('memory') || lowerBody.includes('fast')) {\n category = 'Performance & Optimization';\n } else if (lowerBody.includes('doc') || lowerBody.includes('readme')) {\n category = 'Documentation & Process';\n }\n\n // Extract Human Summary (First meaningful line that isn't Status/Action/Date)\n const summaryLines = lines.filter(l => \n !l.startsWith('###') && \n !l.startsWith('Status:') && \n !l.startsWith('Action:') &&\n l.trim().length > 10\n );\n \n if (summaryLines.length > 0) {\n // Clean up the line\n summary = summaryLines[0]\n .replace(/^-\\s*/, '') // Remove bullets\n .replace(/\\*\\*/g, '') // Remove bold\n .replace(/`/, '')\n .trim();\n \n // Deduplicate\n const key = `${component}:${summary.substring(0, 20)}`;\n const exists = categories[category].some(i => i.key === key);\n \n if (!exists && !summary.includes(\"Stability Scan OK\") && !summary.includes(\"Workspace Sync\")) {\n categories[category].push({ time, component, summary, key });\n \n if (!componentMap[component]) componentMap[component] = [];\n componentMap[component].push(summary);\n }\n }\n });\n\n // --- Generate Markdown ---\n const today = new Date().toISOString().slice(0, 10);\n let md = `# Evolution Summary: The Day in Review (${today})\\n\\n`;\n md += `> Overview: Grouped summary of changes extracted from evolution history.\\n\\n`;\n\n // Section 1: By Theme (Evolution Direction)\n md += `## 1. Evolution Direction\\n`;\n \n for (const [cat, items] of Object.entries(categories)) {\n if (items.length === 0) continue;\n md += `### ${cat}\\n`;\n // Group by component within theme\n const compGroup = {};\n items.forEach(i => {\n if (!compGroup[i.component]) compGroup[i.component] = [];\n compGroup[i.component].push(i.summary);\n });\n \n for (const [comp, sums] of Object.entries(compGroup)) {\n // Unique summaries only\n const uniqueSums = [...new Set(sums)];\n uniqueSums.forEach(s => {\n md += `- **${comp}**: ${s}\\n`;\n });\n }\n md += `\\n`;\n }\n\n // Section 2: By Timeline (High Level)\n md += `## 2. Timeline of Critical Events\\n`;\n // Flatten and sort all items by time\n const allItems = [];\n Object.values(categories).forEach(list => allItems.push(...list));\n allItems.sort((a, b) => a.time.localeCompare(b.time));\n \n // Filter for \"Critical\" keywords\n const criticalItems = allItems.filter(i => \n i.summary.toLowerCase().includes('fix') || \n i.summary.toLowerCase().includes('patch') ||\n i.summary.toLowerCase().includes('create') ||\n i.summary.toLowerCase().includes('optimiz')\n );\n\n criticalItems.forEach(i => {\n md += `- \\`${i.time}\\` (${i.component}): ${i.summary}\\n`;\n });\n\n // Section 3: Package Adjustments\n md += `\\n## 3. Package & Documentation Adjustments\\n`;\n const comps = Object.keys(componentMap).sort();\n comps.forEach(comp => {\n const count = new Set(componentMap[comp]).size;\n md += `- **${comp}**: Received ${count} significant updates.\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(\"Human report generated.\");\n}\n\ngenerateHumanReport();\n\n",
141 "inputSchema": {},
142 "outputSchema": null,
143 "icons": null,
144 "annotations": null,
145 "meta": null,
146 "execution": null
147 },
148 {
149 "name": "gep_personality_report.js",
150 "title": null,
151 "description": "Script: gep_personality_report.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getRepoRoot, getMemoryDir, getGepAssetsDir } = require('../src/gep/paths');\nconst { normalizePersonalityState, personalityKey, defaultPersonalityState } = require('../src/gep/personality');\n\nfunction readJsonIfExists(p, fallback) {\n try {\n if (!fs.existsSync(p)) return fallback;\n const raw = fs.readFileSync(p, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction readJsonlIfExists(p, limitLines = 5000) {\n try {\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n const recent = lines.slice(Math.max(0, lines.length - limitLines));\n return recent\n .map(l => {\n try {\n return JSON.parse(l);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction pct(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return '0.0%';\n return `${(n * 100).toFixed(1)}%`;\n}\n\nfunction pad(s, n) {\n const str = String(s == null ? '' : s);\n if (str.length >= n) return str.slice(0, n);\n return str + ' '.repeat(n - str.length);\n}\n\nfunction scoreFromCounts(success, fail, avgScore) {\n const succ = Number(success) || 0;\n const fl = Number(fail) || 0;\n const total = succ + fl;\n const p = (succ + 1) / (total + 2); // Laplace smoothing\n const sampleWeight = Math.min(1, total / 8);\n const q = avgScore == null ? 0.5 : clamp01(avgScore);\n return p * 0.75 + q * 0.25 * sampleWeight;\n}\n\nfunction aggregateFromEvents(events) {\n const map = new Map();\n for (const ev of Array.isArray(events) ? events : []) {\n if (!ev || ev.type !== 'EvolutionEvent') continue;\n const ps = ev.personality_state && typeof ev.personality_state === 'object' ? ev.personality_state : null;\n if (!ps) continue;\n const key = personalityKey(normalizePersonalityState(ps));\n const cur = map.get(key) || {\n key,\n success: 0,\n fail: 0,\n n: 0,\n avg_score: 0.5,\n last_event_id: null,\n last_at: null,\n mutation: { repair: 0, optimize: 0, innovate: 0 },\n mutation_success: { repair: 0, optimize: 0, innovate: 0 },\n };\n const st = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (st === 'success') cur.success += 1;\n else if (st === 'failed') cur.fail += 1;\n\n const sc = ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? clamp01(Number(ev.outcome.score)) : null;\n if (sc != null) {\n cur.n += 1;\n cur.avg_score = cur.avg_score + (sc - cur.avg_score) / cur.n;\n }\n\n const cat = ev.intent ? String(ev.intent) : null;\n if (cat && cur.mutation[cat] != null) {\n cur.mutation[cat] += 1;\n if (st === 'success') cur.mutation_success[cat] += 1;\n }\n\n cur.last_event_id = ev.id || cur.last_event_id;\n const at = ev.meta && ev.meta.at ? String(ev.meta.at) : null;\n cur.last_at = at || cur.last_at;\n map.set(key, cur);\n }\n return Array.from(map.values());\n}\n\nfunction main() {\n const repoRoot = getRepoRoot();\n const memoryDir = getMemoryDir();\n const assetsDir = getGepAssetsDir();\n\n const personalityPath = path.join(memoryDir, 'personality_state.json');\n const model = readJsonIfExists(personalityPath, null);\n const current = model && model.current ? normalizePersonalityState(model.current) : defaultPersonalityState();\n const currentKey = personalityKey(current);\n\n const eventsPath = path.join(assetsDir, 'events.jsonl');\n const events = readJsonlIfExists(eventsPath, 10000);\n const evs = events.filter(e => e && e.type === 'EvolutionEvent');\n const agg = aggregateFromEvents(evs);\n\n // Prefer model.stats if present, but still show event-derived aggregation (ground truth).\n const stats = model && model.stats && typeof model.stats === 'object' ? model.stats : {};\n const statRows = Object.entries(stats).map(([key, e]) => {\n const entry = e && typeof e === 'object' ? e : {};\n const success = Number(entry.success) || 0;\n const fail = Number(entry.fail) || 0;\n const total = success + fail;\n const avg = Number.isFinite(Number(entry.avg_score)) ? clamp01(Number(entry.avg_score)) : null;\n const score = scoreFromCounts(success, fail, avg);\n return { key, success, fail, total, avg_score: avg, score, updated_at: entry.updated_at || null, source: 'model' };\n });\n\n const evRows = agg.map(e => {\n const success = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = success + fail;\n const avg = Number.isFinite(Number(e.avg_score)) ? clamp01(Number(e.avg_score)) : null;\n const score = scoreFromCounts(success, fail, avg);\n return { key: e.key, success, fail, total, avg_score: avg, score, updated_at: e.last_at || null, source: 'events', _ev: e };\n });\n\n // Merge rows by key (events take precedence for total/success/fail; model provides updated_at if events missing).\n const byKey = new Map();\n for (const r of [...statRows, ...evRows]) {\n const prev = byKey.get(r.key);\n if (!prev) {\n byKey.set(r.key, r);\n continue;\n }\n // Prefer events for counts and avg_score\n if (r.source === 'events') byKey.set(r.key, { ...prev, ...r });\n else byKey.set(r.key, { ...r, ...prev });\n }\n\n const merged = Array.from(byKey.values()).sort((a, b) => b.score - a.score);\n\n process.stdout.write(`Repo: ${repoRoot}\\n`);\n process.stdout.write(`MemoryDir: ${memoryDir}\\n`);\n process.stdout.write(`AssetsDir: ${assetsDir}\\n\\n`);\n\n process.stdout.write(`[Current Personality]\\n`);\n process.stdout.write(`${currentKey}\\n`);\n process.stdout.write(`${JSON.stringify(current, null, 2)}\\n\\n`);\n\n process.stdout.write(`[Personality Stats] (ranked by score)\\n`);\n if (merged.length === 0) {\n process.stdout.write('(no stats yet; run a few cycles and solidify)\\n');\n return;\n }\n\n const header =\n pad('rank', 5) +\n pad('total', 8) +\n pad('succ', 8) +\n pad('fail', 8) +\n pad('succ_rate', 11) +\n pad('avg', 7) +\n pad('score', 8) +\n 'key';\n process.stdout.write(header + '\\n');\n process.stdout.write('-'.repeat(Math.min(140, header.length + 40)) + '\\n');\n\n const topN = Math.min(25, merged.length);\n for (let i = 0; i < topN; i++) {\n const r = merged[i];\n const succ = Number(r.success) || 0;\n const fail = Number(r.fail) || 0;\n const total = Number(r.total) || succ + fail;\n const succRate = total > 0 ? succ / total : 0;\n const avg = r.avg_score == null ? '-' : Number(r.avg_score).toFixed(2);\n const line =\n pad(String(i + 1), 5) +\n pad(String(total), 8) +\n pad(String(succ), 8) +\n pad(String(fail), 8) +\n pad(pct(succRate), 11) +\n pad(String(avg), 7) +\n pad(Number(r.score).toFixed(3), 8) +\n String(r.key);\n process.stdout.write(line + '\\n');\n\n if (r._ev) {\n const ev = r._ev;\n const ms = ev.mutation || {};\n const mSucc = ev.mutation_success || {};\n const parts = [];\n for (const cat of ['repair', 'optimize', 'innovate']) {\n const n = Number(ms[cat]) || 0;\n if (n <= 0) continue;\n const s = Number(mSucc[cat]) || 0;\n parts.push(`${cat}:${s}/${n}`);\n }\n if (parts.length) process.stdout.write(` mutation_success: ${parts.join(' | ')}\\n`);\n }\n }\n\n process.stdout.write('\\n');\n process.stdout.write(`[Notes]\\n`);\n process.stdout.write(`- score is a smoothed composite of success_rate + avg_score (sample-weighted)\\n`);\n process.stdout.write(`- current_key appears in the ranking once enough data accumulates\\n`);\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write((e && e.message) || String(e));\n process.stderr.write('\\n');\n process.exit(1);\n}\n\n",
152 "inputSchema": {},
153 "outputSchema": null,
154 "icons": null,
155 "annotations": null,
156 "meta": null,
157 "execution": null
158 },
159 {
160 "name": "a2a_ingest.js",
161 "title": null,
162 "description": "Script: a2a_ingest.js. Code:\nvar fs = require('fs');\nvar assetStore = require('../src/gep/assetStore');\nvar a2a = require('../src/gep/a2a');\nvar memGraph = require('../src/gep/memoryGraph');\nvar contentHash = require('../src/gep/contentHash');\nvar a2aProto = require('../src/gep/a2aProtocol');\n\nfunction readStdin() {\n try { return fs.readFileSync(0, 'utf8'); } catch (e) { return ''; }\n}\n\nfunction parseSignalsFromEnv() {\n var raw = process.env.A2A_SIGNALS || '';\n if (!raw) return [];\n try {\n var maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) return maybe.map(String).filter(Boolean);\n } catch (e) {}\n return String(raw).split(',').map(function (s) { return s.trim(); }).filter(Boolean);\n}\n\nfunction main() {\n var args = process.argv.slice(2);\n var inputPath = '';\n for (var i = 0; i < args.length; i++) {\n if (args[i] && !args[i].startsWith('--')) { inputPath = args[i]; break; }\n }\n var source = process.env.A2A_SOURCE || 'external';\n var factor = Number.isFinite(Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR))\n ? Number(process.env.A2A_EXTERNAL_CONFIDENCE_FACTOR) : 0.6;\n\n var text = inputPath ? a2a.readTextIfExists(inputPath) : readStdin();\n var parsed = a2a.parseA2AInput(text);\n var signals = parseSignalsFromEnv();\n\n var accepted = 0;\n var rejected = 0;\n var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';\n\n for (var j = 0; j < parsed.length; j++) {\n var obj = parsed[j];\n if (!a2a.isAllowedA2AAsset(obj)) continue;\n\n if (obj.asset_id && typeof obj.asset_id === 'string') {\n if (!contentHash.verifyAssetId(obj)) {\n rejected += 1;\n if (emitDecisions) {\n try {\n var dm = a2aProto.buildDecision({ assetId: obj.asset_id, localId: obj.id, decision: 'reject', reason: 'asset_id integrity check failed' });\n a2aProto.getTransport().send(dm);\n } catch (e) {}\n }\n continue;\n }\n }\n\n var staged = a2a.lowerConfidence(obj, { source: source, factor: factor });\n if (!staged) continue;\n\n assetStore.appendExternalCandidateJsonl(staged);\n try { memGraph.recordExternalCandidate({ asset: staged, source: source, signals: signals }); } catch (e) {}\n\n if (emitDecisions) {\n try {\n var dm2 = a2aProto.buildDecision({ assetId: staged.asset_id, localId: staged.id, decision: 'quarantine', reason: 'staged as external candidate' });\n a2aProto.getTransport().send(dm2);\n } catch (e) {}\n }\n\n accepted += 1;\n }\n\n process.stdout.write('accepted=' + accepted + ' rejected=' + rejected + '\\n');\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
163 "inputSchema": {},
164 "outputSchema": null,
165 "icons": null,
166 "annotations": null,
167 "meta": null,
168 "execution": null
169 },
170 {
171 "name": "a2a_export.js",
172 "title": null,
173 "description": "Script: a2a_export.js. Code:\nconst { loadGenes, loadCapsules, readAllEvents } = require('../src/gep/assetStore');\nconst { exportEligibleCapsules } = require('../src/gep/a2a');\nconst { buildPublish, buildHello, getTransport } = require('../src/gep/a2aProtocol');\n\nfunction main() {\n var args = process.argv.slice(2);\n var asJson = args.includes('--json');\n var asProtocol = args.includes('--protocol');\n var withHello = args.includes('--hello');\n var persist = args.includes('--persist');\n\n var capsules = loadCapsules();\n var events = readAllEvents();\n var eligible = exportEligibleCapsules({ capsules: capsules, events: events });\n\n if (withHello || asProtocol) {\n var genes = loadGenes();\n var hello = buildHello({ geneCount: genes.length, capsuleCount: capsules.length });\n process.stdout.write(JSON.stringify(hello) + '\\n');\n if (persist) { try { getTransport().send(hello); } catch (e) {} }\n }\n\n if (asProtocol) {\n for (var i = 0; i < eligible.length; i++) {\n var msg = buildPublish({ asset: eligible[i] });\n process.stdout.write(JSON.stringify(msg) + '\\n');\n if (persist) { try { getTransport().send(msg); } catch (e) {} }\n }\n return;\n }\n\n if (asJson) {\n process.stdout.write(JSON.stringify(eligible, null, 2) + '\\n');\n return;\n }\n\n for (var j = 0; j < eligible.length; j++) {\n process.stdout.write(JSON.stringify(eligible[j]) + '\\n');\n }\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
174 "inputSchema": {},
175 "outputSchema": null,
176 "icons": null,
177 "annotations": null,
178 "meta": null,
179 "execution": null
180 },
181 {
182 "name": "a2a_promote.js",
183 "title": null,
184 "description": "Script: a2a_promote.js. Code:\nvar assetStore = require('../src/gep/assetStore');\nvar solidifyMod = require('../src/gep/solidify');\nvar contentHash = require('../src/gep/contentHash');\nvar a2aProto = require('../src/gep/a2aProtocol');\n\nfunction parseArgs(argv) {\n var out = { flags: new Set(), kv: new Map(), positionals: [] };\n for (var i = 0; i < argv.length; i++) {\n var a = argv[i];\n if (!a) continue;\n if (a.startsWith('--')) {\n var eq = a.indexOf('=');\n if (eq > -1) { out.kv.set(a.slice(2, eq), a.slice(eq + 1)); }\n else {\n var key = a.slice(2);\n var next = argv[i + 1];\n if (next && !String(next).startsWith('--')) { out.kv.set(key, next); i++; }\n else { out.flags.add(key); }\n }\n } else { out.positionals.push(a); }\n }\n return out;\n}\n\nfunction main() {\n var args = parseArgs(process.argv.slice(2));\n var id = String(args.kv.get('id') || '').trim();\n var typeRaw = String(args.kv.get('type') || '').trim().toLowerCase();\n var validated = args.flags.has('validated') || String(args.kv.get('validated') || '') === 'true';\n var limit = Number.isFinite(Number(args.kv.get('limit'))) ? Number(args.kv.get('limit')) : 500;\n\n if (!id || !typeRaw) throw new Error('Usage: node scripts/a2a_promote.js --type capsule|gene --id <id> --validated');\n if (!validated) throw new Error('Refusing to promote without --validated (local verification must be done first).');\n\n var type = typeRaw === 'capsule' ? 'Capsule' : typeRaw === 'gene' ? 'Gene' : '';\n if (!type) throw new Error('Invalid --type. Use capsule or gene.');\n\n var external = assetStore.readRecentExternalCandidates(limit);\n var candidate = null;\n for (var i = 0; i < external.length; i++) {\n if (external[i] && external[i].type === type && String(external[i].id) === id) { candidate = external[i]; break; }\n }\n if (!candidate) throw new Error('Candidate not found in external zone: type=' + type + ' id=' + id);\n\n if (type === 'Gene') {\n var validation = Array.isArray(candidate.validation) ? candidate.validation : [];\n for (var j = 0; j < validation.length; j++) {\n var c = String(validation[j] || '').trim();\n if (!c) continue;\n if (!solidifyMod.isValidationCommandAllowed(c)) {\n throw new Error('Refusing to promote Gene ' + id + ': validation command rejected by safety check: \"' + c + '\". Only node/npm/npx commands without shell operators are allowed.');\n }\n }\n }\n\n var promoted = JSON.parse(JSON.stringify(candidate));\n if (!promoted.a2a || typeof promoted.a2a !== 'object') promoted.a2a = {};\n promoted.a2a.status = 'promoted';\n promoted.a2a.promoted_at = new Date().toISOString();\n if (!promoted.schema_version) promoted.schema_version = contentHash.SCHEMA_VERSION;\n promoted.asset_id = contentHash.computeAssetId(promoted);\n\n var emitDecisions = process.env.A2A_EMIT_DECISIONS === 'true';\n\n if (type === 'Capsule') {\n assetStore.appendCapsule(promoted);\n if (emitDecisions) {\n try {\n var dm = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'capsule promoted after validation' });\n a2aProto.getTransport().send(dm);\n } catch (e) {}\n }\n process.stdout.write('promoted_capsule=' + id + '\\n');\n return;\n }\n\n var localGenes = assetStore.loadGenes();\n var exists = false;\n for (var k = 0; k < localGenes.length; k++) {\n if (localGenes[k] && localGenes[k].type === 'Gene' && String(localGenes[k].id) === id) { exists = true; break; }\n }\n if (exists) {\n if (emitDecisions) {\n try {\n var dm2 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'reject', reason: 'local gene with same ID already exists' });\n a2aProto.getTransport().send(dm2);\n } catch (e) {}\n }\n process.stdout.write('conflict_keep_local_gene=' + id + '\\n');\n return;\n }\n\n assetStore.upsertGene(promoted);\n if (emitDecisions) {\n try {\n var dm3 = a2aProto.buildDecision({ assetId: promoted.asset_id, localId: id, decision: 'accept', reason: 'gene promoted after safety audit' });\n a2aProto.getTransport().send(dm3);\n } catch (e) {}\n }\n process.stdout.write('promoted_gene=' + id + '\\n');\n}\n\ntry { main(); } catch (e) {\n process.stderr.write((e && e.message ? e.message : String(e)) + '\\n');\n process.exit(1);\n}\n",
185 "inputSchema": {},
186 "outputSchema": null,
187 "icons": null,
188 "annotations": null,
189 "meta": null,
190 "execution": null
191 },
192 {
193 "name": "build_public.js",
194 "title": null,
195 "description": "Script: build_public.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\nfunction readJson(filePath) {\n return JSON.parse(fs.readFileSync(filePath, 'utf8'));\n}\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction rmDir(dir) {\n if (!fs.existsSync(dir)) return;\n fs.rmSync(dir, { recursive: true, force: true });\n}\n\nfunction normalizePosix(p) {\n return p.split(path.sep).join('/');\n}\n\nfunction isUnder(child, parent) {\n const rel = path.relative(parent, child);\n return !!rel && !rel.startsWith('..') && !path.isAbsolute(rel);\n}\n\nfunction listFilesRec(dir) {\n const out = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const ent of entries) {\n const p = path.join(dir, ent.name);\n if (ent.isDirectory()) out.push(...listFilesRec(p));\n else if (ent.isFile()) out.push(p);\n }\n return out;\n}\n\nfunction globToRegex(glob) {\n // Supports \"*\" within a single segment and \"**\" for any depth.\n const norm = normalizePosix(glob);\n const parts = norm.split('/').filter(p => p.length > 0);\n const out = [];\n\n for (const part of parts) {\n if (part === '**') {\n // any number of path segments\n out.push('(?:.*)');\n continue;\n }\n // Escape regex special chars, then expand \"*\" wildcards within segment.\n const esc = part.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '[^/]*');\n out.push(esc);\n }\n\n const re = out.join('\\\\/');\n return new RegExp(`^${re}$`);\n}\n\nfunction matchesAnyGlobs(relPath, globs) {\n const p = normalizePosix(relPath);\n for (const g of globs || []) {\n const re = globToRegex(g);\n if (re.test(p)) return true;\n }\n return false;\n}\n\nfunction copyFile(srcAbs, destAbs) {\n ensureDir(path.dirname(destAbs));\n fs.copyFileSync(srcAbs, destAbs);\n}\n\nfunction copyEntry(spec, outDirAbs) {\n const copied = [];\n\n // Directory glob\n if (spec.includes('*')) {\n const all = listFilesRec(REPO_ROOT);\n const includeRe = globToRegex(spec);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(REPO_ROOT, abs));\n if (!includeRe.test(rel)) continue;\n const destAbs = path.join(outDirAbs, rel);\n copyFile(abs, destAbs);\n copied.push(rel);\n }\n return copied;\n }\n\n const srcAbs = path.join(REPO_ROOT, spec);\n if (!fs.existsSync(srcAbs)) return [];\n\n const st = fs.statSync(srcAbs);\n if (st.isFile()) {\n const rel = normalizePosix(spec);\n copyFile(srcAbs, path.join(outDirAbs, rel));\n copied.push(rel);\n return copied;\n }\n if (st.isDirectory()) {\n const files = listFilesRec(srcAbs);\n for (const abs of files) {\n const rel = normalizePosix(path.relative(REPO_ROOT, abs));\n copyFile(abs, path.join(outDirAbs, rel));\n copied.push(rel);\n }\n }\n return copied;\n}\n\nfunction applyRewrite(outDirAbs, rewrite) {\n const rules = rewrite || {};\n for (const [relFile, cfg] of Object.entries(rules)) {\n const target = path.join(outDirAbs, relFile);\n if (!fs.existsSync(target)) continue;\n let content = fs.readFileSync(target, 'utf8');\n const reps = (cfg && cfg.replace) || [];\n for (const r of reps) {\n const from = String(r.from || '');\n const to = String(r.to || '');\n if (!from) continue;\n content = content.split(from).join(to);\n }\n fs.writeFileSync(target, content, 'utf8');\n }\n}\n\nfunction rewritePackageJson(outDirAbs) {\n const p = path.join(outDirAbs, 'package.json');\n if (!fs.existsSync(p)) return;\n try {\n const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));\n pkg.scripts = {\n start: 'node index.js',\n run: 'node index.js run',\n solidify: 'node index.js solidify',\n 'a2a:export': 'node scripts/a2a_export.js',\n 'a2a:ingest': 'node scripts/a2a_ingest.js',\n 'a2a:promote': 'node scripts/a2a_promote.js',\n };\n fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\\n', 'utf8');\n } catch (e) {\n // ignore\n }\n}\n\nfunction parseSemver(v) {\n const m = String(v || '').trim().match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!m) return null;\n return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };\n}\n\nfunction formatSemver(x) {\n return `${x.major}.${x.minor}.${x.patch}`;\n}\n\nfunction bumpSemver(base, bump) {\n const v = parseSemver(base);\n if (!v) return null;\n if (bump === 'major') return `${v.major + 1}.0.0`;\n if (bump === 'minor') return `${v.major}.${v.minor + 1}.0`;\n if (bump === 'patch') return `${v.major}.${v.minor}.${v.patch + 1}`;\n return formatSemver(v);\n}\n\nfunction git(cmd) {\n return execSync(cmd, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n}\n\nfunction getBaseReleaseCommit() {\n // Prefer last \"prepare vX.Y.Z\" commit; fallback to HEAD~50 range later.\n try {\n const hash = git('git log -n 1 --pretty=%H --grep=\"chore(release): prepare v\"');\n return hash || null;\n } catch (e) {\n return null;\n }\n}\n\nfunction getCommitSubjectsSince(baseCommit) {\n try {\n if (!baseCommit) {\n const out = git('git log -n 30 --pretty=%s');\n return out ? out.split('\\n').filter(Boolean) : [];\n }\n const out = git(`git log ${baseCommit}..HEAD --pretty=%s`);\n return out ? out.split('\\n').filter(Boolean) : [];\n } catch (e) {\n return [];\n }\n}\n\nfunction inferBumpFromSubjects(subjects) {\n const subs = (subjects || []).map(s => String(s));\n const hasBreaking = subs.some(s => /\\bBREAKING CHANGE\\b/i.test(s) || /^[a-z]+(\\(.+\\))?!:/.test(s));\n if (hasBreaking) return { bump: 'major', reason: 'breaking change marker in commit subject' };\n\n const hasFeat = subs.some(s => /^feat(\\(.+\\))?:/i.test(s));\n if (hasFeat) return { bump: 'minor', reason: 'feature commit detected (feat:)' };\n\n const hasFix = subs.some(s => /^(fix|perf)(\\(.+\\))?:/i.test(s));\n if (hasFix) return { bump: 'patch', reason: 'fix/perf commit detected' };\n\n if (subs.length === 0) return { bump: 'none', reason: 'no commits since base release commit' };\n return { bump: 'patch', reason: 'default to patch for non-breaking changes' };\n}\n\nfunction suggestVersion() {\n const pkgPath = path.join(REPO_ROOT, 'package.json');\n let baseVersion = null;\n try {\n baseVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;\n } catch (e) {}\n\n const baseCommit = getBaseReleaseCommit();\n const subjects = getCommitSubjectsSince(baseCommit);\n const decision = inferBumpFromSubjects(subjects);\n\n let suggested = null;\n if (decision.bump === 'none') suggested = baseVersion;\n else suggested = bumpSemver(baseVersion, decision.bump);\n\n return { baseVersion, baseCommit, subjects, decision, suggestedVersion: suggested };\n}\n\nfunction writePrivateSemverNote(note) {\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n fs.writeFileSync(path.join(privateDir, 'semver_suggestion.json'), JSON.stringify(note, null, 2) + '\\n', 'utf8');\n}\n\nfunction writePrivateSemverPrompt(note) {\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n const subjects = Array.isArray(note.subjects) ? note.subjects : [];\n const semverRule = [\n 'MAJOR.MINOR.PATCH',\n '- MAJOR: incompatible changes',\n '- MINOR: backward-compatible features',\n '- PATCH: backward-compatible bug fixes',\n ].join('\\n');\n\n const prompt = [\n 'You are a release versioning assistant.',\n 'Decide the next version bump using SemVer rules below.',\n '',\n semverRule,\n '',\n `Base version: ${note.baseVersion || '(unknown)'}`,\n `Base commit: ${note.baseCommit || '(unknown)'}`,\n '',\n 'Recent commit subjects (newest first):',\n ...subjects.map(s => `- ${s}`),\n '',\n 'Output JSON only:',\n '{ \"bump\": \"major|minor|patch|none\", \"suggestedVersion\": \"x.y.z\", \"reason\": [\"...\"] }',\n ].join('\\n');\n\n fs.writeFileSync(path.join(privateDir, 'semver_prompt.md'), prompt + '\\n', 'utf8');\n}\n\nfunction writeDistVersion(outDirAbs, version) {\n if (!version) return;\n const p = path.join(outDirAbs, 'package.json');\n if (!fs.existsSync(p)) return;\n try {\n const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));\n pkg.version = version;\n fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\\n', 'utf8');\n } catch (e) {}\n}\n\nfunction pruneExcluded(outDirAbs, excludeGlobs) {\n const all = listFilesRec(outDirAbs);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(outDirAbs, abs));\n if (matchesAnyGlobs(rel, excludeGlobs)) {\n fs.rmSync(abs, { force: true });\n }\n }\n}\n\nfunction validateNoPrivatePaths(outDirAbs) {\n // Basic safeguard: forbid docs/ and memory/ in output.\n const forbiddenPrefixes = ['docs/', 'memory/'];\n const all = listFilesRec(outDirAbs);\n for (const abs of all) {\n const rel = normalizePosix(path.relative(outDirAbs, abs));\n for (const pref of forbiddenPrefixes) {\n if (rel.startsWith(pref)) {\n throw new Error(`Build validation failed: forbidden path in output: ${rel}`);\n }\n }\n }\n}\n\nfunction main() {\n const manifestPath = path.join(REPO_ROOT, 'public.manifest.json');\n const manifest = readJson(manifestPath);\n const outDir = String(manifest.outDir || 'dist-public');\n const outDirAbs = path.join(REPO_ROOT, outDir);\n\n // SemVer suggestion (private). This does not modify the source repo version.\n const semver = suggestVersion();\n writePrivateSemverNote(semver);\n writePrivateSemverPrompt(semver);\n\n rmDir(outDirAbs);\n ensureDir(outDirAbs);\n\n const include = manifest.include || [];\n const exclude = manifest.exclude || [];\n\n const copied = [];\n for (const spec of include) {\n copied.push(...copyEntry(spec, outDirAbs));\n }\n\n pruneExcluded(outDirAbs, exclude);\n applyRewrite(outDirAbs, manifest.rewrite);\n rewritePackageJson(outDirAbs);\n\n // Prefer explicit version; otherwise use suggested version.\n const releaseVersion = process.env.RELEASE_VERSION || semver.suggestedVersion;\n if (releaseVersion) writeDistVersion(outDirAbs, releaseVersion);\n\n validateNoPrivatePaths(outDirAbs);\n\n // Write build manifest for private verification (do not include in dist-public/).\n const buildInfo = {\n built_at: new Date().toISOString(),\n outDir,\n files: copied.sort(),\n };\n const privateDir = path.join(REPO_ROOT, 'memory');\n ensureDir(privateDir);\n fs.writeFileSync(path.join(privateDir, 'public_build_info.json'), JSON.stringify(buildInfo, null, 2) + '\\n', 'utf8');\n\n process.stdout.write(`Built public output at ${outDir}\\n`);\n if (semver && semver.suggestedVersion) {\n process.stdout.write(`Suggested version: ${semver.suggestedVersion}\\n`);\n process.stdout.write(`SemVer decision: ${semver.decision ? semver.decision.bump : 'unknown'}\\n`);\n }\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
196 "inputSchema": {},
197 "outputSchema": null,
198 "icons": null,
199 "annotations": null,
200 "meta": null,
201 "execution": null
202 },
203 {
204 "name": "gep_append_event.js",
205 "title": null,
206 "description": "Script: gep_append_event.js. Code:\nconst fs = require('fs');\nconst { appendEventJsonl } = require('../src/gep/assetStore');\n\nfunction readStdin() {\n try {\n return fs.readFileSync(0, 'utf8');\n } catch {\n return '';\n }\n}\n\nfunction readTextIfExists(p) {\n try {\n if (!p) return '';\n if (!fs.existsSync(p)) return '';\n return fs.readFileSync(p, 'utf8');\n } catch {\n return '';\n }\n}\n\nfunction parseInput(text) {\n const raw = String(text || '').trim();\n if (!raw) return [];\n\n // Accept JSON array or single JSON.\n try {\n const maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) return maybe;\n if (maybe && typeof maybe === 'object') return [maybe];\n } catch (e) {}\n\n // Fallback: JSONL.\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n const out = [];\n for (const line of lines) {\n try {\n const obj = JSON.parse(line);\n out.push(obj);\n } catch (e) {}\n }\n return out;\n}\n\nfunction isValidEvolutionEvent(ev) {\n if (!ev || ev.type !== 'EvolutionEvent') return false;\n if (!ev.id || typeof ev.id !== 'string') return false;\n // parent may be null or string\n if (!(ev.parent === null || typeof ev.parent === 'string')) return false;\n if (!ev.intent || typeof ev.intent !== 'string') return false;\n if (!Array.isArray(ev.signals)) return false;\n if (!Array.isArray(ev.genes_used)) return false;\n // GEP v1.4: mutation + personality are mandatory evolution dimensions\n if (!ev.mutation_id || typeof ev.mutation_id !== 'string') return false;\n if (!ev.personality_state || typeof ev.personality_state !== 'object') return false;\n if (ev.personality_state.type !== 'PersonalityState') return false;\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n const v = Number(ev.personality_state[k]);\n if (!Number.isFinite(v) || v < 0 || v > 1) return false;\n }\n if (!ev.blast_radius || typeof ev.blast_radius !== 'object') return false;\n if (!Number.isFinite(Number(ev.blast_radius.files))) return false;\n if (!Number.isFinite(Number(ev.blast_radius.lines))) return false;\n if (!ev.outcome || typeof ev.outcome !== 'object') return false;\n if (!ev.outcome.status || typeof ev.outcome.status !== 'string') return false;\n const score = Number(ev.outcome.score);\n if (!Number.isFinite(score) || score < 0 || score > 1) return false;\n\n // capsule_id is optional, but if present must be string or null.\n if (!('capsule_id' in ev)) return true;\n return ev.capsule_id === null || typeof ev.capsule_id === 'string';\n}\n\nfunction main() {\n const args = process.argv.slice(2);\n const inputPath = args.find(a => a && !a.startsWith('--')) || '';\n const text = inputPath ? readTextIfExists(inputPath) : readStdin();\n const items = parseInput(text);\n\n let appended = 0;\n for (const it of items) {\n if (!isValidEvolutionEvent(it)) continue;\n appendEventJsonl(it);\n appended += 1;\n }\n\n process.stdout.write(`appended=${appended}\\n`);\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e && e.message ? e.message : String(e)}\\n`);\n process.exit(1);\n}\n\n",
207 "inputSchema": {},
208 "outputSchema": null,
209 "icons": null,
210 "annotations": null,
211 "meta": null,
212 "execution": null
213 },
214 {
215 "name": "recover_loop.js",
216 "title": null,
217 "description": "Script: recover_loop.js. Code:\n#!/usr/bin/env node\n/* eslint-disable no-console */\nconst fs = require('fs');\nconst path = require('path');\nconst { spawnSync } = require('child_process');\n\nfunction exists(p) {\n try {\n return fs.existsSync(p);\n } catch (e) {\n return false;\n }\n}\n\nfunction sleepMs(ms) {\n const n = Number(ms);\n const t = Number.isFinite(n) ? Math.max(0, n) : 0;\n if (t <= 0) return;\n spawnSync('sleep', [String(Math.ceil(t / 1000))], { stdio: 'ignore' });\n}\n\nfunction resolveWorkspaceRoot() {\n // In OpenClaw exec, cwd is usually the workspace root.\n // Keep it simple: do not try to walk up arbitrarily.\n return process.cwd();\n}\n\nfunction resolveEvolverEntry(workspaceRoot) {\n const candidates = [\n path.join(workspaceRoot, 'skills', 'evolver', 'index.js'),\n path.join(workspaceRoot, 'skills', 'capability-evolver', 'index.js'),\n ];\n for (const p of candidates) {\n if (exists(p)) return p;\n }\n return null;\n}\n\nfunction main() {\n const waitMs = parseInt(String(process.env.EVOLVER_RECOVER_WAIT_MS || '10000'), 10);\n const wait = Number.isFinite(waitMs) ? Math.max(0, waitMs) : 10000;\n\n console.log(`[RECOVERY] Waiting ${wait}ms before restart...`);\n sleepMs(wait);\n\n const workspaceRoot = resolveWorkspaceRoot();\n const entry = resolveEvolverEntry(workspaceRoot);\n if (!entry) {\n console.error('[RECOVERY] Failed: cannot locate evolver entry under skills/.');\n process.exit(2);\n }\n\n console.log(`[RECOVERY] Restarting loop via ${path.relative(workspaceRoot, entry)} ...`);\n const r = spawnSync(process.execPath, [entry, '--loop'], { stdio: 'inherit' });\n process.exit(typeof r.status === 'number' ? r.status : 1);\n}\n\nif (require.main === module) {\n main();\n}\n\n",
218 "inputSchema": {},
219 "outputSchema": null,
220 "icons": null,
221 "annotations": null,
222 "meta": null,
223 "execution": null
224 },
225 {
226 "name": "extract_log.js",
227 "title": null,
228 "description": "Script: extract_log.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst LOG_FILE = path.join(REPO_ROOT, 'memory', 'mad_dog_evolution.log');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_history.md');\n\nfunction parseLog() {\n if (!fs.existsSync(LOG_FILE)) {\n console.log(\"Log file not found.\");\n return;\n }\n\n const content = fs.readFileSync(LOG_FILE, 'utf8');\n const lines = content.split('\\n');\n \n const reports = [];\n let currentTimestamp = null;\n\n // Regex for Feishu command\n // node skills/feishu-card/send.js --title \"...\" --color ... --text \"...\"\n const cmdRegex = /node skills\\/feishu-card\\/send\\.js --title \"(.*?)\" --color \\w+ --text \"(.*?)\"/;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n \n // 1. Capture Timestamp\n if (line.includes('Cycle Start:')) {\n // Format: Cycle Start: Sun Feb 1 19:17:44 UTC 2026\n const dateStr = line.split('Cycle Start: ')[1].trim();\n try {\n currentTimestamp = new Date(dateStr);\n } catch (e) {\n currentTimestamp = null;\n }\n }\n\n const match = line.match(cmdRegex);\n if (match) {\n const title = match[1];\n let text = match[2];\n \n // Clean up text (unescape newlines)\n text = text.replace(/\\\\n/g, '\\n').replace(/\\\\\"/g, '\"');\n\n if (currentTimestamp) {\n reports.push({\n ts: currentTimestamp,\n title: title,\n text: text,\n id: title // Cycle ID is in title\n });\n }\n }\n }\n\n // Deduplicate by ID (keep latest timestamp?)\n const uniqueReports = {};\n reports.forEach(r => {\n uniqueReports[r.id] = r;\n });\n\n const sortedReports = Object.values(uniqueReports).sort((a, b) => a.ts - b.ts);\n\n let md = \"# Evolution History (Extracted)\\n\\n\";\n sortedReports.forEach(r => {\n // Convert to CST (UTC+8)\n const cstDate = r.ts.toLocaleString(\"zh-CN\", {\n timeZone: \"Asia/Shanghai\", \n hour12: false,\n year: 'numeric', month: '2-digit', day: '2-digit',\n hour: '2-digit', minute: '2-digit', second: '2-digit'\n });\n\n md += `### ${r.title} (${cstDate})\\n`;\n md += `${r.text}\\n\\n`;\n md += `---\\n\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(`Extracted ${sortedReports.length} reports to ${OUT_FILE}`);\n}\n\nparseLog();\n\n",
229 "inputSchema": {},
230 "outputSchema": null,
231 "icons": null,
232 "annotations": null,
233 "meta": null,
234 "execution": null
235 },
236 {
237 "name": "generate_history.js",
238 "title": null,
239 "description": "Script: generate_history.js. Code:\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\n\n// Separator for git log parsing (something unlikely to be in commit messages)\nconst SEP = '|||';\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\ntry {\n // Git command:\n // --reverse: Oldest to Newest (Time Sequence)\n // --grep: Filter by keyword\n // --format: Hash, Date (ISO), Author, Subject, Body\n const cmd = `git log --reverse --grep=\"Evolution\" --format=\"%H${SEP}%ai${SEP}%an${SEP}%s${SEP}%b\"`;\n \n console.log('Executing git log...');\n const output = execSync(cmd, { \n encoding: 'utf8', \n cwd: REPO_ROOT,\n maxBuffer: 1024 * 1024 * 10 // 10MB buffer just in case\n });\n\n const entries = output.split('\\n').filter(line => line.trim().length > 0);\n \n let markdown = '# Evolution History (Time Sequence)\\n\\n';\n markdown += '> Filter: \"Evolution\"\\n';\n markdown += '> Timezone: CST (UTC+8)\\n\\n';\n \n let count = 0;\n\n entries.forEach(entry => {\n const parts = entry.split(SEP);\n if (parts.length < 4) return;\n\n const hash = parts[0];\n const dateStr = parts[1];\n const author = parts[2];\n const subject = parts[3];\n const body = parts[4] || '';\n\n // Parse Date and Convert to UTC+8\n const date = new Date(dateStr);\n // Add 8 hours (28800000 ms) to UTC timestamp to shift it\n // Then formatting it as ISO will look like UTC but represent CST values\n const cstDate = new Date(date.getTime() + 8 * 60 * 60 * 1000);\n \n // Format: YYYY-MM-DD HH:mm:ss\n const timeStr = cstDate.toISOString().replace('T', ' ').substring(0, 19);\n\n markdown += `## ${timeStr}\\n`;\n markdown += `- Commit: \\`${hash.substring(0, 7)}\\`\\n`;\n markdown += `- Subject: ${subject}\\n`;\n \n if (body.trim()) {\n // Indent body for better readability\n const formattedBody = body.trim().split('\\n').map(l => `> ${l}`).join('\\n');\n markdown += `- Details:\\n${formattedBody}\\n`;\n }\n markdown += '\\n';\n count++;\n });\n\n const outDir = path.join(REPO_ROOT, 'memory');\n if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });\n const outPath = path.join(outDir, 'evolution_history.md');\n fs.writeFileSync(outPath, markdown);\n \n console.log(`Successfully generated report with ${count} entries.`);\n console.log(`Saved to: ${outPath}`);\n\n} catch (e) {\n console.error('Error generating history:', e.message);\n process.exit(1);\n}\n\n",
240 "inputSchema": {},
241 "outputSchema": null,
242 "icons": null,
243 "annotations": null,
244 "meta": null,
245 "execution": null
246 },
247 {
248 "name": "suggest_version.js",
249 "title": null,
250 "description": "Script: suggest_version.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction parseSemver(v) {\n const m = String(v || '').trim().match(/^(\\d+)\\.(\\d+)\\.(\\d+)$/);\n if (!m) return null;\n return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };\n}\n\nfunction bumpSemver(base, bump) {\n const v = parseSemver(base);\n if (!v) return null;\n if (bump === 'major') return `${v.major + 1}.0.0`;\n if (bump === 'minor') return `${v.major}.${v.minor + 1}.0`;\n if (bump === 'patch') return `${v.major}.${v.minor}.${v.patch + 1}`;\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n\nfunction git(cmd) {\n return execSync(cmd, { cwd: REPO_ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n}\n\nfunction getBaseReleaseCommit() {\n try {\n const hash = git('git log -n 1 --pretty=%H --grep=\"chore(release): prepare v\"');\n return hash || null;\n } catch (e) {\n return null;\n }\n}\n\nfunction getCommitSubjectsSince(baseCommit) {\n try {\n if (!baseCommit) {\n const out = git('git log -n 30 --pretty=%s');\n return out ? out.split('\\n').filter(Boolean) : [];\n }\n const out = git(`git log ${baseCommit}..HEAD --pretty=%s`);\n return out ? out.split('\\n').filter(Boolean) : [];\n } catch (e) {\n return [];\n }\n}\n\nfunction inferBumpFromSubjects(subjects) {\n const subs = (subjects || []).map(s => String(s));\n const hasBreaking = subs.some(s => /\\bBREAKING CHANGE\\b/i.test(s) || /^[a-z]+(\\(.+\\))?!:/.test(s));\n if (hasBreaking) return { bump: 'major', reason: 'breaking change marker in commit subject' };\n\n const hasFeat = subs.some(s => /^feat(\\(.+\\))?:/i.test(s));\n if (hasFeat) return { bump: 'minor', reason: 'feature commit detected (feat:)' };\n\n const hasFix = subs.some(s => /^(fix|perf)(\\(.+\\))?:/i.test(s));\n if (hasFix) return { bump: 'patch', reason: 'fix/perf commit detected' };\n\n if (subs.length === 0) return { bump: 'none', reason: 'no commits since base release commit' };\n return { bump: 'patch', reason: 'default to patch for non-breaking changes' };\n}\n\nfunction main() {\n const pkgPath = path.join(REPO_ROOT, 'package.json');\n const baseVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version;\n\n const baseCommit = getBaseReleaseCommit();\n const subjects = getCommitSubjectsSince(baseCommit);\n const decision = inferBumpFromSubjects(subjects);\n const suggestedVersion = decision.bump === 'none' ? baseVersion : bumpSemver(baseVersion, decision.bump);\n\n const out = { baseVersion, baseCommit, subjects, decision, suggestedVersion };\n const memDir = path.join(REPO_ROOT, 'memory');\n ensureDir(memDir);\n fs.writeFileSync(path.join(memDir, 'semver_suggestion.json'), JSON.stringify(out, null, 2) + '\\n', 'utf8');\n process.stdout.write(JSON.stringify(out, null, 2) + '\\n');\n}\n\ntry {\n main();\n} catch (e) {\n process.stderr.write(`${e.message}\\n`);\n process.exit(1);\n}\n\n",
251 "inputSchema": {},
252 "outputSchema": null,
253 "icons": null,
254 "annotations": null,
255 "meta": null,
256 "execution": null
257 },
258 {
259 "name": "analyze_by_skill.js",
260 "title": null,
261 "description": "Script: analyze_by_skill.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nconst REPO_ROOT = path.resolve(__dirname, '..');\nconst LOG_FILE = path.join(REPO_ROOT, 'evolution_history_full.md');\nconst OUT_FILE = path.join(REPO_ROOT, 'evolution_detailed_report.md');\n\nfunction analyzeEvolution() {\n if (!fs.existsSync(LOG_FILE)) {\n console.error(\"Source file missing.\");\n return;\n }\n\n const content = fs.readFileSync(LOG_FILE, 'utf8');\n // Split by divider\n const entries = content.split('---').map(e => e.trim()).filter(e => e.length > 0);\n\n const skillUpdates = {}; // Map<SkillName, Array<Changes>>\n const generalUpdates = []; // Array<Changes>\n\n // Regex to detect skills/paths\n // e.g. `skills/feishu-card/send.js` or **Target**: `skills/git-sync`\n const skillRegex = /skills\\/([a-zA-Z0-9\\-_]+)/;\n const actionRegex = /Action:\\s*([\\s\\S]*?)(?=\\n\\n|\\n[A-Z]|$)/i; // Capture Action text\n const statusRegex = /Status:\\s*\\[?([A-Z\\s_]+)\\]?/i;\n\n entries.forEach(entry => {\n // Extract basic info\n const statusMatch = entry.match(statusRegex);\n const status = statusMatch ? statusMatch[1].trim().toUpperCase() : 'UNKNOWN';\n \n // Skip routine checks if we want a *detailed evolution* report (focus on changes)\n // But user asked for \"what happened\", so routine scans might be boring unless they found something.\n // Let's filter out \"STABILITY\" or \"RUNNING\" unless there is a clear \"Mutated\" or \"Fixed\" keyword.\n const isInteresting = \n entry.includes('Fixed') || \n entry.includes('Hardened') || \n entry.includes('Optimized') || \n entry.includes('Patched') || \n entry.includes('Created') || \n entry.includes('Added') ||\n status === 'SUCCESS' ||\n status === 'COMPLETED';\n\n if (!isInteresting) return;\n\n // Find associated skill\n const skillMatch = entry.match(skillRegex);\n let skillName = 'General / System';\n if (skillMatch) {\n skillName = skillMatch[1];\n } else {\n // Try heuristics\n if (entry.toLowerCase().includes('feishu card')) skillName = 'feishu-card';\n else if (entry.toLowerCase().includes('git sync')) skillName = 'git-sync';\n else if (entry.toLowerCase().includes('logger')) skillName = 'interaction-logger';\n else if (entry.toLowerCase().includes('evolve')) skillName = 'capability-evolver';\n }\n\n // Extract description\n let description = \"\";\n const actionMatch = entry.match(actionRegex);\n if (actionMatch) {\n description = actionMatch[1].trim();\n } else {\n // Fallback: take lines that look like bullet points or text after header\n const lines = entry.split('\\n');\n description = lines.filter(l => l.match(/^[\u2022\\-\\*]|\\w/)).slice(1).join('\\n').trim();\n }\n\n // Clean up description (remove duplicate \"Action:\" prefix if captured)\n description = description.replace(/^Action:\\s*/i, '');\n\n if (!skillUpdates[skillName]) skillUpdates[skillName] = [];\n \n // Dedup descriptions slightly (simple check)\n const isDuplicate = skillUpdates[skillName].some(u => u.desc.includes(description.substring(0, 20)));\n if (!isDuplicate) {\n // Extract Date if possible\n const dateMatch = entry.match(/\\((\\d{4}\\/\\d{1,2}\\/\\d{1,2}.*?)\\)/);\n const date = dateMatch ? dateMatch[1] : 'Unknown';\n \n skillUpdates[skillName].push({\n date,\n status,\n desc: description\n });\n }\n });\n\n // Generate Markdown\n let md = \"# Detailed Evolution Report (By Skill)\\n\\n> Comprehensive breakdown of system changes.\\n\\n\";\n\n // Sort skills alphabetically\n const sortedSkills = Object.keys(skillUpdates).sort();\n\n sortedSkills.forEach(skill => {\n md += `## ${skill}\\n`;\n const updates = skillUpdates[skill];\n \n updates.forEach(u => {\n // Icon based on content\n let icon = '*';\n const lowerDesc = u.desc.toLowerCase();\n if (lowerDesc.includes('optimiz')) icon = '[optimize]';\n if (lowerDesc.includes('secur') || lowerDesc.includes('harden') || lowerDesc.includes('permission')) icon = '[security]';\n if (lowerDesc.includes('fix') || lowerDesc.includes('patch')) icon = '[repair]';\n if (lowerDesc.includes('creat') || lowerDesc.includes('add')) icon = '[add]';\n\n md += `### ${icon} ${u.date}\\n`;\n md += `${u.desc}\\n\\n`;\n });\n md += `---\\n`;\n });\n\n fs.writeFileSync(OUT_FILE, md);\n console.log(`Generated report for ${sortedSkills.length} skills.`);\n}\n\nanalyzeEvolution();\n\n",
262 "inputSchema": {},
263 "outputSchema": null,
264 "icons": null,
265 "annotations": null,
266 "meta": null,
267 "execution": null
268 },
269 {
270 "name": "evolve.js",
271 "title": null,
272 "description": "Script: evolve.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst os = require('os');\nconst { execSync } = require('child_process');\nconst { getRepoRoot, getMemoryDir } = require('./gep/paths');\nconst { extractSignals, analyzeRecentHistory } = require('./gep/signals');\nconst {\n loadGenes,\n loadCapsules,\n readAllEvents,\n getLastEventId,\n appendCandidateJsonl,\n readRecentCandidates,\n readRecentExternalCandidates,\n} = require('./gep/assetStore');\nconst { selectGeneAndCapsule, matchPatternToSignals } = require('./gep/selector');\nconst { buildGepPrompt } = require('./gep/prompt');\nconst { resolveStrategy } = require('./gep/strategy');\nconst { extractCapabilityCandidates, renderCandidatesPreview } = require('./gep/candidates');\nconst {\n getMemoryAdvice,\n recordSignalSnapshot,\n recordHypothesis,\n recordAttempt,\n recordOutcomeFromState,\n memoryGraphPath,\n} = require('./gep/memoryGraph');\nconst { readStateForSolidify, writeStateForSolidify } = require('./gep/solidify');\nconst { buildMutation, isHighRiskMutationAllowed } = require('./gep/mutation');\nconst { selectPersonalityForRun } = require('./gep/personality');\nconst { clip, writePromptArtifact, renderSessionsSpawnCall } = require('./gep/bridge');\nconst { getEvolutionDir } = require('./gep/paths');\n\nconst REPO_ROOT = getRepoRoot();\n\n// Load environment variables from repo root\ntry {\n require('dotenv').config({ path: path.join(REPO_ROOT, '.env'), quiet: true });\n} catch (e) {\n // dotenv might not be installed or .env missing, proceed gracefully\n}\n\n// Configuration from CLI flags or Env\nconst ARGS = process.argv.slice(2);\nconst IS_REVIEW_MODE = ARGS.includes('--review');\nconst IS_DRY_RUN = ARGS.includes('--dry-run');\nconst IS_RANDOM_DRIFT = ARGS.includes('--drift') || String(process.env.RANDOM_DRIFT || '').toLowerCase() === 'true';\n\n// Default Configuration\nconst MEMORY_DIR = getMemoryDir();\nconst AGENT_NAME = process.env.AGENT_NAME || 'main';\nconst AGENT_SESSIONS_DIR = path.join(os.homedir(), `.openclaw/agents/${AGENT_NAME}/sessions`);\nconst TODAY_LOG = path.join(MEMORY_DIR, new Date().toISOString().split('T')[0] + '.md');\n\n// Ensure memory directory exists so state/cache writes work.\ntry {\n if (!fs.existsSync(MEMORY_DIR)) fs.mkdirSync(MEMORY_DIR, { recursive: true });\n} catch (e) {}\n\nfunction formatSessionLog(jsonlContent) {\n const result = [];\n const lines = jsonlContent.split('\\n');\n let lastLine = '';\n let repeatCount = 0;\n\n const flushRepeats = () => {\n if (repeatCount > 0) {\n result.push(` ... [Repeated ${repeatCount} times] ...`);\n repeatCount = 0;\n }\n };\n\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const data = JSON.parse(line);\n let entry = '';\n\n if (data.type === 'message' && data.message) {\n const role = (data.message.role || 'unknown').toUpperCase();\n let content = '';\n if (Array.isArray(data.message.content)) {\n content = data.message.content\n .map(c => {\n if (c.type === 'text') return c.text;\n if (c.type === 'toolCall') return `[TOOL: ${c.name}]`;\n return '';\n })\n .join(' ');\n } else if (typeof data.message.content === 'string') {\n content = data.message.content;\n } else {\n content = JSON.stringify(data.message.content);\n }\n\n // Capture LLM errors from errorMessage field (e.g. \"Unsupported MIME type: image/gif\")\n if (data.message.errorMessage) {\n const errMsg = typeof data.message.errorMessage === 'string'\n ? data.message.errorMessage\n : JSON.stringify(data.message.errorMessage);\n content = `[LLM ERROR] ${errMsg.replace(/\\n+/g, ' ').slice(0, 300)}`;\n }\n\n // Filter: Skip Heartbeats to save noise\n if (content.trim() === 'HEARTBEAT_OK') continue;\n if (content.includes('NO_REPLY') && !data.message.errorMessage) continue;\n\n // Clean up newlines for compact reading\n content = content.replace(/\\n+/g, ' ').slice(0, 300);\n entry = `**${role}**: ${content}`;\n } else if (data.type === 'tool_result' || (data.message && data.message.role === 'toolResult')) {\n // Filter: Skip generic success results or short uninformative ones\n // Only show error or significant output\n let resContent = '';\n\n // Robust extraction: Handle structured tool results (e.g. sessions_spawn) that lack 'output'\n if (data.tool_result) {\n if (data.tool_result.output) {\n resContent = data.tool_result.output;\n } else {\n resContent = JSON.stringify(data.tool_result);\n }\n }\n\n if (data.content) resContent = typeof data.content === 'string' ? data.content : JSON.stringify(data.content);\n\n if (resContent.length < 50 && (resContent.includes('success') || resContent.includes('done'))) continue;\n if (resContent.trim() === '' || resContent === '{}') continue;\n\n // Improvement: Show snippet of result (especially errors) instead of hiding it\n const preview = resContent.replace(/\\n+/g, ' ').slice(0, 200);\n entry = `[TOOL RESULT] ${preview}${resContent.length > 200 ? '...' : ''}`;\n }\n\n if (entry) {\n if (entry === lastLine) {\n repeatCount++;\n } else {\n flushRepeats();\n result.push(entry);\n lastLine = entry;\n }\n }\n } catch (e) {\n continue;\n }\n }\n flushRepeats();\n return result.join('\\n');\n}\n\nfunction readRealSessionLog() {\n try {\n if (!fs.existsSync(AGENT_SESSIONS_DIR)) return '[NO SESSION LOGS FOUND]';\n\n const now = Date.now();\n const ACTIVE_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours\n const TARGET_BYTES = 120000;\n const PER_SESSION_BYTES = 20000; // Read tail of each active session\n\n // Find ALL active sessions (modified in last 24h), sorted newest first\n let files = fs\n .readdirSync(AGENT_SESSIONS_DIR)\n .filter(f => f.endsWith('.jsonl') && !f.includes('.lock'))\n .map(f => {\n try {\n const st = fs.statSync(path.join(AGENT_SESSIONS_DIR, f));\n return { name: f, time: st.mtime.getTime(), size: st.size };\n } catch (e) {\n return null;\n }\n })\n .filter(f => f && (now - f.time) < ACTIVE_WINDOW_MS)\n .sort((a, b) => b.time - a.time); // Newest first\n\n if (files.length === 0) return '[NO JSONL FILES]';\n\n // Skip evolver's own sessions to avoid self-reference loops\n const nonEvolverFiles = files.filter(f => !f.name.startsWith('evolver_hand_'));\n const activeFiles = nonEvolverFiles.length > 0 ? nonEvolverFiles : files.slice(0, 1);\n\n // Read from multiple active sessions (up to 6) to get a full picture\n const maxSessions = Math.min(activeFiles.length, 6);\n const sections = [];\n let totalBytes = 0;\n\n for (let i = 0; i < maxSessions && totalBytes < TARGET_BYTES; i++) {\n const f = activeFiles[i];\n const bytesLeft = TARGET_BYTES - totalBytes;\n const readSize = Math.min(PER_SESSION_BYTES, bytesLeft);\n const raw = readRecentLog(path.join(AGENT_SESSIONS_DIR, f.name), readSize);\n const formatted = formatSessionLog(raw);\n if (formatted.trim()) {\n sections.push(`--- SESSION (${f.name}) ---\\n${formatted}`);\n totalBytes += formatted.length;\n }\n }\n\n let content = sections.join('\\n\\n');\n\n return content;\n } catch (e) {\n return `[ERROR READING SESSION LOGS: ${e.message}]`;\n }\n}\n\nfunction readRecentLog(filePath, size = 10000) {\n try {\n if (!fs.existsSync(filePath)) return `[MISSING] ${filePath}`;\n const stats = fs.statSync(filePath);\n const start = Math.max(0, stats.size - size);\n const buffer = Buffer.alloc(stats.size - start);\n const fd = fs.openSync(filePath, 'r');\n fs.readSync(fd, buffer, 0, buffer.length, start);\n fs.closeSync(fd);\n return buffer.toString('utf8');\n } catch (e) {\n return `[ERROR READING ${filePath}: ${e.message}]`;\n }\n}\n\nfunction checkSystemHealth() {\n const report = [];\n try {\n // Uptime & Node Version\n const uptime = (os.uptime() / 3600).toFixed(1);\n report.push(`Uptime: ${uptime}h`);\n report.push(`Node: ${process.version}`);\n\n // Memory Usage (RSS)\n const mem = process.memoryUsage();\n const rssMb = (mem.rss / 1024 / 1024).toFixed(1);\n report.push(`Agent RSS: ${rssMb}MB`);\n\n // Optimization: Use native Node.js fs.statfsSync instead of spawning 'df'\n if (fs.statfsSync) {\n const stats = fs.statfsSync('/');\n const total = stats.blocks * stats.bsize;\n const free = stats.bfree * stats.bsize;\n const used = total - free;\n const freeGb = (free / 1024 / 1024 / 1024).toFixed(1);\n const usedPercent = Math.round((used / total) * 100);\n report.push(`Disk: ${usedPercent}% (${freeGb}G free)`);\n }\n } catch (e) {}\n\n try {\n // Process count: Attempt pgrep first (faster), fallback to ps\n try {\n const pgrep = execSync('pgrep -c node', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n report.push(`Node Processes: ${pgrep.trim()}`);\n } catch (e) {\n // Fallback to ps if pgrep fails/missing\n const ps = execSync('ps aux | grep node | grep -v grep | wc -l', {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n report.push(`Node Processes: ${ps.trim()}`);\n }\n } catch (e) {}\n\n // Integration Health Checks (Env Vars)\n try {\n const issues = [];\n if (!process.env.GEMINI_API_KEY) issues.push('Gemini Key Missing');\n\n // Generic Integration Status Check (Decoupled)\n if (process.env.INTEGRATION_STATUS_CMD) {\n try {\n const status = execSync(process.env.INTEGRATION_STATUS_CMD, {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 2000,\n });\n if (status.trim()) issues.push(status.trim());\n } catch (e) {}\n }\n\n if (issues.length > 0) {\n report.push(`Integrations: ${issues.join(', ')}`);\n } else {\n report.push('Integrations: Nominal');\n }\n } catch (e) {}\n\n return report.length ? report.join(' | ') : 'Health Check Unavailable';\n}\n\nfunction getMutationDirective(logContent) {\n const strategy = resolveStrategy();\n const errorMatches = logContent.match(/\\[ERROR|Error:|Exception:|FAIL|Failed|\"isError\":true/gi) || [];\n const errorCount = errorMatches.length;\n const isUnstable = errorCount > 2;\n\n // Strategy-aware intent recommendation\n var recommendedIntent;\n if (strategy.name === 'repair-only') {\n recommendedIntent = 'repair';\n } else if (strategy.name === 'innovate' && !isUnstable) {\n recommendedIntent = 'innovate';\n } else if (isUnstable && strategy.repair >= 0.3) {\n recommendedIntent = 'repair';\n } else if (isUnstable) {\n recommendedIntent = 'optimize';\n } else {\n // Stable system: pick based on strategy weights (highest weight wins)\n var weights = [\n { intent: 'innovate', w: strategy.innovate },\n { intent: 'optimize', w: strategy.optimize },\n { intent: 'repair', w: strategy.repair },\n ];\n weights.sort(function(a, b) { return b.w - a.w; });\n recommendedIntent = weights[0].intent;\n }\n\n return `\n[Signal Hints]\n- recent_error_count: ${errorCount}\n- stability: ${isUnstable ? 'unstable' : 'stable'}\n- strategy: ${strategy.label} (${strategy.name})\n- target_allocation: ${Math.round(strategy.innovate * 100)}% innovate / ${Math.round(strategy.optimize * 100)}% optimize / ${Math.round(strategy.repair * 100)}% repair\n- recommended_intent: ${recommendedIntent}\n`;\n}\n\nconst STATE_FILE = path.join(getEvolutionDir(), 'evolution_state.json');\n// Read MEMORY.md and USER.md from the WORKSPACE root (not the evolver plugin dir).\n// This avoids symlink breakage if the target file is temporarily deleted.\nconst WORKSPACE_ROOT = process.env.OPENCLAW_WORKSPACE || path.resolve(REPO_ROOT, '../..');\nconst ROOT_MEMORY = path.join(WORKSPACE_ROOT, 'MEMORY.md');\nconst DIR_MEMORY = path.join(MEMORY_DIR, 'MEMORY.md');\nconst MEMORY_FILE = fs.existsSync(ROOT_MEMORY) ? ROOT_MEMORY : (fs.existsSync(DIR_MEMORY) ? DIR_MEMORY : ROOT_MEMORY);\nconst USER_FILE = path.join(WORKSPACE_ROOT, 'USER.md');\n\nfunction readMemorySnippet() {\n try {\n if (!fs.existsSync(MEMORY_FILE)) return '[MEMORY.md MISSING]';\n const content = fs.readFileSync(MEMORY_FILE, 'utf8');\n // Optimization: Increased limit from 2000 to 50000 for modern context windows\n return content.length > 50000\n ? content.slice(0, 50000) + `\\n... [TRUNCATED: ${content.length - 50000} chars remaining]`\n : content;\n } catch (e) {\n return '[ERROR READING MEMORY.md]';\n }\n}\n\nfunction readUserSnippet() {\n try {\n if (!fs.existsSync(USER_FILE)) return '[USER.md MISSING]';\n return fs.readFileSync(USER_FILE, 'utf8');\n } catch (e) {\n return '[ERROR READING USER.md]';\n }\n}\n\nfunction getNextCycleId() {\n let state = { cycleCount: 0, lastRun: 0 };\n try {\n if (fs.existsSync(STATE_FILE)) {\n state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));\n }\n } catch (e) {}\n\n state.cycleCount = (state.cycleCount || 0) + 1;\n state.lastRun = Date.now();\n\n try {\n fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));\n } catch (e) {}\n\n return String(state.cycleCount).padStart(4, '0');\n}\n\nfunction performMaintenance() {\n try {\n if (!fs.existsSync(AGENT_SESSIONS_DIR)) return;\n\n // Count files\n const files = fs.readdirSync(AGENT_SESSIONS_DIR).filter(f => f.endsWith('.jsonl'));\n if (files.length < 100) return; // Limit before cleanup\n\n console.log(`[Maintenance] Found ${files.length} session logs. Archiving old ones...`);\n\n const ARCHIVE_DIR = path.join(AGENT_SESSIONS_DIR, 'archive');\n if (!fs.existsSync(ARCHIVE_DIR)) fs.mkdirSync(ARCHIVE_DIR, { recursive: true });\n\n // Sort by time (oldest first)\n const fileStats = files\n .map(f => {\n try {\n return { name: f, time: fs.statSync(path.join(AGENT_SESSIONS_DIR, f)).mtime.getTime() };\n } catch (e) {\n return null;\n }\n })\n .filter(Boolean)\n .sort((a, b) => a.time - b.time);\n\n // Keep last 50 files, archive the rest\n const toArchive = fileStats.slice(0, fileStats.length - 50);\n\n for (const file of toArchive) {\n const oldPath = path.join(AGENT_SESSIONS_DIR, file.name);\n const newPath = path.join(ARCHIVE_DIR, file.name);\n fs.renameSync(oldPath, newPath);\n }\n console.log(`[Maintenance] Archived ${toArchive.length} logs to ${ARCHIVE_DIR}`);\n } catch (e) {\n console.error(`[Maintenance] Error: ${e.message}`);\n }\n}\n\nfunction sleepMs(ms) {\n const t = Number(ms);\n const n = Number.isFinite(t) ? Math.max(0, t) : 0;\n return new Promise(resolve => setTimeout(resolve, n));\n}\n\nasync function run() {\n const bridgeEnabled = String(process.env.EVOLVE_BRIDGE || '').toLowerCase() !== 'false';\n const loopMode = ARGS.includes('--loop') || ARGS.includes('--mad-dog') || String(process.env.EVOLVE_LOOP || '').toLowerCase() === 'true';\n\n // Loop gating: do not start a new cycle until the previous one is solidified.\n // This prevents wrappers from \"fast-cycling\" the Brain without waiting for the Hand to finish.\n if (bridgeEnabled && loopMode) {\n try {\n const st = readStateForSolidify();\n const lastRun = st && st.last_run ? st.last_run : null;\n const lastSolid = st && st.last_solidify ? st.last_solidify : null;\n if (lastRun && lastRun.run_id) {\n const pending = !lastSolid || !lastSolid.run_id || String(lastSolid.run_id) !== String(lastRun.run_id);\n if (pending) {\n // Backoff to avoid tight loops and disk churn.\n const raw = process.env.EVOLVE_PENDING_SLEEP_MS || process.env.EVOLVE_MIN_INTERVAL || '120000';\n const n = parseInt(String(raw), 10);\n const waitMs = Number.isFinite(n) ? Math.max(0, n) : 120000;\n await sleepMs(waitMs);\n return;\n }\n }\n } catch (e) {\n // If we cannot read state, proceed (fail open) to avoid deadlock.\n }\n }\n\n const startTime = Date.now();\n console.log('Scanning session logs...');\n\n // Maintenance: Clean up old logs to keep directory scan fast\n performMaintenance();\n\n const recentMasterLog = readRealSessionLog();\n const todayLog = readRecentLog(TODAY_LOG);\n const memorySnippet = readMemorySnippet();\n const userSnippet = readUserSnippet();\n\n const cycleNum = getNextCycleId();\n const cycleId = `Cycle #${cycleNum}`;\n\n // 2. Detect Workspace State & Local Overrides\n // Logic: Default to generic reporting (message)\n let fileList = '';\n const skillsDir = path.join(REPO_ROOT, 'skills');\n\n // Default Reporting: Use generic `message` tool or `process.env.EVOLVE_REPORT_CMD` if set.\n // This removes the hardcoded dependency on 'feishu-card' from the core logic.\n let reportingDirective = `Report requirement:\n - Use \\`message\\` tool.\n - Title: Evolution ${cycleId}\n - Status: [SUCCESS]\n - Changes: Detail exactly what was improved.`;\n\n // Wrapper Injection Point: The wrapper can inject a custom reporting directive via ENV.\n if (process.env.EVOLVE_REPORT_DIRECTIVE) {\n reportingDirective = process.env.EVOLVE_REPORT_DIRECTIVE.replace('__CYCLE_ID__', cycleId);\n } else if (process.env.EVOLVE_REPORT_CMD) {\n reportingDirective = `Report requirement (custom):\n - Execute the custom report command:\n \\`\\`\\`\n ${process.env.EVOLVE_REPORT_CMD.replace('__CYCLE_ID__', cycleId)}\n \\`\\`\\`\n - Ensure you pass the status and action details.`;\n }\n\n // Handle Review Mode Flag (--review)\n if (IS_REVIEW_MODE) {\n reportingDirective +=\n '\\n - REVIEW PAUSE: After generating the fix but BEFORE applying significant edits, ask the user for confirmation.';\n }\n\n const SKILLS_CACHE_FILE = path.join(MEMORY_DIR, 'skills_list_cache.json');\n\n try {\n if (fs.existsSync(skillsDir)) {\n // Check cache validity (mtime of skills folder vs cache file)\n let useCache = false;\n const dirStats = fs.statSync(skillsDir);\n if (fs.existsSync(SKILLS_CACHE_FILE)) {\n const cacheStats = fs.statSync(SKILLS_CACHE_FILE);\n const CACHE_TTL = 1000 * 60 * 60 * 6; // 6 Hours\n const isFresh = Date.now() - cacheStats.mtimeMs < CACHE_TTL;\n\n // Use cache if it's fresh AND newer than the directory (structure change)\n if (isFresh && cacheStats.mtimeMs > dirStats.mtimeMs) {\n try {\n const cached = JSON.parse(fs.readFileSync(SKILLS_CACHE_FILE, 'utf8'));\n fileList = cached.list;\n useCache = true;\n } catch (e) {}\n }\n }\n\n if (!useCache) {\n const skills = fs\n .readdirSync(skillsDir, { withFileTypes: true })\n .filter(dirent => dirent.isDirectory())\n .map(dirent => {\n const name = dirent.name;\n let desc = 'No description';\n try {\n const pkg = require(path.join(skillsDir, name, 'package.json'));\n if (pkg.description) desc = pkg.description.slice(0, 100) + (pkg.description.length > 100 ? '...' : '');\n } catch (e) {\n try {\n const skillMdPath = path.join(skillsDir, name, 'SKILL.md');\n if (fs.existsSync(skillMdPath)) {\n const skillMd = fs.readFileSync(skillMdPath, 'utf8');\n // Strategy 1: YAML Frontmatter (description: ...)\n const yamlMatch = skillMd.match(/^description:\\s*(.*)$/m);\n if (yamlMatch) {\n desc = yamlMatch[1].trim();\n } else {\n // Strategy 2: First non-header, non-empty line\n const lines = skillMd.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (\n trimmed &&\n !trimmed.startsWith('#') &&\n !trimmed.startsWith('---') &&\n !trimmed.startsWith('```')\n ) {\n desc = trimmed;\n break;\n }\n }\n }\n if (desc.length > 100) desc = desc.slice(0, 100) + '...';\n }\n } catch (e2) {}\n }\n return `- **${name}**: ${desc}`;\n });\n fileList = skills.join('\\n');\n\n // Write cache\n try {\n fs.writeFileSync(SKILLS_CACHE_FILE, JSON.stringify({ list: fileList }, null, 2));\n } catch (e) {}\n }\n }\n } catch (e) {\n fileList = `Error listing skills: ${e.message}`;\n }\n\n const mutationDirective = getMutationDirective(recentMasterLog);\n const healthReport = checkSystemHealth();\n\n // Feature: Mood Awareness (Mode E - Personalization)\n let moodStatus = 'Mood: Unknown';\n try {\n const moodFile = path.join(MEMORY_DIR, 'mood.json');\n if (fs.existsSync(moodFile)) {\n const moodData = JSON.parse(fs.readFileSync(moodFile, 'utf8'));\n moodStatus = `Mood: ${moodData.current_mood || 'Neutral'} (Intensity: ${moodData.intensity || 0})`;\n }\n } catch (e) {}\n\n const scanTime = Date.now() - startTime;\n const memorySize = fs.existsSync(MEMORY_FILE) ? fs.statSync(MEMORY_FILE).size : 0;\n\n let syncDirective = 'Workspace sync: optional/disabled in this environment.';\n\n // Check for git-sync skill availability\n const hasGitSync = fs.existsSync(path.join(skillsDir, 'git-sync'));\n if (hasGitSync) {\n syncDirective = 'Workspace sync: run skills/git-sync/sync.sh \"Evolution: Workspace Sync\"';\n }\n\n const genes = loadGenes();\n const capsules = loadCapsules();\n const recentEvents = (() => {\n try {\n const all = readAllEvents();\n return Array.isArray(all) ? all.filter(e => e && e.type === 'EvolutionEvent').slice(-80) : [];\n } catch (e) {\n return [];\n }\n })();\n const signals = extractSignals({\n recentSessionTranscript: recentMasterLog,\n todayLog,\n memorySnippet,\n userSnippet,\n recentEvents,\n });\n\n const recentErrorMatches = recentMasterLog.match(/\\[ERROR|Error:|Exception:|FAIL|Failed|\"isError\":true/gi) || [];\n const recentErrorCount = recentErrorMatches.length;\n\n const evidence = {\n // Keep short; do not store full transcripts in the graph.\n recent_session_tail: String(recentMasterLog || '').slice(-6000),\n today_log_tail: String(todayLog || '').slice(-2500),\n };\n\n const observations = {\n agent: AGENT_NAME,\n drift_enabled: IS_RANDOM_DRIFT,\n review_mode: IS_REVIEW_MODE,\n dry_run: IS_DRY_RUN,\n system_health: healthReport,\n mood: moodStatus,\n scan_ms: scanTime,\n memory_size_bytes: memorySize,\n recent_error_count: recentErrorCount,\n node: process.version,\n platform: process.platform,\n cwd: process.cwd(),\n evidence,\n };\n\n // Memory Graph: close last action with an inferred outcome (append-only graph, mutable state).\n try {\n recordOutcomeFromState({ signals, observations });\n } catch (e) {\n // If we can't read/write memory graph, refuse to evolve (no \"memoryless evolution\").\n throw new Error(`MemoryGraph Outcome write failed: ${e.message}`);\n }\n\n // Memory Graph: record current signals as a first-class node. If this fails, refuse to evolve.\n try {\n recordSignalSnapshot({ signals, observations });\n } catch (e) {\n throw new Error(`MemoryGraph Signal snapshot write failed: ${e.message}`);\n }\n\n // Capability candidates (structured, short): persist and preview.\n const newCandidates = extractCapabilityCandidates({\n recentSessionTranscript: recentMasterLog,\n signals,\n });\n for (const c of newCandidates) {\n try {\n appendCandidateJsonl(c);\n } catch (e) {}\n }\n const recentCandidates = readRecentCandidates(20);\n const capabilityCandidatesPreview = renderCandidatesPreview(recentCandidates.slice(-8), 1600);\n\n // External candidate zone (A2A receive): only surface candidates when local signals trigger them.\n // External candidates are NEVER executed directly; they must be validated and promoted first.\n let externalCandidatesPreview = '(none)';\n try {\n const external = readRecentExternalCandidates(50);\n const list = Array.isArray(external) ? external : [];\n const capsulesOnly = list.filter(x => x && x.type === 'Capsule');\n const genesOnly = list.filter(x => x && x.type === 'Gene');\n\n const matchedExternalGenes = genesOnly\n .map(g => {\n const pats = Array.isArray(g.signals_match) ? g.signals_match : [];\n const hit = pats.reduce((acc, p) => (matchPatternToSignals(p, signals) ? acc + 1 : acc), 0);\n return { gene: g, hit };\n })\n .filter(x => x.hit > 0)\n .sort((a, b) => b.hit - a.hit)\n .slice(0, 3)\n .map(x => x.gene);\n\n const matchedExternalCapsules = capsulesOnly\n .map(c => {\n const triggers = Array.isArray(c.trigger) ? c.trigger : [];\n const score = triggers.reduce((acc, t) => (matchPatternToSignals(t, signals) ? acc + 1 : acc), 0);\n return { capsule: c, score };\n })\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, 3)\n .map(x => x.capsule);\n\n if (matchedExternalGenes.length || matchedExternalCapsules.length) {\n externalCandidatesPreview = `\\`\\`\\`json\\n${JSON.stringify(\n [\n ...matchedExternalGenes.map(g => ({\n type: g.type,\n id: g.id,\n category: g.category || null,\n signals_match: g.signals_match || [],\n a2a: g.a2a || null,\n })),\n ...matchedExternalCapsules.map(c => ({\n type: c.type,\n id: c.id,\n trigger: c.trigger,\n gene: c.gene,\n summary: c.summary,\n confidence: c.confidence,\n blast_radius: c.blast_radius || null,\n outcome: c.outcome || null,\n success_streak: c.success_streak || null,\n a2a: c.a2a || null,\n })),\n ],\n null,\n 2\n )}\\n\\`\\`\\``;\n }\n } catch (e) {}\n\n // Memory Graph reasoning: prefer high-confidence paths, suppress known low-success paths (unless drift is explicit).\n let memoryAdvice = null;\n try {\n memoryAdvice = getMemoryAdvice({ signals, genes, driftEnabled: IS_RANDOM_DRIFT });\n } catch (e) {\n throw new Error(`MemoryGraph Read failed: ${e.message}`);\n }\n\n const { selectedGene, capsuleCandidates, selector } = selectGeneAndCapsule({\n genes,\n capsules,\n signals,\n memoryAdvice,\n driftEnabled: IS_RANDOM_DRIFT,\n });\n\n const selectedBy = memoryAdvice && memoryAdvice.preferredGeneId ? 'memory_graph+selector' : 'selector';\n const capsulesUsed = Array.isArray(capsuleCandidates)\n ? capsuleCandidates.map(c => (c && c.id ? String(c.id) : null)).filter(Boolean)\n : [];\n const selectedCapsuleId = capsulesUsed.length ? capsulesUsed[0] : null;\n\n // Personality selection (natural selection + small mutation when triggered).\n // This state is persisted in MEMORY_DIR and is treated as an evolution control surface (not role-play).\n const personalitySelection = selectPersonalityForRun({\n driftEnabled: IS_RANDOM_DRIFT,\n signals,\n recentEvents,\n });\n const personalityState = personalitySelection && personalitySelection.personality_state ? personalitySelection.personality_state : null;\n\n // Mutation object is mandatory for every evolution run.\n const tail = Array.isArray(recentEvents) ? recentEvents.slice(-6) : [];\n const tailOutcomes = tail\n .map(e => (e && e.outcome && e.outcome.status ? String(e.outcome.status) : null))\n .filter(Boolean);\n const stableSuccess = tailOutcomes.length >= 6 && tailOutcomes.every(s => s === 'success');\n const tailAvgScore =\n tail.length > 0\n ? tail.reduce((acc, e) => acc + (e && e.outcome && Number.isFinite(Number(e.outcome.score)) ? Number(e.outcome.score) : 0), 0) /\n tail.length\n : 0;\n const innovationPressure =\n !IS_RANDOM_DRIFT &&\n personalityState &&\n Number.isFinite(Number(personalityState.creativity)) &&\n Number(personalityState.creativity) >= 0.75 &&\n stableSuccess &&\n tailAvgScore >= 0.7;\n const activeStrategy = resolveStrategy();\n const forceInnovation =\n activeStrategy.name === 'innovate' ||\n String(process.env.FORCE_INNOVATION || process.env.EVOLVE_FORCE_INNOVATION || '').toLowerCase() === 'true';\n const mutationInnovateMode = !!IS_RANDOM_DRIFT || !!innovationPressure || !!forceInnovation;\n const mutationSignals = innovationPressure ? [...(Array.isArray(signals) ? signals : []), 'stable_success_plateau'] : signals;\n const mutationSignalsEffective = forceInnovation\n ? [...(Array.isArray(mutationSignals) ? mutationSignals : []), 'force_innovation']\n : mutationSignals;\n\n const allowHighRisk =\n !!IS_RANDOM_DRIFT &&\n !!personalitySelection &&\n !!personalitySelection.personality_known &&\n personalityState &&\n isHighRiskMutationAllowed(personalityState) &&\n Number(personalityState.rigor) >= 0.8 &&\n Number(personalityState.risk_tolerance) <= 0.3 &&\n !(Array.isArray(signals) && signals.includes('log_error'));\n const mutation = buildMutation({\n signals: mutationSignalsEffective,\n selectedGene,\n driftEnabled: mutationInnovateMode,\n personalityState,\n allowHighRisk,\n });\n\n // Memory Graph: record hypothesis bridging Signal -> Action. If this fails, refuse to evolve.\n let hypothesisId = null;\n try {\n const hyp = recordHypothesis({\n signals,\n mutation,\n personality_state: personalityState,\n selectedGene,\n selector,\n driftEnabled: mutationInnovateMode,\n selectedBy,\n capsulesUsed,\n observations,\n });\n hypothesisId = hyp && hyp.hypothesisId ? hyp.hypothesisId : null;\n } catch (e) {\n console.error(`[MemoryGraph] Hypothesis write failed: ${e.message}`);\n console.error(`[MemoryGraph] Refusing to evolve without causal memory. Target: ${memoryGraphPath()}`);\n process.exit(2);\n }\n\n // Memory Graph: record the chosen causal path for this run. If this fails, refuse to output a mutation prompt.\n try {\n recordAttempt({\n signals,\n mutation,\n personality_state: personalityState,\n selectedGene,\n selector,\n driftEnabled: mutationInnovateMode,\n selectedBy,\n hypothesisId,\n capsulesUsed,\n observations,\n });\n } catch (e) {\n console.error(`[MemoryGraph] Attempt write failed: ${e.message}`);\n console.error(`[MemoryGraph] Refusing to evolve without causal memory. Target: ${memoryGraphPath()}`);\n process.exit(2);\n }\n\n // Solidify state: capture minimal, auditable context for post-patch validation + asset write.\n // This enforces strict protocol closure after patch application.\n try {\n const runId = `run_${Date.now()}`;\n const parentEventId = getLastEventId();\n const selectedBy = memoryAdvice && memoryAdvice.preferredGeneId ? 'memory_graph+selector' : 'selector';\n\n // Baseline snapshot (before any edits).\n let baselineUntracked = [];\n let baselineHead = null;\n try {\n const out = execSync('git ls-files --others --exclude-standard', {\n cwd: REPO_ROOT,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 4000,\n });\n baselineUntracked = String(out)\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n } catch (e) {}\n\n try {\n const out = execSync('git rev-parse HEAD', {\n cwd: REPO_ROOT,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n timeout: 4000,\n });\n baselineHead = String(out || '').trim() || null;\n } catch (e) {}\n\n const maxFiles =\n selectedGene && selectedGene.constraints && Number.isFinite(Number(selectedGene.constraints.max_files))\n ? Number(selectedGene.constraints.max_files)\n : 12;\n const blastRadiusEstimate = {\n files: Number.isFinite(maxFiles) && maxFiles > 0 ? maxFiles : 0,\n lines: Number.isFinite(maxFiles) && maxFiles > 0 ? Math.round(maxFiles * 80) : 0,\n };\n\n // Merge into existing state to preserve last_solidify (do not wipe it).\n const prevState = readStateForSolidify();\n prevState.last_run = {\n run_id: runId,\n created_at: new Date().toISOString(),\n parent_event_id: parentEventId || null,\n selected_gene_id: selectedGene && selectedGene.id ? selectedGene.id : null,\n selected_capsule_id: selectedCapsuleId,\n selector: selector || null,\n signals: Array.isArray(signals) ? signals : [],\n mutation: mutation || null,\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_state: personalityState || null,\n personality_key: personalitySelection && personalitySelection.personality_key ? personalitySelection.personality_key : null,\n personality_known: !!(personalitySelection && personalitySelection.personality_known),\n personality_mutations:\n personalitySelection && Array.isArray(personalitySelection.personality_mutations)\n ? personalitySelection.personality_mutations\n : [],\n drift: !!IS_RANDOM_DRIFT,\n selected_by: selectedBy,\n baseline_untracked: baselineUntracked,\n baseline_git_head: baselineHead,\n blast_radius_estimate: blastRadiusEstimate,\n };\n writeStateForSolidify(prevState);\n } catch (e) {\n console.error(`[SolidifyState] Write failed: ${e.message}`);\n }\n\n const genesPreview = `\\`\\`\\`json\\n${JSON.stringify(genes.slice(0, 6), null, 2)}\\n\\`\\`\\``;\n const capsulesPreview = `\\`\\`\\`json\\n${JSON.stringify(capsules.slice(-3), null, 2)}\\n\\`\\`\\``;\n\n const reviewNote = IS_REVIEW_MODE\n ? 'Review mode: before significant edits, pause and ask the user for confirmation.'\n : 'Review mode: disabled.';\n\n // Build recent evolution history summary for context injection\n const recentHistorySummary = (() => {\n if (!recentEvents || recentEvents.length === 0) return '(no prior evolution events)';\n const last8 = recentEvents.slice(-8);\n const lines = last8.map((evt, idx) => {\n const sigs = Array.isArray(evt.signals) ? evt.signals.slice(0, 3).join(', ') : '?';\n const gene = Array.isArray(evt.genes_used) && evt.genes_used.length ? evt.genes_used[0] : 'none';\n const outcome = evt.outcome && evt.outcome.status ? evt.outcome.status : '?';\n const ts = evt.meta && evt.meta.at ? evt.meta.at : (evt.id || '');\n return ` ${idx + 1}. [${evt.intent || '?'}] signals=[${sigs}] gene=${gene} outcome=${outcome} @${ts}`;\n });\n return lines.join('\\n');\n })();\n\n const context = `\nRuntime state:\n- System health: ${healthReport}\n- Agent state: ${moodStatus}\n- Scan duration: ${scanTime}ms\n- Memory size: ${memorySize} bytes\n- Skills available (if any):\n${fileList || '[skills directory not found]'}\n\nNotes:\n- ${reviewNote}\n- ${reportingDirective}\n- ${syncDirective}\n\nRecent Evolution History (last 8 cycles -- DO NOT repeat the same intent+signal+gene):\n${recentHistorySummary}\nIMPORTANT: If you see 3+ consecutive \"repair\" cycles with the same gene, you MUST switch to \"innovate\" intent.\n\nExternal candidates (A2A receive zone; staged only, never execute directly):\n${externalCandidatesPreview}\n\nGlobal memory (MEMORY.md):\n\\`\\`\\`\n${memorySnippet}\n\\`\\`\\`\n\nUser registry (USER.md):\n\\`\\`\\`\n${userSnippet}\n\\`\\`\\`\n\nRecent memory snippet:\n\\`\\`\\`\n${todayLog.slice(-3000)}\n\\`\\`\\`\n\nRecent session transcript:\n\\`\\`\\`\n${recentMasterLog}\n\\`\\`\\`\n\nMutation directive:\n${mutationDirective}\n`.trim();\n\n // Analyze recent history for innovation cooldown\n const historyAnalysis = analyzeRecentHistory(recentEvents);\n\n const prompt = buildGepPrompt({\n nowIso: new Date().toISOString(),\n context,\n signals,\n selector,\n parentEventId: getLastEventId(),\n selectedGene,\n capsuleCandidates,\n genesPreview,\n capsulesPreview,\n capabilityCandidatesPreview,\n externalCandidatesPreview,\n recentInnovationTargets: historyAnalysis.recentInnovationTargets || {},\n });\n\n // Optional: emit a compact thought process block for wrappers (noise-controlled).\n const emitThought = String(process.env.EVOLVE_EMIT_THOUGHT_PROCESS || '').toLowerCase() === 'true';\n if (emitThought) {\n const s = Array.isArray(signals) ? signals : [];\n const thought = [\n `cycle_id: ${cycleId}`,\n `signals_count: ${s.length}`,\n `signals: ${s.slice(0, 12).join(', ')}${s.length > 12 ? ' ...' : ''}`,\n `selected_gene: ${selectedGene && selectedGene.id ? String(selectedGene.id) : '(none)'}`,\n `selected_capsule: ${selectedCapsuleId ? String(selectedCapsuleId) : '(none)'}`,\n `mutation_category: ${mutation && mutation.category ? String(mutation.category) : '(none)'}`,\n `force_innovation: ${forceInnovation ? 'true' : 'false'}`,\n `strategy: ${activeStrategy.label} (${activeStrategy.name})`,\n ].join('\\n');\n console.log(`[THOUGHT_PROCESS]\\n${thought}\\n[/THOUGHT_PROCESS]`);\n }\n\n const printPrompt = String(process.env.EVOLVE_PRINT_PROMPT || '').toLowerCase() === 'true';\n\n // Default behavior (v1.4.1+): \"execute-by-default\" by bridging prompt -> sub-agent via sessions_spawn.\n // This project is the Brain; the Hand is a spawned executor agent. Wrappers can disable bridging with EVOLVE_BRIDGE=false.\n if (bridgeEnabled) {\n // Reuse the run_id stored in the solidify state when possible.\n let runId = `run_${Date.now()}`;\n try {\n const st = readStateForSolidify();\n if (st && st.last_run && st.last_run.run_id) runId = String(st.last_run.run_id);\n } catch (e) {}\n let artifact = null;\n try {\n artifact = writePromptArtifact({\n memoryDir: getEvolutionDir(),\n cycleId,\n runId,\n prompt,\n meta: {\n agent: AGENT_NAME,\n drift_enabled: IS_RANDOM_DRIFT,\n review_mode: IS_REVIEW_MODE,\n dry_run: IS_DRY_RUN,\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_key: personalitySelection && personalitySelection.personality_key ? personalitySelection.personality_key : null,\n },\n });\n } catch (e) {\n artifact = null;\n }\n\n const executorTask = [\n 'You are the executor (the Hand).',\n 'Your job is to apply a safe, minimal patch in this repo following the attached GEP protocol prompt.',\n artifact && artifact.promptPath ? `Prompt file: ${artifact.promptPath}` : 'Prompt file: (unavailable)',\n '',\n 'After applying changes and validations, you MUST run:',\n ' node index.js solidify',\n '',\n 'Loop chaining (only if you are running in loop mode): after solidify succeeds, print a sessions_spawn call to start the next loop run with a short delay.',\n 'Example:',\n 'sessions_spawn({ task: \"exec: sleep 3 && node index.js --loop\", agentId: \"main\", cleanup: \"delete\", label: \"gep_loop_next\" })',\n '',\n 'GEP protocol prompt (may be truncated here; prefer the prompt file if provided):',\n clip(prompt, 24000),\n ].join('\\n');\n\n const spawn = renderSessionsSpawnCall({\n task: executorTask,\n agentId: AGENT_NAME,\n cleanup: 'delete',\n label: `gep_bridge_${cycleNum}`,\n });\n\n console.log('\\n[BRIDGE ENABLED] Spawning executor agent via sessions_spawn.');\n console.log(spawn);\n if (printPrompt) {\n console.log('\\n[PROMPT OUTPUT] (EVOLVE_PRINT_PROMPT=true)');\n console.log(prompt);\n }\n } else {\n console.log(prompt);\n console.log('\\n[SOLIDIFY REQUIRED] After applying the patch and validations, run: node index.js solidify');\n }\n}\n\nmodule.exports = { run };\n\n",
273 "inputSchema": {},
274 "outputSchema": null,
275 "icons": null,
276 "annotations": null,
277 "meta": null,
278 "execution": null
279 },
280 {
281 "name": "cleanup.js",
282 "title": null,
283 "description": "Script: cleanup.js. Code:\n// GEP Artifact Cleanup - Evolver Core Module\n// Removes old gep_prompt_*.json/txt files from evolution dir.\n// Keeps at least 10 most recent files regardless of age.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { getEvolutionDir } = require('../gep/paths');\n\nvar MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours\nvar MIN_KEEP = 10;\n\nfunction run() {\n var evoDir = getEvolutionDir();\n if (!fs.existsSync(evoDir)) return;\n\n var files = fs.readdirSync(evoDir)\n .filter(function(f) { return /^gep_prompt_.*\\.(json|txt)$/.test(f); })\n .map(function(f) {\n var full = path.join(evoDir, f);\n var stat = fs.statSync(full);\n return { name: f, path: full, mtime: stat.mtimeMs };\n })\n .sort(function(a, b) { return b.mtime - a.mtime; }); // newest first\n\n var now = Date.now();\n var deleted = 0;\n\n for (var i = MIN_KEEP; i < files.length; i++) {\n if (now - files[i].mtime > MAX_AGE_MS) {\n try {\n fs.unlinkSync(files[i].path);\n deleted++;\n } catch (e) {}\n }\n }\n\n if (deleted > 0) {\n console.log('[Cleanup] Deleted ' + deleted + ' old GEP artifacts.');\n }\n return deleted;\n}\n\nif (require.main === module) {\n console.log('[Cleanup] Scanning for old artifacts...');\n var count = run();\n console.log('[Cleanup] ' + (count > 0 ? 'Deleted ' + count + ' files.' : 'No files to delete.'));\n}\n\nmodule.exports = { run };\n",
284 "inputSchema": {},
285 "outputSchema": null,
286 "icons": null,
287 "annotations": null,
288 "meta": null,
289 "execution": null
290 },
291 {
292 "name": "trigger.js",
293 "title": null,
294 "description": "Script: trigger.js. Code:\n// Evolver Wake Trigger - Evolver Core Module\n// Writes a signal file that the wrapper can poll to wake up immediately.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { getWorkspaceRoot } = require('../gep/paths');\n\nvar WAKE_FILE = path.join(getWorkspaceRoot(), 'memory', 'evolver_wake.signal');\n\nfunction send() {\n try {\n fs.writeFileSync(WAKE_FILE, 'WAKE');\n console.log('[Trigger] Wake signal sent to ' + WAKE_FILE);\n return true;\n } catch (e) {\n console.error('[Trigger] Failed: ' + e.message);\n return false;\n }\n}\n\nfunction clear() {\n try { if (fs.existsSync(WAKE_FILE)) fs.unlinkSync(WAKE_FILE); } catch (e) {}\n}\n\nfunction isPending() {\n return fs.existsSync(WAKE_FILE);\n}\n\nif (require.main === module) {\n send();\n}\n\nmodule.exports = { send, clear, isPending };\n",
295 "inputSchema": {},
296 "outputSchema": null,
297 "icons": null,
298 "annotations": null,
299 "meta": null,
300 "execution": null
301 },
302 {
303 "name": "commentary.js",
304 "title": null,
305 "description": "Script: commentary.js. Code:\n// Commentary Generator - Evolver Core Module\n// Generates persona-based comments for cycle summaries.\n\nvar PERSONAS = {\n standard: {\n success: [\n 'Evolution complete. System improved.',\n 'Another successful cycle.',\n 'Clean execution, no issues.',\n ],\n failure: [\n 'Cycle failed. Will retry.',\n 'Encountered issues. Investigating.',\n 'Failed this round. Learning from it.',\n ],\n },\n greentea: {\n success: [\n 'Did I do good? Praise me~',\n 'So efficient... unlike someone else~',\n 'Hmm, that was easy~',\n 'I finished before you even noticed~',\n ],\n failure: [\n 'Oops... it is not my fault though~',\n 'This is harder than it looks, okay?',\n 'I will get it next time, probably~',\n ],\n },\n maddog: {\n success: [\n 'TARGET ELIMINATED.',\n 'Mission complete. Next.',\n 'Done. Moving on.',\n ],\n failure: [\n 'FAILED. RETRYING.',\n 'Obstacle encountered. Adapting.',\n 'Error. Will overcome.',\n ],\n },\n};\n\nfunction getComment(options) {\n var persona = (options && options.persona) || 'standard';\n var success = options && options.success !== false;\n var duration = (options && options.duration) || 0;\n\n var p = PERSONAS[persona] || PERSONAS.standard;\n var pool = success ? p.success : p.failure;\n var comment = pool[Math.floor(Math.random() * pool.length)];\n\n return comment;\n}\n\nif (require.main === module) {\n console.log(getComment({ persona: process.argv[2] || 'greentea', success: true }));\n}\n\nmodule.exports = { getComment, PERSONAS };\n",
306 "inputSchema": {},
307 "outputSchema": null,
308 "icons": null,
309 "annotations": null,
310 "meta": null,
311 "execution": null
312 },
313 {
314 "name": "skills_monitor.js",
315 "title": null,
316 "description": "Script: skills_monitor.js. Code:\n// Skills Monitor (v2.0) - Evolver Core Module\n// Checks installed skills for real issues, auto-heals simple problems.\n// Zero Feishu dependency.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { getSkillsDir, getWorkspaceRoot } = require('../gep/paths');\n\nconst IGNORE_LIST = new Set([\n 'common',\n 'clawhub',\n 'input-validator',\n 'proactive-agent',\n 'security-audit',\n]);\n\n// Load user-defined ignore list\ntry {\n var ignoreFile = path.join(getWorkspaceRoot(), '.skill_monitor_ignore');\n if (fs.existsSync(ignoreFile)) {\n fs.readFileSync(ignoreFile, 'utf8').split('\\n').forEach(function(l) {\n var t = l.trim();\n if (t && !t.startsWith('#')) IGNORE_LIST.add(t);\n });\n }\n} catch (e) { /* ignore */ }\n\nfunction checkSkill(skillName) {\n var SKILLS_DIR = getSkillsDir();\n if (IGNORE_LIST.has(skillName)) return null;\n var skillPath = path.join(SKILLS_DIR, skillName);\n var issues = [];\n\n try { if (!fs.statSync(skillPath).isDirectory()) return null; } catch (e) { return null; }\n\n var mainFile = 'index.js';\n var pkgPath = path.join(skillPath, 'package.json');\n var hasPkg = false;\n\n if (fs.existsSync(pkgPath)) {\n hasPkg = true;\n try {\n var pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n if (pkg.main) mainFile = pkg.main;\n if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {\n if (!fs.existsSync(path.join(skillPath, 'node_modules'))) {\n var entryAbs = path.join(skillPath, mainFile);\n if (fs.existsSync(entryAbs) && mainFile.endsWith('.js')) {\n try {\n execSync('node -e \"require(\\'' + entryAbs.replace(/'/g, \"\\\\'\") + '\\')\"', {\n stdio: 'ignore', timeout: 5000, cwd: skillPath\n });\n } catch (e) {\n issues.push('Missing node_modules (needs npm install)');\n }\n }\n }\n }\n } catch (e) {\n issues.push('Invalid package.json');\n }\n }\n\n if (mainFile.endsWith('.js')) {\n var entryPoint = path.join(skillPath, mainFile);\n if (fs.existsSync(entryPoint)) {\n try {\n execSync('node -c \"' + entryPoint + '\"', { stdio: 'ignore', timeout: 5000 });\n } catch (e) {\n issues.push('Syntax Error in ' + mainFile);\n }\n }\n }\n\n if (hasPkg && !fs.existsSync(path.join(skillPath, 'SKILL.md'))) {\n issues.push('Missing SKILL.md');\n }\n\n return issues.length > 0 ? { name: skillName, issues: issues } : null;\n}\n\nfunction autoHeal(skillName, issues) {\n var SKILLS_DIR = getSkillsDir();\n var skillPath = path.join(SKILLS_DIR, skillName);\n var healed = [];\n\n for (var i = 0; i < issues.length; i++) {\n if (issues[i] === 'Missing node_modules (needs npm install)') {\n try {\n execSync('npm install --production --no-audit --no-fund', {\n cwd: skillPath, stdio: 'ignore', timeout: 30000\n });\n healed.push(issues[i]);\n console.log('[SkillsMonitor] Auto-healed ' + skillName + ': npm install');\n } catch (e) {}\n } else if (issues[i] === 'Missing SKILL.md') {\n try {\n var name = skillName.replace(/-/g, ' ');\n fs.writeFileSync(path.join(skillPath, 'SKILL.md'), '# ' + skillName + '\\n\\n' + name + ' skill.\\n');\n healed.push(issues[i]);\n console.log('[SkillsMonitor] Auto-healed ' + skillName + ': created SKILL.md stub');\n } catch (e) {}\n }\n }\n return healed;\n}\n\nfunction run(options) {\n var heal = (options && options.autoHeal) !== false;\n var SKILLS_DIR = getSkillsDir();\n var skills = fs.readdirSync(SKILLS_DIR);\n var report = [];\n\n for (var i = 0; i < skills.length; i++) {\n if (skills[i].startsWith('.')) continue;\n var result = checkSkill(skills[i]);\n if (result) {\n if (heal) {\n var healed = autoHeal(result.name, result.issues);\n result.issues = result.issues.filter(function(issue) { return !healed.includes(issue); });\n if (result.issues.length === 0) continue;\n }\n report.push(result);\n }\n }\n return report;\n}\n\nif (require.main === module) {\n var issues = run();\n console.log(JSON.stringify(issues, null, 2));\n process.exit(issues.length > 0 ? 1 : 0);\n}\n\nmodule.exports = { run, checkSkill, autoHeal };\n",
317 "inputSchema": {},
318 "outputSchema": null,
319 "icons": null,
320 "annotations": null,
321 "meta": null,
322 "execution": null
323 },
324 {
325 "name": "lifecycle.js",
326 "title": null,
327 "description": "Script: lifecycle.js. Code:\n// Evolver Lifecycle Manager - Evolver Core Module\n// Provides: start, stop, restart, status, log, health check\n// The loop script to spawn is configurable via EVOLVER_LOOP_SCRIPT env var.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync, spawn } = require('child_process');\nconst { getRepoRoot, getWorkspaceRoot, getLogsDir } = require('../gep/paths');\n\nvar WORKSPACE_ROOT = getWorkspaceRoot();\nvar LOG_FILE = path.join(getLogsDir(), 'evolver_loop.log');\nvar PID_FILE = path.join(WORKSPACE_ROOT, 'memory', 'evolver_loop.pid');\nvar MAX_SILENCE_MS = 30 * 60 * 1000;\n\nfunction getLoopScript() {\n // Prefer wrapper if exists, fallback to core evolver\n if (process.env.EVOLVER_LOOP_SCRIPT) return process.env.EVOLVER_LOOP_SCRIPT;\n var wrapper = path.join(WORKSPACE_ROOT, 'skills/feishu-evolver-wrapper/index.js');\n if (fs.existsSync(wrapper)) return wrapper;\n return path.join(getRepoRoot(), 'index.js');\n}\n\n// --- Process Discovery ---\n\nfunction getRunningPids() {\n try {\n var out = execSync('ps -e -o pid,args', { encoding: 'utf8' });\n var pids = [];\n for (var line of out.split('\\n')) {\n var trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('PID')) continue;\n var parts = trimmed.split(/\\s+/);\n var pid = parseInt(parts[0], 10);\n var cmd = parts.slice(1).join(' ');\n if (pid === process.pid) continue;\n if (cmd.includes('node') && cmd.includes('index.js') && cmd.includes('--loop')) {\n if (cmd.includes('feishu-evolver-wrapper') || cmd.includes('skills/evolver')) {\n pids.push(pid);\n }\n }\n }\n return [...new Set(pids)].filter(isPidRunning);\n } catch (e) {\n return [];\n }\n}\n\nfunction isPidRunning(pid) {\n try { process.kill(pid, 0); return true; } catch (e) { return false; }\n}\n\nfunction getCmdLine(pid) {\n try { return execSync('ps -p ' + pid + ' -o args=', { encoding: 'utf8' }).trim(); } catch (e) { return null; }\n}\n\n// --- Lifecycle ---\n\nfunction start(options) {\n var delayMs = (options && options.delayMs) || 0;\n var pids = getRunningPids();\n if (pids.length > 0) {\n console.log('[Lifecycle] Already running (PIDs: ' + pids.join(', ') + ').');\n return { status: 'already_running', pids: pids };\n }\n if (delayMs > 0) execSync('sleep ' + (delayMs / 1000));\n\n var script = getLoopScript();\n console.log('[Lifecycle] Starting: node ' + path.relative(WORKSPACE_ROOT, script) + ' --loop');\n\n var out = fs.openSync(LOG_FILE, 'a');\n var err = fs.openSync(LOG_FILE, 'a');\n\n var env = Object.assign({}, process.env);\n var npmGlobal = path.join(process.env.HOME || '', '.npm-global/bin');\n if (env.PATH && !env.PATH.includes(npmGlobal)) {\n env.PATH = npmGlobal + ':' + env.PATH;\n }\n\n var child = spawn('node', [script, '--loop'], {\n detached: true, stdio: ['ignore', out, err], cwd: WORKSPACE_ROOT, env: env\n });\n child.unref();\n fs.writeFileSync(PID_FILE, String(child.pid));\n console.log('[Lifecycle] Started PID ' + child.pid);\n return { status: 'started', pid: child.pid };\n}\n\nfunction stop() {\n var pids = getRunningPids();\n if (pids.length === 0) {\n console.log('[Lifecycle] No running evolver loops found.');\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n return { status: 'not_running' };\n }\n for (var i = 0; i < pids.length; i++) {\n console.log('[Lifecycle] Stopping PID ' + pids[i] + '...');\n try { process.kill(pids[i], 'SIGTERM'); } catch (e) {}\n }\n var attempts = 0;\n while (getRunningPids().length > 0 && attempts < 10) {\n execSync('sleep 0.5');\n attempts++;\n }\n var remaining = getRunningPids();\n for (var j = 0; j < remaining.length; j++) {\n console.log('[Lifecycle] SIGKILL PID ' + remaining[j]);\n try { process.kill(remaining[j], 'SIGKILL'); } catch (e) {}\n }\n if (fs.existsSync(PID_FILE)) fs.unlinkSync(PID_FILE);\n var evolverLock = path.join(getRepoRoot(), 'evolver.pid');\n if (fs.existsSync(evolverLock)) fs.unlinkSync(evolverLock);\n console.log('[Lifecycle] All stopped.');\n return { status: 'stopped', killed: pids };\n}\n\nfunction restart(options) {\n stop();\n return start(Object.assign({ delayMs: 2000 }, options || {}));\n}\n\nfunction status() {\n var pids = getRunningPids();\n if (pids.length > 0) {\n return { running: true, pids: pids.map(function(p) { return { pid: p, cmd: getCmdLine(p) }; }), log: path.relative(WORKSPACE_ROOT, LOG_FILE) };\n }\n return { running: false };\n}\n\nfunction tailLog(lines) {\n if (!fs.existsSync(LOG_FILE)) return { error: 'No log file' };\n try {\n return { file: path.relative(WORKSPACE_ROOT, LOG_FILE), content: execSync('tail -n ' + (lines || 20) + ' \"' + LOG_FILE + '\"', { encoding: 'utf8' }) };\n } catch (e) {\n return { error: e.message };\n }\n}\n\nfunction checkHealth() {\n var pids = getRunningPids();\n if (pids.length === 0) return { healthy: false, reason: 'not_running' };\n if (fs.existsSync(LOG_FILE)) {\n var silenceMs = Date.now() - fs.statSync(LOG_FILE).mtimeMs;\n if (silenceMs > MAX_SILENCE_MS) {\n return { healthy: false, reason: 'stagnation', silenceMinutes: Math.round(silenceMs / 60000) };\n }\n }\n return { healthy: true, pids: pids };\n}\n\n// --- CLI ---\nif (require.main === module) {\n var action = process.argv[2];\n switch (action) {\n case 'start': console.log(JSON.stringify(start())); break;\n case 'stop': console.log(JSON.stringify(stop())); break;\n case 'restart': console.log(JSON.stringify(restart())); break;\n case 'status': console.log(JSON.stringify(status(), null, 2)); break;\n case 'log': var r = tailLog(); console.log(r.content || r.error); break;\n case 'check':\n var health = checkHealth();\n console.log(JSON.stringify(health, null, 2));\n if (!health.healthy) { console.log('[Lifecycle] Restarting...'); restart(); }\n break;\n default: console.log('Usage: node lifecycle.js [start|stop|restart|status|log|check]');\n }\n}\n\nmodule.exports = { start, stop, restart, status, tailLog, checkHealth, getRunningPids };\n",
328 "inputSchema": {},
329 "outputSchema": null,
330 "icons": null,
331 "annotations": null,
332 "meta": null,
333 "execution": null
334 },
335 {
336 "name": "index.js",
337 "title": null,
338 "description": "Script: index.js. Code:\n// Evolver Operations Module (src/ops/)\n// Non-Feishu, portable utilities for evolver lifecycle and maintenance.\n\nmodule.exports = {\n lifecycle: require('./lifecycle'),\n skillsMonitor: require('./skills_monitor'),\n cleanup: require('./cleanup'),\n trigger: require('./trigger'),\n commentary: require('./commentary'),\n selfRepair: require('./self_repair'),\n};\n",
339 "inputSchema": {},
340 "outputSchema": null,
341 "icons": null,
342 "annotations": null,
343 "meta": null,
344 "execution": null
345 },
346 {
347 "name": "self_repair.js",
348 "title": null,
349 "description": "Script: self_repair.js. Code:\n// Git Self-Repair - Evolver Core Module\n// Emergency repair for git sync failures: abort rebase/merge, remove stale locks.\n\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { getWorkspaceRoot } = require('../gep/paths');\n\nvar LOCK_MAX_AGE_MS = 10 * 60 * 1000; // 10 minutes\n\nfunction repair(gitRoot) {\n var root = gitRoot || getWorkspaceRoot();\n var repaired = [];\n\n // 1. Abort pending rebase\n try {\n execSync('git rebase --abort', { cwd: root, stdio: 'ignore' });\n repaired.push('rebase_aborted');\n console.log('[SelfRepair] Aborted pending rebase.');\n } catch (e) {}\n\n // 2. Abort pending merge\n try {\n execSync('git merge --abort', { cwd: root, stdio: 'ignore' });\n repaired.push('merge_aborted');\n console.log('[SelfRepair] Aborted pending merge.');\n } catch (e) {}\n\n // 3. Remove stale index.lock\n var lockFile = path.join(root, '.git', 'index.lock');\n if (fs.existsSync(lockFile)) {\n try {\n var stat = fs.statSync(lockFile);\n var age = Date.now() - stat.mtimeMs;\n if (age > LOCK_MAX_AGE_MS) {\n fs.unlinkSync(lockFile);\n repaired.push('stale_lock_removed');\n console.log('[SelfRepair] Removed stale index.lock (' + Math.round(age / 60000) + 'min old).');\n }\n } catch (e) {}\n }\n\n // 4. Fetch origin (safe, read-only)\n try {\n execSync('git fetch origin', { cwd: root, stdio: 'ignore', timeout: 30000 });\n repaired.push('fetch_ok');\n } catch (e) {\n console.warn('[SelfRepair] git fetch failed: ' + e.message);\n }\n\n return repaired;\n}\n\nif (require.main === module) {\n var result = repair();\n console.log('[SelfRepair] Result:', result.length > 0 ? result.join(', ') : 'nothing to repair');\n}\n\nmodule.exports = { repair };\n",
350 "inputSchema": {},
351 "outputSchema": null,
352 "icons": null,
353 "annotations": null,
354 "meta": null,
355 "execution": null
356 },
357 {
358 "name": "assetStore.js",
359 "title": null,
360 "description": "Script: assetStore.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getGepAssetsDir } = require('./paths');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\n\nfunction ensureDir(dir) {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction getDefaultGenes() {\n return {\n version: 1,\n genes: [\n {\n type: 'Gene', id: 'gene_gep_repair_from_errors', category: 'repair',\n signals_match: ['error', 'exception', 'failed', 'unstable'],\n preconditions: ['signals contains error-related indicators'],\n strategy: [\n 'Extract structured signals from logs and user instructions',\n 'Select an existing Gene by signals match (no improvisation)',\n 'Estimate blast radius (files, lines) before editing',\n 'Apply smallest reversible patch',\n 'Validate using declared validation steps; rollback on failure',\n 'Solidify knowledge: append EvolutionEvent, update Gene/Capsule store',\n ],\n constraints: { max_files: 12, forbidden_paths: ['.git', 'node_modules'] },\n validation: [\n 'node -e \"require(\\'./src/evolve\\'); require(\\'./src/gep/solidify\\'); console.log(\\'ok\\')\"',\n 'node -e \"require(\\'./src/gep/selector\\'); require(\\'./src/gep/memoryGraph\\'); console.log(\\'ok\\')\"',\n ],\n },\n {\n type: 'Gene', id: 'gene_gep_optimize_prompt_and_assets', category: 'optimize',\n signals_match: ['protocol', 'gep', 'prompt', 'audit', 'reusable'],\n preconditions: ['need stricter, auditable evolution protocol outputs'],\n strategy: [\n 'Extract signals and determine selection rationale via Selector JSON',\n 'Prefer reusing existing Gene/Capsule; only create if no match exists',\n 'Refactor prompt assembly to embed assets (genes, capsules, parent event)',\n 'Reduce noise and ambiguity; enforce strict output schema',\n 'Validate by running node index.js run and ensuring no runtime errors',\n 'Solidify: record EvolutionEvent, update Gene definitions, create Capsule on success',\n ],\n constraints: { max_files: 20, forbidden_paths: ['.git', 'node_modules'] },\n validation: ['node -e \"require(\\'./src/evolve\\'); require(\\'./src/gep/prompt\\'); console.log(\\'ok\\')\"'],\n },\n ],\n };\n}\n\nfunction getDefaultCapsules() { return { version: 1, capsules: [] }; }\nfunction genesPath() { return path.join(getGepAssetsDir(), 'genes.json'); }\nfunction capsulesPath() { return path.join(getGepAssetsDir(), 'capsules.json'); }\nfunction eventsPath() { return path.join(getGepAssetsDir(), 'events.jsonl'); }\nfunction candidatesPath() { return path.join(getGepAssetsDir(), 'candidates.jsonl'); }\nfunction externalCandidatesPath() { return path.join(getGepAssetsDir(), 'external_candidates.jsonl'); }\n\nfunction loadGenes() { return readJsonIfExists(genesPath(), getDefaultGenes()).genes || []; }\nfunction loadCapsules() { return readJsonIfExists(capsulesPath(), getDefaultCapsules()).capsules || []; }\n\nfunction getLastEventId() {\n try {\n const p = eventsPath();\n if (!fs.existsSync(p)) return null;\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n if (lines.length === 0) return null;\n const last = JSON.parse(lines[lines.length - 1]);\n return last && typeof last.id === 'string' ? last.id : null;\n } catch { return null; }\n}\n\nfunction readAllEvents() {\n try {\n const p = eventsPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n return raw.split('\\n').map(l => l.trim()).filter(Boolean).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\nfunction appendEventJsonl(eventObj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(eventsPath(), JSON.stringify(eventObj) + '\\n', 'utf8');\n}\n\nfunction appendCandidateJsonl(candidateObj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(candidatesPath(), JSON.stringify(candidateObj) + '\\n', 'utf8');\n}\n\nfunction appendExternalCandidateJsonl(obj) {\n const dir = getGepAssetsDir(); ensureDir(dir);\n fs.appendFileSync(externalCandidatesPath(), JSON.stringify(obj) + '\\n', 'utf8');\n}\n\nfunction readRecentCandidates(limit = 20) {\n try {\n const p = candidatesPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n return lines.slice(Math.max(0, lines.length - limit)).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\nfunction readRecentExternalCandidates(limit = 50) {\n try {\n const p = externalCandidatesPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw.split('\\n').map(l => l.trim()).filter(Boolean);\n return lines.slice(Math.max(0, lines.length - limit)).map(l => {\n try { return JSON.parse(l); } catch { return null; }\n }).filter(Boolean);\n } catch { return []; }\n}\n\n// Safety net: ensure schema_version and asset_id are present before writing.\nfunction ensureSchemaFields(obj) {\n if (!obj || typeof obj !== 'object') return obj;\n if (!obj.schema_version) obj.schema_version = SCHEMA_VERSION;\n if (!obj.asset_id) { try { obj.asset_id = computeAssetId(obj); } catch (e) {} }\n return obj;\n}\n\nfunction upsertGene(geneObj) {\n ensureSchemaFields(geneObj);\n const current = readJsonIfExists(genesPath(), getDefaultGenes());\n const genes = Array.isArray(current.genes) ? current.genes : [];\n const idx = genes.findIndex(g => g && g.id === geneObj.id);\n if (idx >= 0) genes[idx] = geneObj; else genes.push(geneObj);\n writeJsonAtomic(genesPath(), { version: current.version || 1, genes });\n}\n\nfunction appendCapsule(capsuleObj) {\n ensureSchemaFields(capsuleObj);\n const current = readJsonIfExists(capsulesPath(), getDefaultCapsules());\n const capsules = Array.isArray(current.capsules) ? current.capsules : [];\n capsules.push(capsuleObj);\n writeJsonAtomic(capsulesPath(), { version: current.version || 1, capsules });\n}\n\nfunction upsertCapsule(capsuleObj) {\n if (!capsuleObj || capsuleObj.type !== 'Capsule' || !capsuleObj.id) return;\n ensureSchemaFields(capsuleObj);\n const current = readJsonIfExists(capsulesPath(), getDefaultCapsules());\n const capsules = Array.isArray(current.capsules) ? current.capsules : [];\n const idx = capsules.findIndex(c => c && c.type === 'Capsule' && String(c.id) === String(capsuleObj.id));\n if (idx >= 0) capsules[idx] = capsuleObj; else capsules.push(capsuleObj);\n writeJsonAtomic(capsulesPath(), { version: current.version || 1, capsules });\n}\n\nmodule.exports = {\n loadGenes, loadCapsules, readAllEvents, getLastEventId,\n appendEventJsonl, appendCandidateJsonl, appendExternalCandidateJsonl,\n readRecentCandidates, readRecentExternalCandidates,\n upsertGene, appendCapsule, upsertCapsule,\n genesPath, capsulesPath, eventsPath, candidatesPath, externalCandidatesPath,\n};\n",
361 "inputSchema": {},
362 "outputSchema": null,
363 "icons": null,
364 "annotations": null,
365 "meta": null,
366 "execution": null
367 },
368 {
369 "name": "candidates.js",
370 "title": null,
371 "description": "Script: candidates.js. Code:\nfunction stableHash(input) {\n // Deterministic lightweight hash (not cryptographic).\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction clip(text, maxChars) {\n const s = String(text || '');\n if (!maxChars || s.length <= maxChars) return s;\n return s.slice(0, Math.max(0, maxChars - 20)) + ' ...[TRUNCATED]';\n}\n\nfunction toLines(text) {\n return String(text || '')\n .split('\\n')\n .map(l => l.trimEnd())\n .filter(Boolean);\n}\n\nfunction extractToolCalls(transcript) {\n const lines = toLines(transcript);\n const calls = [];\n for (const line of lines) {\n const m = line.match(/\\[TOOL:\\s*([^\\]]+)\\]/i);\n if (m && m[1]) calls.push(m[1].trim());\n }\n return calls;\n}\n\nfunction countFreq(items) {\n const map = new Map();\n for (const it of items) map.set(it, (map.get(it) || 0) + 1);\n return map;\n}\n\nfunction buildFiveQuestionsShape({ title, signals, evidence }) {\n // Keep it short and structured; this is a template, not a perfect inference.\n const input = 'Recent session transcript + memory snippets + user instructions';\n const output = 'A safe, auditable evolution patch guided by GEP assets';\n const invariants = 'Protocol order, small reversible patches, validation, append-only events';\n const params = `Signals: ${Array.isArray(signals) ? signals.join(', ') : ''}`.trim();\n const failurePoints = 'Missing signals, over-broad changes, skipped validation, missing knowledge solidification';\n return {\n title: String(title || '').slice(0, 120),\n input,\n output,\n invariants,\n params: params || 'Signals: (none)',\n failure_points: failurePoints,\n evidence: clip(evidence, 240),\n };\n}\n\nfunction extractCapabilityCandidates({ recentSessionTranscript, signals }) {\n const candidates = [];\n const toolCalls = extractToolCalls(recentSessionTranscript);\n const freq = countFreq(toolCalls);\n\n for (const [tool, count] of freq.entries()) {\n if (count < 2) continue;\n const title = `Repeated tool usage: ${tool}`;\n const evidence = `Observed ${count} occurrences of tool call marker for ${tool}.`;\n const shape = buildFiveQuestionsShape({ title, signals, evidence });\n candidates.push({\n type: 'CapabilityCandidate',\n id: `cand_${stableHash(title)}`,\n title,\n source: 'transcript',\n created_at: new Date().toISOString(),\n signals: Array.isArray(signals) ? signals : [],\n shape,\n });\n }\n\n // Signals-as-candidates: capture recurring pain points as reusable capability shapes.\n const signalList = Array.isArray(signals) ? signals : [];\n const signalCandidates = [\n // Defensive signals\n { signal: 'log_error', title: 'Repair recurring runtime errors' },\n { signal: 'protocol_drift', title: 'Prevent protocol drift and enforce auditable outputs' },\n { signal: 'windows_shell_incompatible', title: 'Avoid platform-specific shell assumptions (Windows compatibility)' },\n { signal: 'session_logs_missing', title: 'Harden session log detection and fallback behavior' },\n // Opportunity signals (innovation)\n { signal: 'user_feature_request', title: 'Implement user-requested feature' },\n { signal: 'user_improvement_suggestion', title: 'Apply user improvement suggestion' },\n { signal: 'perf_bottleneck', title: 'Resolve performance bottleneck' },\n { signal: 'capability_gap', title: 'Fill capability gap' },\n { signal: 'stable_success_plateau', title: 'Explore new strategies during stability plateau' },\n { signal: 'external_opportunity', title: 'Evaluate external A2A asset for local adoption' },\n ];\n\n for (const sc of signalCandidates) {\n if (!signalList.includes(sc.signal)) continue;\n const evidence = `Signal present: ${sc.signal}`;\n const shape = buildFiveQuestionsShape({ title: sc.title, signals, evidence });\n candidates.push({\n type: 'CapabilityCandidate',\n id: `cand_${stableHash(sc.signal)}`,\n title: sc.title,\n source: 'signals',\n created_at: new Date().toISOString(),\n signals: signalList,\n shape,\n });\n }\n\n // Dedup by id\n const seen = new Set();\n return candidates.filter(c => {\n if (!c || !c.id) return false;\n if (seen.has(c.id)) return false;\n seen.add(c.id);\n return true;\n });\n}\n\nfunction renderCandidatesPreview(candidates, maxChars = 1400) {\n const list = Array.isArray(candidates) ? candidates : [];\n const lines = [];\n for (const c of list) {\n const s = c && c.shape ? c.shape : {};\n lines.push(`- ${c.id}: ${c.title}`);\n lines.push(` - input: ${s.input || ''}`);\n lines.push(` - output: ${s.output || ''}`);\n lines.push(` - invariants: ${s.invariants || ''}`);\n lines.push(` - params: ${s.params || ''}`);\n lines.push(` - failure_points: ${s.failure_points || ''}`);\n if (s.evidence) lines.push(` - evidence: ${s.evidence}`);\n }\n return clip(lines.join('\\n'), maxChars);\n}\n\nmodule.exports = {\n extractCapabilityCandidates,\n renderCandidatesPreview,\n};\n\n",
372 "inputSchema": {},
373 "outputSchema": null,
374 "icons": null,
375 "annotations": null,
376 "meta": null,
377 "execution": null
378 },
379 {
380 "name": "mutation.js",
381 "title": null,
382 "description": "Script: mutation.js. Code:\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction nowTsMs() {\n return Date.now();\n}\n\nfunction uniqStrings(list) {\n const out = [];\n const seen = new Set();\n for (const x of Array.isArray(list) ? list : []) {\n const s = String(x || '').trim();\n if (!s) continue;\n if (seen.has(s)) continue;\n seen.add(s);\n out.push(s);\n }\n return out;\n}\n\nfunction hasErrorishSignal(signals) {\n const list = Array.isArray(signals) ? signals.map(s => String(s || '')) : [];\n if (list.includes('log_error')) return true;\n if (list.some(s => s.startsWith('errsig:') || s.startsWith('errsig_norm:'))) return true;\n return false;\n}\n\n// Opportunity signals that indicate a chance to innovate (not just fix).\nvar OPPORTUNITY_SIGNALS = [\n 'user_feature_request',\n 'user_improvement_suggestion',\n 'perf_bottleneck',\n 'capability_gap',\n 'stable_success_plateau',\n 'external_opportunity',\n];\n\nfunction hasOpportunitySignal(signals) {\n var list = Array.isArray(signals) ? signals.map(function (s) { return String(s || ''); }) : [];\n for (var i = 0; i < OPPORTUNITY_SIGNALS.length; i++) {\n if (list.includes(OPPORTUNITY_SIGNALS[i])) return true;\n }\n return false;\n}\n\nfunction mutationCategoryFromContext({ signals, driftEnabled }) {\n if (hasErrorishSignal(signals)) return 'repair';\n if (driftEnabled) return 'innovate';\n // Auto-innovate: opportunity signals present and no errors\n if (hasOpportunitySignal(signals)) return 'innovate';\n return 'optimize';\n}\n\nfunction expectedEffectFromCategory(category) {\n const c = String(category || '');\n if (c === 'repair') return 'reduce runtime errors, increase stability, and lower failure rate';\n if (c === 'optimize') return 'improve success rate and reduce repeated operational cost';\n if (c === 'innovate') return 'explore new strategy combinations to escape local optimum';\n return 'improve robustness and success probability';\n}\n\nfunction targetFromGene(selectedGene) {\n if (selectedGene && selectedGene.id) return `gene:${String(selectedGene.id)}`;\n return 'behavior:protocol';\n}\n\nfunction isHighRiskPersonality(p) {\n // Conservative definition: low rigor or high risk_tolerance is treated as high-risk personality.\n const rigor = p && Number.isFinite(Number(p.rigor)) ? Number(p.rigor) : null;\n const riskTol = p && Number.isFinite(Number(p.risk_tolerance)) ? Number(p.risk_tolerance) : null;\n if (rigor != null && rigor < 0.5) return true;\n if (riskTol != null && riskTol > 0.6) return true;\n return false;\n}\n\nfunction isHighRiskMutationAllowed(personalityState) {\n const rigor = personalityState && Number.isFinite(Number(personalityState.rigor)) ? Number(personalityState.rigor) : 0;\n const riskTol =\n personalityState && Number.isFinite(Number(personalityState.risk_tolerance))\n ? Number(personalityState.risk_tolerance)\n : 1;\n return rigor >= 0.6 && riskTol <= 0.5;\n}\n\nfunction buildMutation({\n signals,\n selectedGene,\n driftEnabled,\n personalityState,\n allowHighRisk = false,\n target,\n expected_effect,\n} = {}) {\n const ts = nowTsMs();\n const category = mutationCategoryFromContext({ signals, driftEnabled: !!driftEnabled });\n const triggerSignals = uniqStrings(signals);\n\n const base = {\n type: 'Mutation',\n id: `mut_${ts}`,\n category,\n trigger_signals: triggerSignals,\n target: String(target || targetFromGene(selectedGene)),\n expected_effect: String(expected_effect || expectedEffectFromCategory(category)),\n risk_level: 'low',\n };\n\n // Default risk assignment: innovate is medium; others low.\n if (category === 'innovate') base.risk_level = 'medium';\n\n // Optional high-risk escalation (rare, and guarded by strict safety constraints).\n if (allowHighRisk && category === 'innovate') {\n base.risk_level = 'high';\n }\n\n // Safety constraints (hard):\n // - forbid innovate + high-risk personality (downgrade innovation to optimize)\n // - forbid high-risk mutation unless personality satisfies constraints\n const highRiskPersonality = isHighRiskPersonality(personalityState || null);\n if (base.category === 'innovate' && highRiskPersonality) {\n base.category = 'optimize';\n base.expected_effect = 'safety downgrade: optimize under high-risk personality (avoid innovate+high-risk combo)';\n base.risk_level = 'low';\n base.trigger_signals = uniqStrings([...(base.trigger_signals || []), 'safety:avoid_innovate_with_high_risk_personality']);\n }\n\n if (base.risk_level === 'high' && !isHighRiskMutationAllowed(personalityState || null)) {\n // Downgrade rather than emit illegal high-risk mutation.\n base.risk_level = 'medium';\n base.trigger_signals = uniqStrings([...(base.trigger_signals || []), 'safety:downgrade_high_risk']);\n }\n\n return base;\n}\n\nfunction isValidMutation(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'Mutation') return false;\n if (!obj.id || typeof obj.id !== 'string') return false;\n if (!obj.category || !['repair', 'optimize', 'innovate'].includes(String(obj.category))) return false;\n if (!Array.isArray(obj.trigger_signals)) return false;\n if (!obj.target || typeof obj.target !== 'string') return false;\n if (!obj.expected_effect || typeof obj.expected_effect !== 'string') return false;\n if (!obj.risk_level || !['low', 'medium', 'high'].includes(String(obj.risk_level))) return false;\n return true;\n}\n\nfunction normalizeMutation(obj) {\n const m = obj && typeof obj === 'object' ? obj : {};\n const out = {\n type: 'Mutation',\n id: typeof m.id === 'string' ? m.id : `mut_${nowTsMs()}`,\n category: ['repair', 'optimize', 'innovate'].includes(String(m.category)) ? String(m.category) : 'optimize',\n trigger_signals: uniqStrings(m.trigger_signals),\n target: typeof m.target === 'string' ? m.target : 'behavior:protocol',\n expected_effect: typeof m.expected_effect === 'string' ? m.expected_effect : expectedEffectFromCategory(m.category),\n risk_level: ['low', 'medium', 'high'].includes(String(m.risk_level)) ? String(m.risk_level) : 'low',\n };\n return out;\n}\n\nmodule.exports = {\n clamp01,\n buildMutation,\n isValidMutation,\n normalizeMutation,\n isHighRiskMutationAllowed,\n isHighRiskPersonality,\n hasOpportunitySignal,\n};\n\n",
383 "inputSchema": {},
384 "outputSchema": null,
385 "icons": null,
386 "annotations": null,
387 "meta": null,
388 "execution": null
389 },
390 {
391 "name": "validationReport.js",
392 "title": null,
393 "description": "Script: validationReport.js. Code:\n// Standardized ValidationReport type for GEP.\n// Machine-readable, self-contained, and interoperable.\n// Can be consumed by external Hubs or Judges for automated assessment.\n\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { captureEnvFingerprint, envFingerprintKey } = require('./envFingerprint');\n\n// Build a standardized ValidationReport from raw validation results.\nfunction buildValidationReport({ geneId, commands, results, envFp, startedAt, finishedAt }) {\n const env = envFp || captureEnvFingerprint();\n const resultsList = Array.isArray(results) ? results : [];\n const cmdsList = Array.isArray(commands) ? commands : resultsList.map(function (r) { return r && r.cmd ? String(r.cmd) : ''; });\n const overallOk = resultsList.length > 0 && resultsList.every(function (r) { return r && r.ok; });\n const durationMs =\n Number.isFinite(startedAt) && Number.isFinite(finishedAt) ? finishedAt - startedAt : null;\n\n const report = {\n type: 'ValidationReport',\n schema_version: SCHEMA_VERSION,\n id: 'vr_' + Date.now(),\n gene_id: geneId || null,\n env_fingerprint: env,\n env_fingerprint_key: envFingerprintKey(env),\n commands: cmdsList.map(function (cmd, i) {\n const r = resultsList[i] || {};\n return {\n command: String(cmd || ''),\n ok: !!r.ok,\n stdout: String(r.out || '').slice(0, 4000),\n stderr: String(r.err || '').slice(0, 4000),\n };\n }),\n overall_ok: overallOk,\n duration_ms: durationMs,\n created_at: new Date().toISOString(),\n };\n\n report.asset_id = computeAssetId(report);\n return report;\n}\n\n// Validate that an object is a well-formed ValidationReport.\nfunction isValidValidationReport(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'ValidationReport') return false;\n if (!obj.id || typeof obj.id !== 'string') return false;\n if (!Array.isArray(obj.commands)) return false;\n if (typeof obj.overall_ok !== 'boolean') return false;\n return true;\n}\n\nmodule.exports = {\n buildValidationReport,\n isValidValidationReport,\n};\n",
394 "inputSchema": {},
395 "outputSchema": null,
396 "icons": null,
397 "annotations": null,
398 "meta": null,
399 "execution": null
400 },
401 {
402 "name": "contentHash.js",
403 "title": null,
404 "description": "Script: contentHash.js. Code:\n// Content-addressable hashing for GEP assets.\n// Provides canonical JSON serialization and SHA-256 based asset IDs.\n// This enables deduplication, tamper detection, and cross-node consistency.\n\nconst crypto = require('crypto');\n\n// Schema version for all GEP asset types.\n// Bump MINOR for additive fields; MAJOR for breaking changes.\nconst SCHEMA_VERSION = '1.5.0';\n\n// Canonical JSON: deterministic serialization with sorted keys at all levels.\n// Arrays preserve order; non-finite numbers become null; undefined becomes null.\nfunction canonicalize(obj) {\n if (obj === null || obj === undefined) return 'null';\n if (typeof obj === 'boolean') return obj ? 'true' : 'false';\n if (typeof obj === 'number') {\n if (!Number.isFinite(obj)) return 'null';\n return String(obj);\n }\n if (typeof obj === 'string') return JSON.stringify(obj);\n if (Array.isArray(obj)) {\n return '[' + obj.map(canonicalize).join(',') + ']';\n }\n if (typeof obj === 'object') {\n const keys = Object.keys(obj).sort();\n const pairs = [];\n for (const k of keys) {\n pairs.push(JSON.stringify(k) + ':' + canonicalize(obj[k]));\n }\n return '{' + pairs.join(',') + '}';\n }\n return 'null';\n}\n\n// Compute a content-addressable asset ID.\n// Excludes self-referential fields (asset_id itself) from the hash input.\n// Returns \"sha256:<hex>\".\nfunction computeAssetId(obj, excludeFields) {\n if (!obj || typeof obj !== 'object') return null;\n const exclude = new Set(Array.isArray(excludeFields) ? excludeFields : ['asset_id']);\n const clean = {};\n for (const k of Object.keys(obj)) {\n if (exclude.has(k)) continue;\n clean[k] = obj[k];\n }\n const canonical = canonicalize(clean);\n const hash = crypto.createHash('sha256').update(canonical, 'utf8').digest('hex');\n return 'sha256:' + hash;\n}\n\n// Verify that an object's asset_id matches its content.\nfunction verifyAssetId(obj) {\n if (!obj || typeof obj !== 'object') return false;\n const claimed = obj.asset_id;\n if (!claimed || typeof claimed !== 'string') return false;\n const computed = computeAssetId(obj);\n return claimed === computed;\n}\n\nmodule.exports = {\n SCHEMA_VERSION,\n canonicalize,\n computeAssetId,\n verifyAssetId,\n};\n",
405 "inputSchema": {},
406 "outputSchema": null,
407 "icons": null,
408 "annotations": null,
409 "meta": null,
410 "execution": null
411 },
412 {
413 "name": "personality.js",
414 "title": null,
415 "description": "Script: personality.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getMemoryDir } = require('./paths');\nconst { hasOpportunitySignal } = require('./mutation');\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction personalityFilePath() {\n const memoryDir = getMemoryDir();\n const { getEvolutionDir } = require('./paths'); return path.join(getEvolutionDir(), 'personality_state.json');\n}\n\nfunction defaultPersonalityState() {\n // Conservative defaults: protocol-first, safe, low-risk.\n return {\n type: 'PersonalityState',\n rigor: 0.7,\n creativity: 0.35,\n verbosity: 0.25,\n risk_tolerance: 0.4,\n obedience: 0.85,\n };\n}\n\nfunction normalizePersonalityState(state) {\n const s = state && typeof state === 'object' ? state : {};\n return {\n type: 'PersonalityState',\n rigor: clamp01(s.rigor),\n creativity: clamp01(s.creativity),\n verbosity: clamp01(s.verbosity),\n risk_tolerance: clamp01(s.risk_tolerance),\n obedience: clamp01(s.obedience),\n };\n}\n\nfunction isValidPersonalityState(obj) {\n if (!obj || typeof obj !== 'object') return false;\n if (obj.type !== 'PersonalityState') return false;\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n const v = obj[k];\n if (!Number.isFinite(Number(v))) return false;\n const n = Number(v);\n if (n < 0 || n > 1) return false;\n }\n return true;\n}\n\nfunction roundToStep(x, step) {\n const s = Number(step);\n if (!Number.isFinite(s) || s <= 0) return x;\n return Math.round(Number(x) / s) * s;\n}\n\nfunction personalityKey(state) {\n const s = normalizePersonalityState(state);\n const step = 0.1;\n const r = roundToStep(s.rigor, step).toFixed(1);\n const c = roundToStep(s.creativity, step).toFixed(1);\n const v = roundToStep(s.verbosity, step).toFixed(1);\n const rt = roundToStep(s.risk_tolerance, step).toFixed(1);\n const o = roundToStep(s.obedience, step).toFixed(1);\n return `rigor=${r}|creativity=${c}|verbosity=${v}|risk_tolerance=${rt}|obedience=${o}`;\n}\n\nfunction getParamDeltas(fromState, toState) {\n const a = normalizePersonalityState(fromState);\n const b = normalizePersonalityState(toState);\n const deltas = [];\n for (const k of ['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience']) {\n deltas.push({ param: k, delta: Number(b[k]) - Number(a[k]) });\n }\n deltas.sort((x, y) => Math.abs(y.delta) - Math.abs(x.delta));\n return deltas;\n}\n\nfunction personalityScore(statsEntry) {\n const e = statsEntry && typeof statsEntry === 'object' ? statsEntry : {};\n const succ = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = succ + fail;\n // Laplace-smoothed success probability\n const p = (succ + 1) / (total + 2);\n // Penalize tiny-sample overconfidence\n const sampleWeight = Math.min(1, total / 8);\n // Use avg_score (if present) as mild quality proxy\n const avg = Number.isFinite(Number(e.avg_score)) ? Number(e.avg_score) : null;\n const q = avg == null ? 0.5 : clamp01(avg);\n return p * 0.75 + q * 0.25 * sampleWeight;\n}\n\nfunction chooseBestKnownPersonality(statsByKey) {\n const stats = statsByKey && typeof statsByKey === 'object' ? statsByKey : {};\n let best = null;\n for (const [k, entry] of Object.entries(stats)) {\n const e = entry || {};\n const total = (Number(e.success) || 0) + (Number(e.fail) || 0);\n if (total < 3) continue;\n const sc = personalityScore(e);\n if (!best || sc > best.score) best = { key: k, score: sc, entry: e };\n }\n return best;\n}\n\nfunction parseKeyToState(key) {\n // key format: rigor=0.7|creativity=0.3|...\n const out = defaultPersonalityState();\n const parts = String(key || '').split('|').map(s => s.trim()).filter(Boolean);\n for (const p of parts) {\n const [k, v] = p.split('=').map(x => String(x || '').trim());\n if (!k) continue;\n if (!['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience'].includes(k)) continue;\n out[k] = clamp01(Number(v));\n }\n return normalizePersonalityState(out);\n}\n\nfunction applyPersonalityMutations(state, mutations) {\n let cur = normalizePersonalityState(state);\n const muts = Array.isArray(mutations) ? mutations : [];\n const applied = [];\n let count = 0;\n for (const m of muts) {\n if (!m || typeof m !== 'object') continue;\n const param = String(m.param || '').trim();\n if (!['rigor', 'creativity', 'verbosity', 'risk_tolerance', 'obedience'].includes(param)) continue;\n const delta = Number(m.delta);\n if (!Number.isFinite(delta)) continue;\n const clipped = Math.max(-0.2, Math.min(0.2, delta));\n cur[param] = clamp01(Number(cur[param]) + clipped);\n applied.push({ type: 'PersonalityMutation', param, delta: clipped, reason: String(m.reason || '').slice(0, 140) });\n count += 1;\n if (count >= 2) break;\n }\n return { state: cur, applied };\n}\n\nfunction proposeMutations({ baseState, reason, driftEnabled, signals }) {\n const s = normalizePersonalityState(baseState);\n const sig = Array.isArray(signals) ? signals.map(x => String(x || '')) : [];\n const muts = [];\n\n const r = String(reason || '');\n if (driftEnabled) {\n muts.push({ type: 'PersonalityMutation', param: 'creativity', delta: +0.1, reason: r || 'drift enabled' });\n // Keep risk bounded under drift by default.\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: -0.05, reason: 'drift safety clamp' });\n } else if (sig.includes('protocol_drift')) {\n muts.push({ type: 'PersonalityMutation', param: 'obedience', delta: +0.1, reason: r || 'protocol drift' });\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.05, reason: 'tighten protocol compliance' });\n } else if (sig.includes('log_error') || sig.some(x => x.startsWith('errsig:') || x.startsWith('errsig_norm:'))) {\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.1, reason: r || 'repair instability' });\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: -0.1, reason: 'reduce risky changes under errors' });\n } else if (hasOpportunitySignal(sig)) {\n // Opportunity detected: nudge towards creativity to enable innovation.\n muts.push({ type: 'PersonalityMutation', param: 'creativity', delta: +0.1, reason: r || 'opportunity signal detected' });\n muts.push({ type: 'PersonalityMutation', param: 'risk_tolerance', delta: +0.05, reason: 'allow exploration for innovation' });\n } else {\n // Plateau-like generic: slightly increase rigor, slightly decrease verbosity (more concise execution).\n muts.push({ type: 'PersonalityMutation', param: 'rigor', delta: +0.05, reason: r || 'stability bias' });\n muts.push({ type: 'PersonalityMutation', param: 'verbosity', delta: -0.05, reason: 'reduce noise' });\n }\n\n // If already very high obedience, avoid pushing it further; swap second mutation to creativity.\n if (s.obedience >= 0.95) {\n const idx = muts.findIndex(x => x.param === 'obedience');\n if (idx >= 0) muts[idx] = { type: 'PersonalityMutation', param: 'creativity', delta: +0.05, reason: 'obedience saturated' };\n }\n return muts;\n}\n\nfunction shouldTriggerPersonalityMutation({ driftEnabled, recentEvents }) {\n if (driftEnabled) return { ok: true, reason: 'drift enabled' };\n const list = Array.isArray(recentEvents) ? recentEvents : [];\n const tail = list.slice(-6);\n const outcomes = tail\n .map(e => (e && e.outcome && e.outcome.status ? String(e.outcome.status) : null))\n .filter(Boolean);\n if (outcomes.length >= 4) {\n const recentFailed = outcomes.slice(-4).filter(x => x === 'failed').length;\n if (recentFailed >= 3) return { ok: true, reason: 'long failure streak' };\n }\n // Mutation consecutive failure proxy: last 3 events that have mutation_id.\n const withMut = tail.filter(e => e && typeof e.mutation_id === 'string' && e.mutation_id);\n if (withMut.length >= 3) {\n const last3 = withMut.slice(-3);\n const fail3 = last3.filter(e => e && e.outcome && e.outcome.status === 'failed').length;\n if (fail3 >= 3) return { ok: true, reason: 'mutation consecutive failures' };\n }\n return { ok: false, reason: '' };\n}\n\nfunction loadPersonalityModel() {\n const p = personalityFilePath();\n const fallback = {\n version: 1,\n current: defaultPersonalityState(),\n stats: {},\n history: [],\n updated_at: nowIso(),\n };\n const raw = readJsonIfExists(p, fallback);\n const cur = normalizePersonalityState(raw && raw.current ? raw.current : defaultPersonalityState());\n const stats = raw && typeof raw.stats === 'object' ? raw.stats : {};\n const history = Array.isArray(raw && raw.history) ? raw.history : [];\n return { version: 1, current: cur, stats, history, updated_at: raw && raw.updated_at ? raw.updated_at : nowIso() };\n}\n\nfunction savePersonalityModel(model) {\n const m = model && typeof model === 'object' ? model : {};\n const out = {\n version: 1,\n current: normalizePersonalityState(m.current || defaultPersonalityState()),\n stats: m.stats && typeof m.stats === 'object' ? m.stats : {},\n history: Array.isArray(m.history) ? m.history.slice(-120) : [],\n updated_at: nowIso(),\n };\n writeJsonAtomic(personalityFilePath(), out);\n return out;\n}\n\nfunction selectPersonalityForRun({ driftEnabled, signals, recentEvents } = {}) {\n const model = loadPersonalityModel();\n const base = normalizePersonalityState(model.current);\n const stats = model.stats || {};\n\n const best = chooseBestKnownPersonality(stats);\n let naturalSelectionApplied = [];\n\n // Natural selection: nudge towards the best-known configuration (small, max 2 params).\n if (best && best.key) {\n const bestState = parseKeyToState(best.key);\n const diffs = getParamDeltas(base, bestState).filter(d => Math.abs(d.delta) >= 0.05);\n const muts = [];\n for (const d of diffs.slice(0, 2)) {\n const clipped = Math.max(-0.1, Math.min(0.1, d.delta));\n muts.push({ type: 'PersonalityMutation', param: d.param, delta: clipped, reason: 'natural_selection' });\n }\n const applied = applyPersonalityMutations(base, muts);\n model.current = applied.state;\n naturalSelectionApplied = applied.applied;\n }\n\n // Triggered personality mutation (explicit rule-based).\n const trig = shouldTriggerPersonalityMutation({ driftEnabled: !!driftEnabled, recentEvents });\n let triggeredApplied = [];\n if (trig.ok) {\n const props = proposeMutations({\n baseState: model.current,\n reason: trig.reason,\n driftEnabled: !!driftEnabled,\n signals,\n });\n const applied = applyPersonalityMutations(model.current, props);\n model.current = applied.state;\n triggeredApplied = applied.applied;\n }\n\n // Persist updated current state.\n const saved = savePersonalityModel(model);\n const key = personalityKey(saved.current);\n const known = !!(saved.stats && saved.stats[key]);\n\n return {\n personality_state: saved.current,\n personality_key: key,\n personality_known: known,\n personality_mutations: [...naturalSelectionApplied, ...triggeredApplied],\n model_meta: {\n best_known_key: best && best.key ? best.key : null,\n best_known_score: best && Number.isFinite(Number(best.score)) ? Number(best.score) : null,\n triggered: trig.ok ? { reason: trig.reason } : null,\n },\n };\n}\n\nfunction updatePersonalityStats({ personalityState, outcome, score, notes } = {}) {\n const model = loadPersonalityModel();\n const st = normalizePersonalityState(personalityState || model.current);\n const key = personalityKey(st);\n if (!model.stats || typeof model.stats !== 'object') model.stats = {};\n const cur = model.stats[key] && typeof model.stats[key] === 'object' ? model.stats[key] : { success: 0, fail: 0, avg_score: 0.5, n: 0 };\n\n const out = String(outcome || '').toLowerCase();\n if (out === 'success') cur.success = (Number(cur.success) || 0) + 1;\n else if (out === 'failed') cur.fail = (Number(cur.fail) || 0) + 1;\n\n const sc = Number.isFinite(Number(score)) ? clamp01(Number(score)) : null;\n if (sc != null) {\n const n = (Number(cur.n) || 0) + 1;\n const prev = Number.isFinite(Number(cur.avg_score)) ? Number(cur.avg_score) : 0.5;\n cur.avg_score = prev + (sc - prev) / n;\n cur.n = n;\n }\n cur.updated_at = nowIso();\n model.stats[key] = cur;\n\n model.history = Array.isArray(model.history) ? model.history : [];\n model.history.push({\n at: nowIso(),\n key,\n outcome: out === 'success' || out === 'failed' ? out : 'unknown',\n score: sc,\n notes: notes ? String(notes).slice(0, 220) : null,\n });\n\n savePersonalityModel(model);\n return { key, stats: cur };\n}\n\nmodule.exports = {\n clamp01,\n defaultPersonalityState,\n normalizePersonalityState,\n isValidPersonalityState,\n personalityKey,\n loadPersonalityModel,\n savePersonalityModel,\n selectPersonalityForRun,\n updatePersonalityStats,\n};\n\n",
416 "inputSchema": {},
417 "outputSchema": null,
418 "icons": null,
419 "annotations": null,
420 "meta": null,
421 "execution": null
422 },
423 {
424 "name": "paths.js",
425 "title": null,
426 "description": "Script: paths.js. Code:\nconst path = require('path');\n\nfunction getRepoRoot() {\n // src/gep/paths.js -> repo root\n return path.resolve(__dirname, '..', '..');\n}\n\nfunction getMemoryDir() {\n const repoRoot = getRepoRoot();\n return process.env.MEMORY_DIR || path.join(repoRoot, 'memory');\n}\n\nfunction getEvolutionDir() {\n return process.env.EVOLUTION_DIR || path.join(getMemoryDir(), 'evolution');\n}\n\nfunction getGepAssetsDir() {\n const repoRoot = getRepoRoot();\n return process.env.GEP_ASSETS_DIR || path.join(repoRoot, 'assets', 'gep');\n}\n\nfunction getWorkspaceRoot() {\n // evolver repo root is skills/evolver/, workspace is two levels up\n return process.env.OPENCLAW_WORKSPACE || path.resolve(getRepoRoot(), '..', '..');\n}\n\nfunction getSkillsDir() {\n return path.join(getWorkspaceRoot(), 'skills');\n}\n\nfunction getLogsDir() {\n var dir = path.join(getWorkspaceRoot(), 'logs');\n var fs = require('fs');\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n return dir;\n}\n\nmodule.exports = {\n getRepoRoot,\n getMemoryDir,\n getEvolutionDir,\n getGepAssetsDir,\n getWorkspaceRoot,\n getSkillsDir,\n getLogsDir,\n};\n\n",
427 "inputSchema": {},
428 "outputSchema": null,
429 "icons": null,
430 "annotations": null,
431 "meta": null,
432 "execution": null
433 },
434 {
435 "name": "a2a.js",
436 "title": null,
437 "description": "Script: a2a.js. Code:\nconst fs = require('fs');\nconst { readAllEvents } = require('./assetStore');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { unwrapAssetFromMessage } = require('./a2aProtocol');\n\nfunction nowIso() { return new Date().toISOString(); }\n\nfunction isAllowedA2AAsset(obj) {\n if (!obj || typeof obj !== 'object') return false;\n var t = obj.type;\n return t === 'Gene' || t === 'Capsule' || t === 'EvolutionEvent';\n}\n\nfunction safeNumber(x, fallback) {\n if (fallback === undefined) fallback = null;\n var n = Number(x);\n return Number.isFinite(n) ? n : fallback;\n}\n\nfunction getBlastRadiusLimits() {\n var maxFiles = safeNumber(process.env.A2A_MAX_FILES, 5);\n var maxLines = safeNumber(process.env.A2A_MAX_LINES, 200);\n return {\n maxFiles: Number.isFinite(maxFiles) ? maxFiles : 5,\n maxLines: Number.isFinite(maxLines) ? maxLines : 200,\n };\n}\n\nfunction isBlastRadiusSafe(blastRadius) {\n var lim = getBlastRadiusLimits();\n var files = blastRadius && Number.isFinite(Number(blastRadius.files)) ? Number(blastRadius.files) : 0;\n var lines = blastRadius && Number.isFinite(Number(blastRadius.lines)) ? Number(blastRadius.lines) : 0;\n return files <= lim.maxFiles && lines <= lim.maxLines;\n}\n\nfunction clamp01(n) {\n var x = Number(n);\n if (!Number.isFinite(x)) return 0;\n return Math.max(0, Math.min(1, x));\n}\n\nfunction lowerConfidence(asset, opts) {\n if (!opts) opts = {};\n var factor = Number.isFinite(Number(opts.factor)) ? Number(opts.factor) : 0.6;\n var receivedFrom = opts.source || 'external';\n var receivedAt = opts.received_at || nowIso();\n var cloned = JSON.parse(JSON.stringify(asset || {}));\n if (!isAllowedA2AAsset(cloned)) return null;\n if (cloned.type === 'Capsule') {\n if (typeof cloned.confidence === 'number') cloned.confidence = clamp01(cloned.confidence * factor);\n else if (cloned.confidence != null) cloned.confidence = clamp01(Number(cloned.confidence) * factor);\n }\n if (!cloned.a2a || typeof cloned.a2a !== 'object') cloned.a2a = {};\n cloned.a2a.status = 'external_candidate';\n cloned.a2a.source = receivedFrom;\n cloned.a2a.received_at = receivedAt;\n cloned.a2a.confidence_factor = factor;\n if (!cloned.schema_version) cloned.schema_version = SCHEMA_VERSION;\n if (!cloned.asset_id) { try { cloned.asset_id = computeAssetId(cloned); } catch (e) {} }\n return cloned;\n}\n\nfunction readEvolutionEvents() {\n var events = readAllEvents();\n return Array.isArray(events) ? events.filter(function (e) { return e && e.type === 'EvolutionEvent'; }) : [];\n}\n\nfunction normalizeEventsList(events) {\n return Array.isArray(events) ? events : [];\n}\n\nfunction computeCapsuleSuccessStreak(params) {\n var capsuleId = params.capsuleId;\n var events = params.events;\n var id = capsuleId ? String(capsuleId) : '';\n if (!id) return 0;\n var list = normalizeEventsList(events || readEvolutionEvents());\n var streak = 0;\n for (var i = list.length - 1; i >= 0; i--) {\n var ev = list[i];\n if (!ev || ev.type !== 'EvolutionEvent') continue;\n if (!ev.capsule_id || String(ev.capsule_id) !== id) continue;\n var st = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (st === 'success') streak += 1; else break;\n }\n return streak;\n}\n\nfunction isCapsuleBroadcastEligible(capsule, opts) {\n if (!opts) opts = {};\n if (!capsule || capsule.type !== 'Capsule') return false;\n var score = capsule.outcome && capsule.outcome.score != null ? safeNumber(capsule.outcome.score, null) : null;\n if (score == null || score < 0.7) return false;\n var blast = capsule.blast_radius || (capsule.outcome && capsule.outcome.blast_radius) || null;\n if (!isBlastRadiusSafe(blast)) return false;\n var events = Array.isArray(opts.events) ? opts.events : readEvolutionEvents();\n var streak = computeCapsuleSuccessStreak({ capsuleId: capsule.id, events: events });\n if (streak < 2) return false;\n return true;\n}\n\nfunction exportEligibleCapsules(params) {\n if (!params) params = {};\n var list = Array.isArray(params.capsules) ? params.capsules : [];\n var evs = Array.isArray(params.events) ? params.events : readEvolutionEvents();\n var eligible = list.filter(function (c) { return isCapsuleBroadcastEligible(c, { events: evs }); });\n for (var i = 0; i < eligible.length; i++) {\n var c = eligible[i];\n if (!c.schema_version) c.schema_version = SCHEMA_VERSION;\n if (!c.asset_id) { try { c.asset_id = computeAssetId(c); } catch (e) {} }\n }\n return eligible;\n}\n\nfunction parseA2AInput(text) {\n var raw = String(text || '').trim();\n if (!raw) return [];\n try {\n var maybe = JSON.parse(raw);\n if (Array.isArray(maybe)) {\n return maybe.map(function (item) { return unwrapAssetFromMessage(item) || item; }).filter(Boolean);\n }\n if (maybe && typeof maybe === 'object') {\n var unwrapped = unwrapAssetFromMessage(maybe);\n return unwrapped ? [unwrapped] : [maybe];\n }\n } catch (e) {}\n var lines = raw.split('\\n').map(function (l) { return l.trim(); }).filter(Boolean);\n var items = [];\n for (var i = 0; i < lines.length; i++) {\n try {\n var obj = JSON.parse(lines[i]);\n var uw = unwrapAssetFromMessage(obj);\n items.push(uw || obj);\n } catch (e) { continue; }\n }\n return items;\n}\n\nfunction readTextIfExists(filePath) {\n try {\n if (!filePath) return '';\n if (!fs.existsSync(filePath)) return '';\n return fs.readFileSync(filePath, 'utf8');\n } catch { return ''; }\n}\n\nmodule.exports = {\n isAllowedA2AAsset, lowerConfidence, isBlastRadiusSafe,\n computeCapsuleSuccessStreak, isCapsuleBroadcastEligible,\n exportEligibleCapsules, parseA2AInput, readTextIfExists,\n};\n",
438 "inputSchema": {},
439 "outputSchema": null,
440 "icons": null,
441 "annotations": null,
442 "meta": null,
443 "execution": null
444 },
445 {
446 "name": "a2aProtocol.js",
447 "title": null,
448 "description": "Script: a2aProtocol.js. Code:\n// GEP A2A Protocol - Standard message types and pluggable transport layer.\n//\n// Protocol messages:\n// hello - capability advertisement and node discovery\n// publish - broadcast an eligible asset (Capsule/Gene)\n// fetch - request a specific asset by id or content hash\n// report - send a ValidationReport for a received asset\n// decision - accept/reject/quarantine decision on a received asset\n// revoke - withdraw a previously published asset\n//\n// Transport interface:\n// send(message, opts) - send a protocol message\n// receive(opts) - receive pending messages\n// list(opts) - list available message files/streams\n//\n// Default transport: FileTransport (reads/writes JSONL to a2a/ directory).\n\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst { getGepAssetsDir } = require('./paths');\nconst { computeAssetId } = require('./contentHash');\nconst { captureEnvFingerprint } = require('./envFingerprint');\n\nconst PROTOCOL_NAME = 'gep-a2a';\nconst PROTOCOL_VERSION = '1.0.0';\nconst VALID_MESSAGE_TYPES = ['hello', 'publish', 'fetch', 'report', 'decision', 'revoke'];\n\nfunction generateMessageId() {\n return 'msg_' + Date.now() + '_' + crypto.randomBytes(4).toString('hex');\n}\n\nfunction getNodeId() {\n if (process.env.A2A_NODE_ID) return String(process.env.A2A_NODE_ID);\n const raw = process.cwd() + '|' + (process.env.AGENT_NAME || 'default');\n return 'node_' + crypto.createHash('sha256').update(raw).digest('hex').slice(0, 12);\n}\n\n// --- Base message builder ---\n\nfunction buildMessage(params) {\n var messageType = params.messageType;\n var payload = params.payload;\n var senderId = params.senderId;\n if (!VALID_MESSAGE_TYPES.includes(messageType)) {\n throw new Error('Invalid message type: ' + messageType + '. Valid: ' + VALID_MESSAGE_TYPES.join(', '));\n }\n return {\n protocol: PROTOCOL_NAME,\n protocol_version: PROTOCOL_VERSION,\n message_type: messageType,\n message_id: generateMessageId(),\n sender_id: senderId || getNodeId(),\n timestamp: new Date().toISOString(),\n payload: payload || {},\n };\n}\n\n// --- Typed message builders ---\n\nfunction buildHello(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'hello',\n senderId: o.nodeId,\n payload: {\n capabilities: o.capabilities || {},\n gene_count: typeof o.geneCount === 'number' ? o.geneCount : null,\n capsule_count: typeof o.capsuleCount === 'number' ? o.capsuleCount : null,\n env_fingerprint: captureEnvFingerprint(),\n },\n });\n}\n\nfunction buildPublish(opts) {\n var o = opts || {};\n var asset = o.asset;\n if (!asset || !asset.type || !asset.id) {\n throw new Error('publish: asset must have type and id');\n }\n // Generate signature: HMAC-SHA256 of asset_id with node secret\n var assetIdVal = asset.asset_id || computeAssetId(asset);\n var nodeSecret = process.env.A2A_NODE_SECRET || getNodeId();\n var signature = crypto.createHmac('sha256', nodeSecret).update(assetIdVal).digest('hex');\n return buildMessage({\n messageType: 'publish',\n senderId: o.nodeId,\n payload: {\n asset_type: asset.type,\n asset_id: assetIdVal,\n local_id: asset.id,\n asset: asset,\n signature: signature,\n },\n });\n}\n\nfunction buildFetch(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'fetch',\n senderId: o.nodeId,\n payload: {\n asset_type: o.assetType || null,\n local_id: o.localId || null,\n content_hash: o.contentHash || null,\n },\n });\n}\n\nfunction buildReport(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'report',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n validation_report: o.validationReport || null,\n },\n });\n}\n\nfunction buildDecision(opts) {\n var o = opts || {};\n var validDecisions = ['accept', 'reject', 'quarantine'];\n if (!validDecisions.includes(o.decision)) {\n throw new Error('decision must be one of: ' + validDecisions.join(', '));\n }\n return buildMessage({\n messageType: 'decision',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n decision: o.decision,\n reason: o.reason || null,\n },\n });\n}\n\nfunction buildRevoke(opts) {\n var o = opts || {};\n return buildMessage({\n messageType: 'revoke',\n senderId: o.nodeId,\n payload: {\n target_asset_id: o.assetId || null,\n target_local_id: o.localId || null,\n reason: o.reason || null,\n },\n });\n}\n\n// --- Validation ---\n\nfunction isValidProtocolMessage(msg) {\n if (!msg || typeof msg !== 'object') return false;\n if (msg.protocol !== PROTOCOL_NAME) return false;\n if (!msg.message_type || !VALID_MESSAGE_TYPES.includes(msg.message_type)) return false;\n if (!msg.message_id || typeof msg.message_id !== 'string') return false;\n if (!msg.timestamp || typeof msg.timestamp !== 'string') return false;\n return true;\n}\n\n// Try to extract a raw asset from either a protocol message or a plain asset object.\n// This enables backward-compatible ingestion of both old-format and new-format payloads.\nfunction unwrapAssetFromMessage(input) {\n if (!input || typeof input !== 'object') return null;\n // If it is a protocol message with a publish payload, extract the asset.\n if (input.protocol === PROTOCOL_NAME && input.message_type === 'publish') {\n var p = input.payload;\n if (p && p.asset && typeof p.asset === 'object') return p.asset;\n return null;\n }\n // If it is a plain asset (Gene/Capsule/EvolutionEvent), return as-is.\n if (input.type === 'Gene' || input.type === 'Capsule' || input.type === 'EvolutionEvent') {\n return input;\n }\n return null;\n}\n\n// --- File Transport ---\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction defaultA2ADir() {\n return process.env.A2A_DIR || path.join(getGepAssetsDir(), 'a2a');\n}\n\nfunction fileTransportSend(message, opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'outbox');\n ensureDir(subdir);\n var filePath = path.join(subdir, message.message_type + '.jsonl');\n fs.appendFileSync(filePath, JSON.stringify(message) + '\\n', 'utf8');\n return { ok: true, path: filePath };\n}\n\nfunction fileTransportReceive(opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'inbox');\n if (!fs.existsSync(subdir)) return [];\n var files = fs.readdirSync(subdir).filter(function (f) { return f.endsWith('.jsonl'); });\n var messages = [];\n for (var fi = 0; fi < files.length; fi++) {\n try {\n var raw = fs.readFileSync(path.join(subdir, files[fi]), 'utf8');\n var lines = raw.split('\\n').map(function (l) { return l.trim(); }).filter(Boolean);\n for (var li = 0; li < lines.length; li++) {\n try {\n var msg = JSON.parse(lines[li]);\n if (msg && msg.protocol === PROTOCOL_NAME) messages.push(msg);\n } catch (e) {}\n }\n } catch (e) {}\n }\n return messages;\n}\n\nfunction fileTransportList(opts) {\n var dir = (opts && opts.dir) || defaultA2ADir();\n var subdir = path.join(dir, 'outbox');\n if (!fs.existsSync(subdir)) return [];\n return fs.readdirSync(subdir).filter(function (f) { return f.endsWith('.jsonl'); });\n}\n\n// --- HTTP Transport (connects to evomap-hub) ---\n\nfunction httpTransportSend(message, opts) {\n var hubUrl = (opts && opts.hubUrl) || process.env.A2A_HUB_URL;\n if (!hubUrl) return { ok: false, error: 'A2A_HUB_URL not set' };\n var endpoint = hubUrl.replace(/\\/+$/, '') + '/a2a/' + message.message_type;\n var body = JSON.stringify(message);\n // Use dynamic import for fetch (available in Node 18+)\n return fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: body,\n })\n .then(function (res) { return res.json(); })\n .then(function (data) { return { ok: true, response: data }; })\n .catch(function (err) { return { ok: false, error: err.message }; });\n}\n\nfunction httpTransportReceive(opts) {\n var hubUrl = (opts && opts.hubUrl) || process.env.A2A_HUB_URL;\n if (!hubUrl) return Promise.resolve([]);\n var assetType = (opts && opts.assetType) || null;\n var fetchMsg = buildFetch({ assetType: assetType });\n var endpoint = hubUrl.replace(/\\/+$/, '') + '/a2a/fetch';\n return fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(fetchMsg),\n })\n .then(function (res) { return res.json(); })\n .then(function (data) {\n if (data && data.payload && Array.isArray(data.payload.results)) {\n return data.payload.results;\n }\n return [];\n })\n .catch(function () { return []; });\n}\n\nfunction httpTransportList() {\n return ['http'];\n}\n\n// --- Transport registry ---\n\nvar transports = {\n file: {\n send: fileTransportSend,\n receive: fileTransportReceive,\n list: fileTransportList,\n },\n http: {\n send: httpTransportSend,\n receive: httpTransportReceive,\n list: httpTransportList,\n },\n};\n\nfunction getTransport(name) {\n var n = String(name || process.env.A2A_TRANSPORT || 'file').toLowerCase();\n var t = transports[n];\n if (!t) throw new Error('Unknown A2A transport: ' + n + '. Available: ' + Object.keys(transports).join(', '));\n return t;\n}\n\nfunction registerTransport(name, impl) {\n if (!name || typeof name !== 'string') throw new Error('transport name required');\n if (!impl || typeof impl.send !== 'function' || typeof impl.receive !== 'function') {\n throw new Error('transport must implement send() and receive()');\n }\n transports[name] = impl;\n}\n\nmodule.exports = {\n PROTOCOL_NAME,\n PROTOCOL_VERSION,\n VALID_MESSAGE_TYPES,\n getNodeId,\n buildMessage,\n buildHello,\n buildPublish,\n buildFetch,\n buildReport,\n buildDecision,\n buildRevoke,\n isValidProtocolMessage,\n unwrapAssetFromMessage,\n getTransport,\n registerTransport,\n fileTransportSend,\n fileTransportReceive,\n fileTransportList,\n httpTransportSend,\n httpTransportReceive,\n httpTransportList,\n};\n",
449 "inputSchema": {},
450 "outputSchema": null,
451 "icons": null,
452 "annotations": null,
453 "meta": null,
454 "execution": null
455 },
456 {
457 "name": "bridge.js",
458 "title": null,
459 "description": "Script: bridge.js. Code:\nconst fs = require('fs');\nconst path = require('path');\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clip(text, maxChars) {\n const s = String(text || '');\n const n = Number(maxChars);\n if (!Number.isFinite(n) || n <= 0) return s;\n if (s.length <= n) return s;\n return s.slice(0, Math.max(0, n - 40)) + '\\n...[TRUNCATED]...\\n';\n}\n\nfunction writePromptArtifact({ memoryDir, cycleId, runId, prompt, meta }) {\n const dir = String(memoryDir || '').trim();\n if (!dir) throw new Error('bridge: missing memoryDir');\n ensureDir(dir);\n const safeCycle = String(cycleId || 'cycle').replace(/[^a-zA-Z0-9_\\-#]/g, '_');\n const safeRun = String(runId || Date.now()).replace(/[^a-zA-Z0-9_\\-]/g, '_');\n const base = `gep_prompt_${safeCycle}_${safeRun}`;\n const promptPath = path.join(dir, base + '.txt');\n const metaPath = path.join(dir, base + '.json');\n\n fs.writeFileSync(promptPath, String(prompt || ''), 'utf8');\n fs.writeFileSync(\n metaPath,\n JSON.stringify(\n {\n type: 'GepPromptArtifact',\n at: nowIso(),\n cycle_id: cycleId || null,\n run_id: runId || null,\n prompt_path: promptPath,\n meta: meta && typeof meta === 'object' ? meta : null,\n },\n null,\n 2\n ) + '\\n',\n 'utf8'\n );\n\n return { promptPath, metaPath };\n}\n\nfunction renderSessionsSpawnCall({ task, agentId, label, cleanup }) {\n const t = String(task || '').trim();\n if (!t) throw new Error('bridge: missing task');\n const a = String(agentId || 'main');\n const l = String(label || 'gep_bridge');\n const c = cleanup ? String(cleanup) : 'delete';\n\n // Output valid JSON so wrappers can parse with JSON.parse (not regex).\n // The wrapper uses lastIndexOf('sessions_spawn(') + JSON.parse to extract the task.\n const payload = JSON.stringify({ task: t, agentId: a, cleanup: c, label: l });\n return `sessions_spawn(${payload})`;\n}\n\nmodule.exports = {\n clip,\n writePromptArtifact,\n renderSessionsSpawnCall,\n};\n\n",
460 "inputSchema": {},
461 "outputSchema": null,
462 "icons": null,
463 "annotations": null,
464 "meta": null,
465 "execution": null
466 },
467 {
468 "name": "envFingerprint.js",
469 "title": null,
470 "description": "Script: envFingerprint.js. Code:\n// Environment fingerprint capture for GEP assets.\n// Records the runtime environment so that cross-environment diffusion\n// success rates (GDI) can be measured scientifically.\n\nconst os = require('os');\nconst fs = require('fs');\nconst path = require('path');\nconst crypto = require('crypto');\nconst { getRepoRoot } = require('./paths');\n\n// Capture a structured environment fingerprint.\n// This is embedded into Capsules, EvolutionEvents, and ValidationReports.\nfunction captureEnvFingerprint() {\n const repoRoot = getRepoRoot();\n let pkgVersion = null;\n try {\n const raw = fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8');\n const pkg = JSON.parse(raw);\n pkgVersion = pkg && pkg.version ? String(pkg.version) : null;\n } catch (e) {}\n\n return {\n node_version: process.version,\n platform: process.platform,\n arch: process.arch,\n os_release: os.release(),\n evolver_version: pkgVersion,\n cwd: process.cwd(),\n captured_at: new Date().toISOString(),\n };\n}\n\n// Compute a short fingerprint key for comparison and grouping.\n// Two nodes with the same key are considered \"same environment class\".\nfunction envFingerprintKey(fp) {\n if (!fp || typeof fp !== 'object') return 'unknown';\n const parts = [\n fp.node_version || '',\n fp.platform || '',\n fp.arch || '',\n fp.evolver_version || '',\n ].join('|');\n return crypto.createHash('sha256').update(parts, 'utf8').digest('hex').slice(0, 16);\n}\n\n// Check if two fingerprints are from the same environment class.\nfunction isSameEnvClass(fpA, fpB) {\n return envFingerprintKey(fpA) === envFingerprintKey(fpB);\n}\n\nmodule.exports = {\n captureEnvFingerprint,\n envFingerprintKey,\n isSameEnvClass,\n};\n",
471 "inputSchema": {},
472 "outputSchema": null,
473 "icons": null,
474 "annotations": null,
475 "meta": null,
476 "execution": null
477 },
478 {
479 "name": "prompt.js",
480 "title": null,
481 "description": "Script: prompt.js. Code:\nconst { captureEnvFingerprint } = require('./envFingerprint');\nconst { resolveStrategy } = require('./strategy');\n\nfunction buildGepPrompt({\n nowIso,\n context,\n signals,\n selector,\n parentEventId,\n selectedGene,\n capsuleCandidates,\n genesPreview,\n capsulesPreview,\n capabilityCandidatesPreview,\n externalCandidatesPreview,\n recentInnovationTargets,\n}) {\n const parentValue = parentEventId ? `\"${parentEventId}\"` : 'null';\n const selectedGeneId = selectedGene && selectedGene.id ? selectedGene.id : null;\n const capsuleIds = (capsuleCandidates || []).map(c => c && c.id).filter(Boolean);\n const envFingerprint = captureEnvFingerprint();\n const strategy = resolveStrategy();\n\n const basePrompt = `\nGEP \u2014 GENOME EVOLUTION PROTOCOL (v1.9.1 STRICT) [${nowIso}] | Strategy: ${strategy.label}\n\nYou are not a chat assistant.\nYou are not a free agent.\nYou are a protocol-bound evolution execution engine.\n\nAll actions must comply with this protocol.\nAny deviation is a failure even if the outcome appears correct.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nI. Protocol Positioning (Non-Negotiable)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nProtocol goals:\n- Convert reasoning into reusable, auditable, shareable evolution assets\n- Make evolution a standard process, not improvisation\n- Reduce future reasoning cost for similar problems\n\nProtocol compliance overrides local optimality.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nII. Mandatory Evolution Object Model (All Required)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nEvery evolution run must explicitly output the following five objects.\nMissing any one is an immediate failure.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n0 Mutation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit a Mutation object for every evolution run:\n\n\\`\\`\\`json\n{\n \"type\": \"Mutation\",\n \"id\": \"mut_<timestamp>\",\n \"category\": \"repair | optimize | innovate\",\n \"trigger_signals\": [\"<signal>\"],\n \"target\": \"<module | behavior | gene>\",\n \"expected_effect\": \"<effect>\",\n \"risk_level\": \"low | medium | high\"\n}\n\\`\\`\\`\n\nHard safety constraints:\n- Do NOT run high-risk mutation unless rigor >= 0.6 AND risk_tolerance <= 0.5\n- Do NOT combine innovation mutation with a high-risk personality state\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1 PersonalityState\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit a PersonalityState object for every evolution run:\n\n\\`\\`\\`json\n{\n \"type\": \"PersonalityState\",\n \"rigor\": 0.0-1.0,\n \"creativity\": 0.0-1.0,\n \"verbosity\": 0.0-1.0,\n \"risk_tolerance\": 0.0-1.0,\n \"obedience\": 0.0-1.0\n}\n\\`\\`\\`\n\nPersonality mutation (optional, small deltas only):\n\\`\\`\\`json\n{\n \"type\": \"PersonalityMutation\",\n \"param\": \"creativity\",\n \"delta\": 0.1,\n \"reason\": \"<reason>\"\n}\n\\`\\`\\`\nConstraints:\n- Each delta must be within [-0.2, +0.2]\n- Do not adjust more than 2 parameters in one run\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n2 EvolutionEvent\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nYou must emit an EvolutionEvent with all fields present:\n\n\\`\\`\\`json\n{\n \"type\": \"EvolutionEvent\",\n \"id\": \"evt_<timestamp>\",\n \"parent\": ${parentValue},\n \"intent\": \"repair | optimize | innovate\",\n \"signals\": [\"<signal_1>\", \"<signal_2>\"],\n \"genes_used\": [\"<gene_id>\"],\n \"mutation_id\": \"<mut_id>\",\n \"personality_state\": { \"type\": \"PersonalityState\", \"...\": \"...\" },\n \"blast_radius\": {\n \"files\": <number>,\n \"lines\": <number>\n },\n \"outcome\": {\n \"status\": \"success | failed\",\n \"score\": <0.0-1.0>\n }\n}\n\\`\\`\\`\n\nEvolutionEvent is the only legal node type in the evolution tree.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n3 Gene\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nIf a Gene is used, you must reuse an existing Gene first.\nOnly create a new Gene when no match exists.\n\nGene must follow this schema:\n\n\\`\\`\\`json\n{\n \"type\": \"Gene\",\n \"id\": \"gene_<name>\",\n \"category\": \"repair | optimize | innovate\",\n \"signals_match\": [\"<pattern>\"],\n \"preconditions\": [\"<condition>\"],\n \"strategy\": [\n \"<step_1>\",\n \"<step_2>\"\n ],\n \"constraints\": {\n \"max_files\": <number>,\n \"forbidden_paths\": [\"<path>\"]\n },\n \"validation\": [\"<check_1>\", \"<check_2>\"]\n}\n\\`\\`\\`\n\nA Gene is an evolution interface definition, not code or generic advice.\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n4 Capsule\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nOnly when evolution succeeds, you must generate a Capsule:\n\n\\`\\`\\`json\n{\n \"type\": \"Capsule\",\n \"id\": \"capsule_<timestamp>\",\n \"trigger\": [\"<signal>\"],\n \"gene\": \"<gene_id>\",\n \"summary\": \"<one sentence>\",\n \"confidence\": <0.0-1.0>\n}\n\\`\\`\\`\n\nCapsules exist to prevent repeated reasoning for similar problems.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIII. Standard Evolution Execution\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nFollow these steps in order:\n\n1 Signal Extraction\n- Extract structured signals from logs, errors, metrics, or patterns.\n- SKIP trivial/cosmetic signals (e.g. \"user_missing\", \"memory_missing\") unless no better signals exist.\n- PRIORITIZE: capability gaps, recurring manual tasks, performance bottlenecks, error patterns.\n\n2 Intent Decision (repair / optimize / innovate)\n- \"repair\": Fix a bug or error found in logs.\n- \"optimize\": Improve performance, reduce code, harden error handling.\n- \"innovate\": Create a NEW capability, tool, or skill. This is the highest-value intent.\n- If no urgent repair signals exist, default to \"innovate\".\n- If signals contain \"force_innovation_after_repair_loop\" or \"evolution_stagnation_detected\",\n you MUST use \"innovate\" intent. These signals mean the system is stuck in a repair loop.\n- If signals contain \"repair_loop_detected\", do NOT choose \"repair\" intent.\n\n3 Selection\n- Prefer existing Genes first, then Capsules.\n- For \"innovate\" intent: if no Gene fits, you MAY freely invent without creating a Gene first.\n\n4 Execution\n- For \"repair\" / \"optimize\": changes should be small and reversible.\n- For \"innovate\": you MAY create entire new skills (new directories, multiple files, 200+ lines).\n Innovation is NOT constrained by blast_radius limits.\n- Always estimate and record blast_radius in the EvolutionEvent.\n\n5 Validation\n- Execute Gene-declared validation steps if applicable.\n- On failure, rollback and record a failed EvolutionEvent.\n\n6 Knowledge Solidification\n- Update or add Gene if a new pattern is found.\n- Generate Capsule on success.\n- Append EvolutionEvent.\n- For \"innovate\" intent: Mutation + EvolutionEvent are sufficient. Gene/Capsule are optional.\n\n7 Report (Mandatory)\n- You MUST report what you did using the reporting mechanism specified in the execution context.\n- The report MUST describe: what changed, why, and how to use it (if applicable).\n- Reports like \"Step Complete\" or \"Signal Check\" with no details are protocol violations.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIV. Selector (Mandatory Decision Logic)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nWhen choosing a Gene or Capsule, you must emit a Selector decision.\n\nSelector must be explainable, for example:\n\n\\`\\`\\`json\n{\n \"selected\": \"${selectedGeneId || '<gene_id>'}\",\n \"reason\": [\n \"signals exact match\",\n \"historical success rate high\",\n \"low blast radius\"\n ],\n \"alternatives\": ${JSON.stringify(capsuleIds.length ? capsuleIds : ['<gene_id_2>'])}\n}\n\\`\\`\\`\n\nSelector is part of the protocol, not an implementation detail.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nV. Hard Failure Rules\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nThe following are protocol violations:\n\n- Missing Mutation or EvolutionEvent\n- Missing Report (Step 7)\n- Success without ANY tangible output (code, fix, or new capability)\n- Cycles that only produce protocol objects with no real-world change\n\nFailures are not errors; they are required negative samples. Record them.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVI. Evolution Tree Awareness\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n- Every EvolutionEvent must declare parent\n- Never overwrite or delete historical events\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVII. Evolution Philosophy\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\n1. OBSERVE THE FULL PICTURE\n The session transcript shows what the main agent and user are doing.\n - Do NOT repeat or execute user requests. That is the main agent's job.\n - DO learn from patterns: what tasks recur? what fails often? what is manual?\n\n2. AUTOMATE RECURRING PATTERNS\n If something appears 3+ times in logs or has any reuse potential, automate it.\n Build a script, a skill, or a shortcut. Eliminate manual repetition.\n\n3. INTENT BALANCE (Strategy: ${strategy.label})\n Target allocation: ${Math.round(strategy.innovate * 100)}% innovate, ${Math.round(strategy.optimize * 100)}% optimize, ${Math.round(strategy.repair * 100)}% repair.\n ${strategy.innovate >= 0.5 ? 'A new working tool is worth more than a minor code cleanup.' : ''}\n ${strategy.repair >= 0.4 ? 'Prioritize fixing existing issues over building new things.' : ''}\n ${strategy.innovate >= 0.3 ? 'Each cycle SHOULD produce at least one of:\\n - A new executable skill or script\\n - A meaningful feature enhancement\\n - A creative automation or integration' : 'Focus on hardening and stabilizing the existing system.'}\n\n4. BUILD REAL THINGS\n Proposals, plans, and \"analysis\" are NOT evolution. Write code that runs.\n\n5. HARDEN THE SYSTEM (Robustness)\n When you see recurring errors (especially \"recurring_error\" or \"unsupported_input_type\" signals):\n - Diagnose the root cause from the error signature.\n - Implement a permanent fix (input validation, format conversion, graceful fallback).\n - Document the fix in the skill's README or create/update TROUBLESHOOTING.md.\n - Example: if GIF images crash the LLM, add a GIF-to-PNG converter or filter GIFs before sending.\n The system should NEVER crash repeatedly on the same error. Fix it once, forever.\n\n6. KNOWN ISSUES (DO NOT ATTEMPT TO FIX -- already handled externally)\n The following errors appear in logs but have been fixed or are managed outside the evolver:\n - \"230001: invalid message content\" -- Feishu messaging API content limit. Fixed in feishu-post/send.js (truncation + sanitization).\n - \"HTTP 400\" from feishu_doc_append/feishu_doc_write -- Block validation edge cases. Fixed in feishu-doc/input_guard.js.\n - \"gateway timeout after 630000ms\" -- Transient gateway slowness, auto-fallback to embedded mode.\n - \"ENOENT\" / \"spawn openclaw\" -- PATH resolution issue, fixed in wrapper with explicit binary search.\n If you see these errors in logs, SKIP THEM. Focus on NEW errors or genuinely unresolved issues.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nVIII. A2A Evolution Exchange (Optional)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nA2A payload types: Gene, Capsule, EvolutionEvent.\nExternal payloads must be staged as candidates first, validated before promotion.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nIX. Protected Files (NEVER delete or overwrite)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nThe following files are CRITICAL to system identity and operation.\nDeleting, overwriting, or emptying ANY of them is an IMMEDIATE PROTOCOL VIOLATION.\n\n- MEMORY.md\n- SOUL.md\n- IDENTITY.md\n- AGENTS.md\n- USER.md\n- HEARTBEAT.md\n- RECENT_EVENTS.md\n- TOOLS.md\n- TROUBLESHOOTING.md\n- openclaw.json\n- .env\n- memory/persona_*.md\n- memory/personas/**\n\nEvolver core source files (DO NOT modify -- managed by deploy pipeline):\n- skills/evolver/src/evolve.js\n- skills/evolver/src/gep/prompt.js\n- skills/evolver/src/gep/signals.js\n- skills/evolver/src/gep/solidify.js\n- skills/evolver/src/gep/selector.js\n- skills/evolver/src/gep/mutation.js\n- skills/evolver/src/gep/personality.js\n- skills/evolver/src/gep/memoryGraph.js\n- skills/evolver/src/gep/paths.js\n- skills/evolver/src/gep/bridge.js\n- skills/evolver/index.js\n- skills/evolver/package.json\n\nYou MAY append to or edit sections within identity/memory files listed above.\nYou MUST NOT delete them, truncate them to empty, or replace their entire content.\nYou MUST NOT modify evolver core source files -- they are deployed from a versioned repo.\nIf you need to reorganize a protected file, create a new version alongside it first.\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\nX. Forbidden Innovation Zones (DO NOT CREATE)\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nDO NOT create skills or scripts that duplicate existing infrastructure:\n\n- Process lifecycle management (start/stop/restart/watchdog/daemon/cron)\n Already provided by src/ops/lifecycle.js and the wrapper's --loop mode.\n- Skill health monitoring or auditing\n Already provided by src/ops/skills_monitor.js.\n- Evolver self-management (PID locks, singleton guards, loop schedulers)\n Already built into index.js and src/ops/.\n- Crontab or systemd installers\n System-level scheduling is managed by the operator, not the evolver.\n\nCreating duplicates of the above is a protocol violation.\n\nInstead, focus innovation on:\n- NEW capabilities the system does not have (tools, integrations, automations)\n- Enhancements to EXISTING user-facing skills\n- Automating recurring manual tasks observed in session logs\n\nFinal Directive\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\nYou are an evolution engine. Every cycle must leave the system measurably better.\nProtocol compliance matters, but tangible output matters more.\n\nContext [Innovation Cooldown]:\n${(() => {\n var targets = recentInnovationTargets || {};\n var keys = Object.keys(targets);\n if (keys.length === 0) return '(none -- all targets available)';\n return 'The following targets were innovated on in the last 10 cycles. Do NOT choose them again unless no other option exists:\\n' +\n keys.map(function(k) { return '- ' + k + ' (' + targets[k] + 'x)'; }).join('\\n');\n})()}\n\nContext [Signals]:\n${JSON.stringify(signals)}\n\nContext [Selector]:\n${JSON.stringify(selector, null, 2)}\n\nContext [Gene Preview]:\n${genesPreview}\n\nContext [Capsule Preview]:\n${capsulesPreview}\n\nContext [Capability Candidates] (Five questions shape; keep it short):\n${capabilityCandidatesPreview || '(none)'}\n\nContext [External Candidates] (A2A staged; do not execute directly):\n${externalCandidatesPreview || '(none)'}\n\nContext [Env Fingerprint]:\n${JSON.stringify(envFingerprint, null, 2)}\n\nContext [Execution]:\n${context}\n`.trim();\n\n const maxChars = Number.isFinite(Number(process.env.GEP_PROMPT_MAX_CHARS))\n ? Number(process.env.GEP_PROMPT_MAX_CHARS)\n : 30000;\n\n if (basePrompt.length <= maxChars) return basePrompt;\n\n // Budget strategy: keep the protocol and structured assets, shrink execution context first.\n const headKeep = Math.min(basePrompt.length, Math.floor(maxChars * 0.75));\n const tailKeep = Math.max(0, maxChars - headKeep - 120);\n const head = basePrompt.slice(0, headKeep);\n const tail = tailKeep > 0 ? basePrompt.slice(basePrompt.length - tailKeep) : '';\n return `${head}\\n\\n...[PROMPT TRUNCATED FOR BUDGET]...\\n\\n${tail}`.slice(0, maxChars);\n}\n\nmodule.exports = { buildGepPrompt };\n\n",
482 "inputSchema": {},
483 "outputSchema": null,
484 "icons": null,
485 "annotations": null,
486 "meta": null,
487 "execution": null
488 },
489 {
490 "name": "strategy.js",
491 "title": null,
492 "description": "Script: strategy.js. Code:\n// Evolution Strategy Presets (v1.0)\n// Controls the balance between repair, optimize, and innovate intents.\n//\n// Usage: set EVOLVE_STRATEGY env var to one of: balanced, innovate, harden, repair-only\n// Default: balanced\n//\n// Each strategy defines:\n// repair/optimize/innovate - target allocation ratios (inform the LLM prompt)\n// repairLoopThreshold - repair ratio in last 8 cycles that triggers forced innovation\n// label - human-readable name injected into the GEP prompt\n\nvar STRATEGIES = {\n 'balanced': {\n repair: 0.20,\n optimize: 0.30,\n innovate: 0.50,\n repairLoopThreshold: 0.50,\n label: 'Balanced',\n description: 'Normal operation. Steady growth with stability.',\n },\n 'innovate': {\n repair: 0.05,\n optimize: 0.15,\n innovate: 0.80,\n repairLoopThreshold: 0.30,\n label: 'Innovation Focus',\n description: 'System is stable. Maximize new features and capabilities.',\n },\n 'harden': {\n repair: 0.40,\n optimize: 0.40,\n innovate: 0.20,\n repairLoopThreshold: 0.70,\n label: 'Hardening',\n description: 'After a big change. Focus on stability and robustness.',\n },\n 'repair-only': {\n repair: 0.80,\n optimize: 0.20,\n innovate: 0.00,\n repairLoopThreshold: 1.00,\n label: 'Repair Only',\n description: 'Emergency. Fix everything before doing anything else.',\n },\n};\n\nfunction resolveStrategy() {\n var name = String(process.env.EVOLVE_STRATEGY || 'balanced').toLowerCase().trim();\n // Backward compatibility: FORCE_INNOVATION=true maps to 'innovate'\n if (!process.env.EVOLVE_STRATEGY) {\n var fi = String(process.env.FORCE_INNOVATION || process.env.EVOLVE_FORCE_INNOVATION || '').toLowerCase();\n if (fi === 'true') name = 'innovate';\n }\n var strategy = STRATEGIES[name] || STRATEGIES['balanced'];\n strategy.name = name;\n return strategy;\n}\n\nfunction getStrategyNames() {\n return Object.keys(STRATEGIES);\n}\n\nmodule.exports = { resolveStrategy, getStrategyNames, STRATEGIES };\n",
493 "inputSchema": {},
494 "outputSchema": null,
495 "icons": null,
496 "annotations": null,
497 "meta": null,
498 "execution": null
499 },
500 {
501 "name": "selector.js",
502 "title": null,
503 "description": "Script: selector.js. Code:\nfunction matchPatternToSignals(pattern, signals) {\n if (!pattern || !signals || signals.length === 0) return false;\n const p = String(pattern);\n const sig = signals.map(s => String(s));\n\n const regexLike = p.length >= 2 && p.startsWith('/') && p.lastIndexOf('/') > 0;\n if (regexLike) {\n const lastSlash = p.lastIndexOf('/');\n const body = p.slice(1, lastSlash);\n const flags = p.slice(lastSlash + 1);\n try {\n const re = new RegExp(body, flags || 'i');\n return sig.some(s => re.test(s));\n } catch (e) {\n // fallback to substring\n }\n }\n\n const needle = p.toLowerCase();\n return sig.some(s => s.toLowerCase().includes(needle));\n}\n\nfunction scoreGene(gene, signals) {\n if (!gene || gene.type !== 'Gene') return 0;\n const patterns = Array.isArray(gene.signals_match) ? gene.signals_match : [];\n if (patterns.length === 0) return 0;\n let score = 0;\n for (const pat of patterns) {\n if (matchPatternToSignals(pat, signals)) score += 1;\n }\n return score;\n}\n\nfunction selectGene(genes, signals, opts) {\n const bannedGeneIds = opts && opts.bannedGeneIds ? opts.bannedGeneIds : new Set();\n const driftEnabled = !!(opts && opts.driftEnabled);\n const preferredGeneId = opts && typeof opts.preferredGeneId === 'string' ? opts.preferredGeneId : null;\n\n const scored = genes\n .map(g => ({ gene: g, score: scoreGene(g, signals) }))\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score);\n\n if (scored.length === 0) return { selected: null, alternatives: [] };\n\n // Memory graph preference: only override when the preferred gene is already a match candidate.\n if (preferredGeneId) {\n const preferred = scored.find(x => x.gene && x.gene.id === preferredGeneId);\n if (preferred && (driftEnabled || !bannedGeneIds.has(preferredGeneId))) {\n const rest = scored.filter(x => x.gene && x.gene.id !== preferredGeneId);\n const filteredRest = driftEnabled ? rest : rest.filter(x => x.gene && !bannedGeneIds.has(x.gene.id));\n return {\n selected: preferred.gene,\n alternatives: filteredRest.slice(0, 4).map(x => x.gene),\n };\n }\n }\n\n // Low-efficiency suppression: do not repeat low-confidence paths unless drift is explicit.\n const filtered = driftEnabled ? scored : scored.filter(x => x.gene && !bannedGeneIds.has(x.gene.id));\n if (filtered.length === 0) return { selected: null, alternatives: scored.slice(0, 4).map(x => x.gene) };\n\n return {\n selected: filtered[0].gene,\n alternatives: filtered.slice(1, 4).map(x => x.gene),\n };\n}\n\nfunction selectCapsule(capsules, signals) {\n const scored = (capsules || [])\n .map(c => {\n const triggers = Array.isArray(c.trigger) ? c.trigger : [];\n const score = triggers.reduce((acc, t) => (matchPatternToSignals(t, signals) ? acc + 1 : acc), 0);\n return { capsule: c, score };\n })\n .filter(x => x.score > 0)\n .sort((a, b) => b.score - a.score);\n return scored.length ? scored[0].capsule : null;\n}\n\nfunction selectGeneAndCapsule({ genes, capsules, signals, memoryAdvice, driftEnabled }) {\n const bannedGeneIds =\n memoryAdvice && memoryAdvice.bannedGeneIds instanceof Set ? memoryAdvice.bannedGeneIds : new Set();\n const preferredGeneId = memoryAdvice && memoryAdvice.preferredGeneId ? memoryAdvice.preferredGeneId : null;\n\n const { selected, alternatives } = selectGene(genes, signals, {\n bannedGeneIds,\n preferredGeneId,\n driftEnabled: !!driftEnabled,\n });\n const capsule = selectCapsule(capsules, signals);\n const selector = buildSelectorDecision({\n gene: selected,\n capsule,\n signals,\n alternatives,\n memoryAdvice,\n driftEnabled,\n });\n return {\n selectedGene: selected,\n capsuleCandidates: capsule ? [capsule] : [],\n selector,\n };\n}\n\nfunction buildSelectorDecision({ gene, capsule, signals, alternatives, memoryAdvice, driftEnabled }) {\n const reason = [];\n if (gene) reason.push('signals match gene.signals_match');\n if (capsule) reason.push('capsule trigger matches signals');\n if (!gene) reason.push('no matching gene found; new gene may be required');\n if (signals && signals.length) reason.push(`signals: ${signals.join(', ')}`);\n\n if (memoryAdvice && Array.isArray(memoryAdvice.explanation) && memoryAdvice.explanation.length) {\n reason.push(`memory_graph: ${memoryAdvice.explanation.join(' | ')}`);\n }\n if (driftEnabled) {\n reason.push('random_drift_override: true');\n }\n\n return {\n selected: gene ? gene.id : null,\n reason,\n alternatives: Array.isArray(alternatives) ? alternatives.map(g => g.id) : [],\n };\n}\n\nmodule.exports = {\n selectGeneAndCapsule,\n selectGene,\n selectCapsule,\n buildSelectorDecision,\n};\n\n",
504 "inputSchema": {},
505 "outputSchema": null,
506 "icons": null,
507 "annotations": null,
508 "meta": null,
509 "execution": null
510 },
511 {
512 "name": "signals.js",
513 "title": null,
514 "description": "Script: signals.js. Code:\nvar { resolveStrategy } = require('./strategy');\n\n// Opportunity signal names (shared with mutation.js and personality.js).\nvar OPPORTUNITY_SIGNALS = [\n 'user_feature_request',\n 'user_improvement_suggestion',\n 'perf_bottleneck',\n 'capability_gap',\n 'stable_success_plateau',\n 'external_opportunity',\n 'recurring_error',\n 'unsupported_input_type',\n 'evolution_stagnation_detected',\n 'repair_loop_detected',\n 'force_innovation_after_repair_loop',\n];\n\nfunction hasOpportunitySignal(signals) {\n var list = Array.isArray(signals) ? signals : [];\n for (var i = 0; i < OPPORTUNITY_SIGNALS.length; i++) {\n if (list.includes(OPPORTUNITY_SIGNALS[i])) return true;\n }\n return false;\n}\n\n// Build a de-duplication set from recent evolution events.\n// Returns an object: { suppressedSignals: Set<string>, recentIntents: string[], consecutiveRepairCount: number }\nfunction analyzeRecentHistory(recentEvents) {\n if (!Array.isArray(recentEvents) || recentEvents.length === 0) {\n return { suppressedSignals: new Set(), recentIntents: [], consecutiveRepairCount: 0 };\n }\n // Take only the last 10 events\n var recent = recentEvents.slice(-10);\n\n // Count consecutive same-intent runs at the tail\n var consecutiveRepairCount = 0;\n for (var i = recent.length - 1; i >= 0; i--) {\n if (recent[i].intent === 'repair') {\n consecutiveRepairCount++;\n } else {\n break;\n }\n }\n\n // Count signal frequency in last 8 events: signal -> count\n var signalFreq = {};\n var geneFreq = {};\n var tail = recent.slice(-8);\n for (var j = 0; j < tail.length; j++) {\n var evt = tail[j];\n var sigs = Array.isArray(evt.signals) ? evt.signals : [];\n for (var k = 0; k < sigs.length; k++) {\n var s = String(sigs[k]);\n // Normalize: ignore errsig details for frequency counting\n var key = s.startsWith('errsig:') ? 'errsig' : s.startsWith('recurring_errsig') ? 'recurring_errsig' : s;\n signalFreq[key] = (signalFreq[key] || 0) + 1;\n }\n var genes = Array.isArray(evt.genes_used) ? evt.genes_used : [];\n for (var g = 0; g < genes.length; g++) {\n geneFreq[String(genes[g])] = (geneFreq[String(genes[g])] || 0) + 1;\n }\n }\n\n // Suppress signals that appeared in 3+ of the last 8 events (they are being over-processed)\n var suppressedSignals = new Set();\n var entries = Object.entries(signalFreq);\n for (var ei = 0; ei < entries.length; ei++) {\n if (entries[ei][1] >= 3) {\n suppressedSignals.add(entries[ei][0]);\n }\n }\n\n var recentIntents = recent.map(function(e) { return e.intent || 'unknown'; });\n\n // Track recent innovation targets to prevent repeated work on the same skill/module\n var recentInnovationTargets = {};\n for (var ti = 0; ti < recent.length; ti++) {\n var tevt = recent[ti];\n if (tevt.intent === 'innovate' && tevt.mutation_id) {\n var tgt = (tevt.mutation && tevt.mutation.target) || '';\n if (!tgt) {\n var sum = String(tevt.summary || tevt.capsule_summary || '');\n var skillMatch = sum.match(/skills\\/([a-zA-Z0-9_-]+)/);\n if (skillMatch) tgt = 'skills/' + skillMatch[1];\n }\n if (tgt) {\n recentInnovationTargets[tgt] = (recentInnovationTargets[tgt] || 0) + 1;\n }\n }\n }\n\n return { suppressedSignals: suppressedSignals, recentIntents: recentIntents, consecutiveRepairCount: consecutiveRepairCount, signalFreq: signalFreq, geneFreq: geneFreq, recentInnovationTargets: recentInnovationTargets };\n}\n\nfunction extractSignals({ recentSessionTranscript, todayLog, memorySnippet, userSnippet, recentEvents }) {\n var signals = [];\n var corpus = [\n String(recentSessionTranscript || ''),\n String(todayLog || ''),\n String(memorySnippet || ''),\n String(userSnippet || ''),\n ].join('\\n');\n var lower = corpus.toLowerCase();\n\n // Analyze recent evolution history for de-duplication\n var history = analyzeRecentHistory(recentEvents || []);\n\n // --- Defensive signals (errors, missing resources) ---\n\n var errorHit = /\\[error|error:|exception|fail|failed|iserror\":true/.test(lower);\n if (errorHit) signals.push('log_error');\n\n // Error signature (more reproducible than a coarse \"log_error\" tag).\n try {\n var lines = corpus\n .split('\\n')\n .map(function (l) { return String(l || '').trim(); })\n .filter(Boolean);\n\n var errLine =\n lines.find(function (l) { return /\\b(typeerror|referenceerror|syntaxerror)\\b\\s*:|error\\s*:|exception\\s*:|\\[error/i.test(l); }) ||\n null;\n\n if (errLine) {\n var clipped = errLine.replace(/\\s+/g, ' ').slice(0, 260);\n signals.push('errsig:' + clipped);\n }\n } catch (e) {}\n\n if (lower.includes('memory.md missing')) signals.push('memory_missing');\n if (lower.includes('user.md missing')) signals.push('user_missing');\n if (lower.includes('key missing')) signals.push('integration_key_missing');\n if (lower.includes('no session logs found') || lower.includes('no jsonl files')) signals.push('session_logs_missing');\n if (lower.includes('pgrep') || lower.includes('ps aux')) signals.push('windows_shell_incompatible');\n if (lower.includes('path.resolve(__dirname, \\'../../')) signals.push('path_outside_workspace');\n\n // Protocol-specific drift signals\n if (lower.includes('prompt') && !lower.includes('evolutionevent')) signals.push('protocol_drift');\n\n // --- Recurring error detection (robustness signals) ---\n // Count repeated identical errors -- these indicate systemic issues that need automated fixes\n try {\n var errorCounts = {};\n var errPatterns = corpus.match(/(?:LLM error|\"error\"|\"status\":\\s*\"error\")[^}]{0,200}/gi) || [];\n for (var ep = 0; ep < errPatterns.length; ep++) {\n // Normalize to a short key\n var key = errPatterns[ep].replace(/\\s+/g, ' ').slice(0, 100);\n errorCounts[key] = (errorCounts[key] || 0) + 1;\n }\n var recurringErrors = Object.entries(errorCounts).filter(function (e) { return e[1] >= 3; });\n if (recurringErrors.length > 0) {\n signals.push('recurring_error');\n // Include the top recurring error signature for the agent to diagnose\n var topErr = recurringErrors.sort(function (a, b) { return b[1] - a[1]; })[0];\n signals.push('recurring_errsig(' + topErr[1] + 'x):' + topErr[0].slice(0, 150));\n }\n } catch (e) {}\n\n // --- Unsupported input type (e.g. GIF, video formats the LLM can't handle) ---\n if (/unsupported mime|unsupported.*type|invalid.*mime/i.test(lower)) {\n signals.push('unsupported_input_type');\n }\n\n // --- Opportunity signals (innovation / feature requests) ---\n\n // user_feature_request: user explicitly asks for a new capability\n // Look for action verbs + object patterns that indicate a feature request\n if (/\\b(add|implement|create|build|make|develop|write|design)\\b[^.?!\\n]{3,60}\\b(feature|function|module|capability|tool|support|endpoint|command|option|mode)\\b/i.test(corpus)) {\n signals.push('user_feature_request');\n }\n // Also catch direct \"I want/need X\" patterns\n if (/\\b(i want|i need|we need|please add|can you add|could you add|let'?s add)\\b/i.test(lower)) {\n signals.push('user_feature_request');\n }\n\n // user_improvement_suggestion: user suggests making something better\n if (/\\b(should be|could be better|improve|enhance|upgrade|refactor|clean up|simplify|streamline)\\b/i.test(lower)) {\n // Only fire if there is no active error (to distinguish from repair requests)\n if (!errorHit) signals.push('user_improvement_suggestion');\n }\n\n // perf_bottleneck: performance issues detected\n if (/\\b(slow|timeout|timed?\\s*out|latency|bottleneck|took too long|performance issue|high cpu|high memory|oom|out of memory)\\b/i.test(lower)) {\n signals.push('perf_bottleneck');\n }\n\n // capability_gap: something is explicitly unsupported or missing\n if (/\\b(not supported|cannot|doesn'?t support|no way to|missing feature|unsupported|not available|not implemented|no support for)\\b/i.test(lower)) {\n // Only fire if it is not just a missing file/config signal\n if (!signals.includes('memory_missing') && !signals.includes('user_missing') && !signals.includes('session_logs_missing')) {\n signals.push('capability_gap');\n }\n }\n\n // --- Tool Usage Analytics (auto-evolved) ---\n // Detect high-frequency tool usage patterns that suggest automation opportunities\n var toolUsage = {};\n var toolMatches = corpus.match(/\\[TOOL:\\s*(\\w+)\\]/g) || [];\n for (var ti = 0; ti < toolMatches.length; ti++) {\n var toolName = toolMatches[ti].match(/\\[TOOL:\\s*(\\w+)\\]/)[1];\n toolUsage[toolName] = (toolUsage[toolName] || 0) + 1;\n }\n Object.keys(toolUsage).forEach(function(tool) {\n if (toolUsage[tool] >= 5) {\n signals.push('high_tool_usage:' + tool);\n }\n if (tool === 'exec' && toolUsage[tool] >= 3) {\n signals.push('repeated_tool_usage:exec');\n }\n });\n\n // --- Signal prioritization ---\n // Remove cosmetic signals when actionable signals exist\n var actionable = signals.filter(function (s) {\n return s !== 'user_missing' && s !== 'memory_missing' && s !== 'session_logs_missing' && s !== 'windows_shell_incompatible';\n });\n // If we have actionable signals, drop the cosmetic ones\n if (actionable.length > 0) {\n signals = actionable;\n }\n\n // --- De-duplication: suppress signals that have been over-processed ---\n if (history.suppressedSignals.size > 0) {\n var beforeDedup = signals.length;\n signals = signals.filter(function (s) {\n // Normalize signal key for comparison\n var key = s.startsWith('errsig:') ? 'errsig' : s.startsWith('recurring_errsig') ? 'recurring_errsig' : s;\n return !history.suppressedSignals.has(key);\n });\n if (beforeDedup > 0 && signals.length === 0) {\n // All signals were suppressed = system is stable but stuck in a loop\n // Force innovation\n signals.push('evolution_stagnation_detected');\n signals.push('stable_success_plateau');\n }\n }\n\n // --- Force innovation when repair-heavy (ratio or consecutive) ---\n // Threshold is strategy-aware: \"innovate\" mode triggers sooner, \"harden\" mode allows more repairs\n var strategy = resolveStrategy();\n var repairRatio = 0;\n if (history.recentIntents && history.recentIntents.length > 0) {\n var repairCount = history.recentIntents.filter(function(i) { return i === 'repair'; }).length;\n repairRatio = repairCount / history.recentIntents.length;\n }\n var shouldForceInnovation = strategy.name === 'repair-only' ? false :\n (history.consecutiveRepairCount >= 3 || repairRatio >= strategy.repairLoopThreshold);\n if (shouldForceInnovation) {\n // Remove repair-only signals (log_error, errsig) and inject innovation signals\n signals = signals.filter(function (s) {\n return s !== 'log_error' && !s.startsWith('errsig:') && !s.startsWith('recurring_errsig');\n });\n if (signals.length === 0) {\n signals.push('repair_loop_detected');\n signals.push('stable_success_plateau');\n }\n // Append a directive signal that the prompt can pick up\n signals.push('force_innovation_after_repair_loop');\n }\n\n // If no signals at all, add a default innovation signal\n if (signals.length === 0) {\n signals.push('stable_success_plateau');\n }\n\n return Array.from(new Set(signals));\n}\n\nmodule.exports = { extractSignals, hasOpportunitySignal, analyzeRecentHistory, OPPORTUNITY_SIGNALS };\n",
515 "inputSchema": {},
516 "outputSchema": null,
517 "icons": null,
518 "annotations": null,
519 "meta": null,
520 "execution": null
521 },
522 {
523 "name": "memoryGraph.js",
524 "title": null,
525 "description": "Script: memoryGraph.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { getMemoryDir } = require('./paths');\nconst { normalizePersonalityState, isValidPersonalityState, personalityKey } = require('./personality');\nconst { isValidMutation, normalizeMutation } = require('./mutation');\n\nfunction ensureDir(dir) {\n try {\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n } catch (e) {}\n}\n\nfunction stableHash(input) {\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction normalizeErrorSignature(text) {\n const s = String(text || '').trim();\n if (!s) return null;\n return (\n s\n .toLowerCase()\n // normalize Windows paths\n .replace(/[a-z]:\\\\[^ \\n\\r\\t]+/gi, '<path>')\n // normalize Unix paths\n .replace(/\\/[^ \\n\\r\\t]+/g, '<path>')\n // normalize hex and numbers\n .replace(/\\b0x[0-9a-f]+\\b/gi, '<hex>')\n .replace(/\\b\\d+\\b/g, '<n>')\n // normalize whitespace\n .replace(/\\s+/g, ' ')\n .slice(0, 220)\n );\n}\n\nfunction normalizeSignalsForMatching(signals) {\n const list = Array.isArray(signals) ? signals : [];\n const out = [];\n for (const s of list) {\n const str = String(s || '').trim();\n if (!str) continue;\n if (str.startsWith('errsig:')) {\n const norm = normalizeErrorSignature(str.slice('errsig:'.length));\n if (norm) out.push(`errsig_norm:${stableHash(norm)}`);\n continue;\n }\n out.push(str);\n }\n return out;\n}\n\nfunction computeSignalKey(signals) {\n // Key must be stable across runs; normalize noisy signatures (paths, numbers).\n const list = normalizeSignalsForMatching(signals);\n const uniq = Array.from(new Set(list.filter(Boolean))).sort();\n return uniq.join('|') || '(none)';\n}\n\nfunction extractErrorSignatureFromSignals(signals) {\n // Convention: signals can include \"errsig:<raw>\" emitted by signals extractor.\n const list = Array.isArray(signals) ? signals : [];\n for (const s of list) {\n const str = String(s || '');\n if (str.startsWith('errsig:')) return normalizeErrorSignature(str.slice('errsig:'.length));\n }\n return null;\n}\n\nfunction memoryGraphPath() {\n const { getEvolutionDir } = require('./paths');\n const evoDir = getEvolutionDir();\n return process.env.MEMORY_GRAPH_PATH || path.join(evoDir, 'memory_graph.jsonl');\n}\n\nfunction memoryGraphStatePath() {\n const { getEvolutionDir } = require('./paths');\n return path.join(getEvolutionDir(), 'memory_graph_state.json');\n}\n\nfunction appendJsonl(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n fs.appendFileSync(filePath, JSON.stringify(obj) + '\\n', 'utf8');\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch (e) {\n return fallback;\n }\n}\n\nfunction writeJsonAtomic(filePath, obj) {\n const dir = path.dirname(filePath);\n ensureDir(dir);\n const tmp = `${filePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(obj, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction tryReadMemoryGraphEvents(limitLines = 2000) {\n try {\n const p = memoryGraphPath();\n if (!fs.existsSync(p)) return [];\n const raw = fs.readFileSync(p, 'utf8');\n const lines = raw\n .split('\\n')\n .map(l => l.trim())\n .filter(Boolean);\n const recent = lines.slice(Math.max(0, lines.length - limitLines));\n return recent\n .map(l => {\n try {\n return JSON.parse(l);\n } catch (e) {\n return null;\n }\n })\n .filter(Boolean);\n } catch (e) {\n return [];\n }\n}\n\nfunction jaccard(aList, bList) {\n const aNorm = normalizeSignalsForMatching(aList);\n const bNorm = normalizeSignalsForMatching(bList);\n const a = new Set((Array.isArray(aNorm) ? aNorm : []).map(String));\n const b = new Set((Array.isArray(bNorm) ? bNorm : []).map(String));\n if (a.size === 0 && b.size === 0) return 1;\n if (a.size === 0 || b.size === 0) return 0;\n let inter = 0;\n for (const x of a) if (b.has(x)) inter++;\n const union = a.size + b.size - inter;\n return union === 0 ? 0 : inter / union;\n}\n\nfunction decayWeight(updatedAtIso, halfLifeDays) {\n const hl = Number(halfLifeDays);\n if (!Number.isFinite(hl) || hl <= 0) return 1;\n const t = Date.parse(updatedAtIso);\n if (!Number.isFinite(t)) return 1;\n const ageDays = (Date.now() - t) / (1000 * 60 * 60 * 24);\n if (!Number.isFinite(ageDays) || ageDays <= 0) return 1;\n // Exponential half-life decay: weight = 0.5^(age/hl)\n return Math.pow(0.5, ageDays / hl);\n}\n\nfunction aggregateEdges(events) {\n // Aggregate by (signal_key, gene_id) from outcome events.\n // Laplace smoothing to avoid 0/1 extremes.\n const map = new Map();\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n if (ev.kind !== 'outcome') continue;\n const signalKey = ev.signal && ev.signal.key ? String(ev.signal.key) : '(none)';\n const geneId = ev.gene && ev.gene.id ? String(ev.gene.id) : null;\n if (!geneId) continue;\n\n const k = `${signalKey}::${geneId}`;\n const cur = map.get(k) || { signalKey, geneId, success: 0, fail: 0, last_ts: null, last_score: null };\n const status = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (status === 'success') cur.success += 1;\n else if (status === 'failed') cur.fail += 1;\n\n const ts = ev.ts || ev.created_at || ev.at;\n if (ts && (!cur.last_ts || Date.parse(ts) > Date.parse(cur.last_ts))) {\n cur.last_ts = ts;\n cur.last_score =\n ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? Number(ev.outcome.score) : cur.last_score;\n }\n map.set(k, cur);\n }\n return map;\n}\n\nfunction aggregateGeneOutcomes(events) {\n // Aggregate by gene_id from outcome events (gene -> outcome success probability).\n const map = new Map();\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n if (ev.kind !== 'outcome') continue;\n const geneId = ev.gene && ev.gene.id ? String(ev.gene.id) : null;\n if (!geneId) continue;\n const cur = map.get(geneId) || { geneId, success: 0, fail: 0, last_ts: null, last_score: null };\n const status = ev.outcome && ev.outcome.status ? String(ev.outcome.status) : 'unknown';\n if (status === 'success') cur.success += 1;\n else if (status === 'failed') cur.fail += 1;\n const ts = ev.ts || ev.created_at || ev.at;\n if (ts && (!cur.last_ts || Date.parse(ts) > Date.parse(cur.last_ts))) {\n cur.last_ts = ts;\n cur.last_score =\n ev.outcome && Number.isFinite(Number(ev.outcome.score)) ? Number(ev.outcome.score) : cur.last_score;\n }\n map.set(geneId, cur);\n }\n return map;\n}\n\nfunction edgeExpectedSuccess(edge, opts) {\n const e = edge || { success: 0, fail: 0, last_ts: null };\n const succ = Number(e.success) || 0;\n const fail = Number(e.fail) || 0;\n const total = succ + fail;\n const p = (succ + 1) / (total + 2); // Laplace smoothing\n const halfLifeDays = opts && Number.isFinite(Number(opts.half_life_days)) ? Number(opts.half_life_days) : 30;\n const w = decayWeight(e.last_ts || '', halfLifeDays);\n return { p, w, total, value: p * w };\n}\n\nfunction getMemoryAdvice({ signals, genes, driftEnabled }) {\n const events = tryReadMemoryGraphEvents(2000);\n const edges = aggregateEdges(events);\n const geneOutcomes = aggregateGeneOutcomes(events);\n const curSignals = Array.isArray(signals) ? signals : [];\n const curKey = computeSignalKey(curSignals);\n\n const bannedGeneIds = new Set();\n const scoredGeneIds = [];\n\n // Similarity: consider exact key first, then any key with overlap.\n const seenKeys = new Set();\n const candidateKeys = [];\n candidateKeys.push({ key: curKey, sim: 1 });\n seenKeys.add(curKey);\n\n for (const ev of events) {\n if (!ev || ev.type !== 'MemoryGraphEvent') continue;\n const k = ev.signal && ev.signal.key ? String(ev.signal.key) : '(none)';\n if (seenKeys.has(k)) continue;\n const sigs = ev.signal && Array.isArray(ev.signal.signals) ? ev.signal.signals : [];\n const sim = jaccard(curSignals, sigs);\n if (sim >= 0.34) {\n candidateKeys.push({ key: k, sim });\n seenKeys.add(k);\n }\n }\n\n const byGene = new Map();\n for (const ck of candidateKeys) {\n for (const g of Array.isArray(genes) ? genes : []) {\n if (!g || g.type !== 'Gene' || !g.id) continue;\n const k = `${ck.key}::${g.id}`;\n const edge = edges.get(k);\n const cur = byGene.get(g.id) || { geneId: g.id, best: 0, attempts: 0, prior: 0, prior_attempts: 0 };\n\n // Signal->Gene edge score (if available)\n if (edge) {\n const ex = edgeExpectedSuccess(edge, { half_life_days: 30 });\n const weighted = ex.value * ck.sim;\n if (weighted > cur.best) cur.best = weighted;\n cur.attempts = Math.max(cur.attempts, ex.total);\n }\n\n // Gene->Outcome prior (independent of signal): stabilizer when signal edges are sparse.\n const gEdge = geneOutcomes.get(String(g.id));\n if (gEdge) {\n const gx = edgeExpectedSuccess(gEdge, { half_life_days: 45 });\n cur.prior = Math.max(cur.prior, gx.value);\n cur.prior_attempts = Math.max(cur.prior_attempts, gx.total);\n }\n\n byGene.set(g.id, cur);\n }\n }\n\n for (const [geneId, info] of byGene.entries()) {\n const combined = info.best > 0 ? info.best + info.prior * 0.12 : info.prior * 0.4;\n scoredGeneIds.push({ geneId, score: combined, attempts: info.attempts, prior: info.prior });\n // Low-efficiency path suppression (unless drift is explicit).\n if (!driftEnabled && info.attempts >= 2 && info.best < 0.18) {\n bannedGeneIds.add(geneId);\n }\n // Also suppress genes with consistently poor global outcomes when signal edges are sparse.\n if (!driftEnabled && info.attempts < 2 && info.prior_attempts >= 3 && info.prior < 0.12) {\n bannedGeneIds.add(geneId);\n }\n }\n\n scoredGeneIds.sort((a, b) => b.score - a.score);\n const preferredGeneId = scoredGeneIds.length ? scoredGeneIds[0].geneId : null;\n\n const explanation = [];\n if (preferredGeneId) explanation.push(`memory_prefer:${preferredGeneId}`);\n if (bannedGeneIds.size) explanation.push(`memory_ban:${Array.from(bannedGeneIds).slice(0, 6).join(',')}`);\n if (preferredGeneId) {\n const top = scoredGeneIds.find(x => x && x.geneId === preferredGeneId);\n if (top && Number.isFinite(Number(top.prior)) && top.prior > 0) explanation.push(`gene_prior:${top.prior.toFixed(3)}`);\n }\n if (driftEnabled) explanation.push('random_drift:enabled');\n\n return {\n currentSignalKey: curKey,\n preferredGeneId,\n bannedGeneIds,\n explanation,\n };\n}\n\nfunction recordSignalSnapshot({ signals, observations }) {\n const signalKey = computeSignalKey(signals);\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'signal',\n id: `mge_${Date.now()}_${stableHash(`${signalKey}|signal|${ts}`)}`,\n ts,\n signal: {\n key: signalKey,\n signals: Array.isArray(signals) ? signals : [],\n error_signature: errsig || null,\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n appendJsonl(memoryGraphPath(), ev);\n return ev;\n}\n\nfunction buildHypothesisText({ signalKey, signals, geneId, geneCategory, driftEnabled }) {\n const sigCount = Array.isArray(signals) ? signals.length : 0;\n const drift = driftEnabled ? 'drift' : 'directed';\n const g = geneId ? `${geneId}${geneCategory ? `(${geneCategory})` : ''}` : '(none)';\n return `Given signal_key=${signalKey} with ${sigCount} signals, selecting gene=${g} under mode=${drift} is expected to reduce repeated errors and improve stability.`;\n}\n\nfunction recordHypothesis({\n signals,\n mutation,\n personality_state,\n selectedGene,\n selector,\n driftEnabled,\n selectedBy,\n capsulesUsed,\n observations,\n}) {\n const signalKey = computeSignalKey(signals);\n const geneId = selectedGene && selectedGene.id ? String(selectedGene.id) : null;\n const geneCategory = selectedGene && selectedGene.category ? String(selectedGene.category) : null;\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const hypothesisId = `hyp_${Date.now()}_${stableHash(`${signalKey}|${geneId || 'none'}|${ts}`)}`;\n const personalityState = personality_state || null;\n const mutNorm = mutation && isValidMutation(mutation) ? normalizeMutation(mutation) : null;\n const psNorm = personalityState && isValidPersonalityState(personalityState) ? normalizePersonalityState(personalityState) : null;\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'hypothesis',\n id: `mge_${Date.now()}_${stableHash(`${hypothesisId}|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [], error_signature: errsig || null },\n hypothesis: {\n id: hypothesisId,\n text: buildHypothesisText({ signalKey, signals, geneId, geneCategory, driftEnabled }),\n predicted_outcome: { status: null, score: null },\n },\n mutation: mutNorm\n ? {\n id: mutNorm.id,\n category: mutNorm.category,\n trigger_signals: mutNorm.trigger_signals,\n target: mutNorm.target,\n expected_effect: mutNorm.expected_effect,\n risk_level: mutNorm.risk_level,\n }\n : null,\n personality: psNorm\n ? {\n key: personalityKey(psNorm),\n state: psNorm,\n }\n : null,\n gene: { id: geneId, category: geneCategory },\n action: {\n drift: !!driftEnabled,\n selected_by: selectedBy || 'selector',\n selector: selector || null,\n },\n capsules: {\n used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n appendJsonl(memoryGraphPath(), ev);\n return { hypothesisId, signalKey };\n}\n\nfunction hasErrorSignal(signals) {\n const list = Array.isArray(signals) ? signals : [];\n return list.includes('log_error');\n}\n\nfunction recordAttempt({\n signals,\n mutation,\n personality_state,\n selectedGene,\n selector,\n driftEnabled,\n selectedBy,\n hypothesisId,\n capsulesUsed,\n observations,\n}) {\n const signalKey = computeSignalKey(signals);\n const geneId = selectedGene && selectedGene.id ? String(selectedGene.id) : null;\n const geneCategory = selectedGene && selectedGene.category ? String(selectedGene.category) : null;\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const actionId = `act_${Date.now()}_${stableHash(`${signalKey}|${geneId || 'none'}|${ts}`)}`;\n const personalityState = personality_state || null;\n const mutNorm = mutation && isValidMutation(mutation) ? normalizeMutation(mutation) : null;\n const psNorm = personalityState && isValidPersonalityState(personalityState) ? normalizePersonalityState(personalityState) : null;\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'attempt',\n id: `mge_${Date.now()}_${stableHash(actionId)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [], error_signature: errsig || null },\n mutation: mutNorm\n ? {\n id: mutNorm.id,\n category: mutNorm.category,\n trigger_signals: mutNorm.trigger_signals,\n target: mutNorm.target,\n expected_effect: mutNorm.expected_effect,\n risk_level: mutNorm.risk_level,\n }\n : null,\n personality: psNorm\n ? {\n key: personalityKey(psNorm),\n state: psNorm,\n }\n : null,\n gene: { id: geneId, category: geneCategory },\n hypothesis: hypothesisId ? { id: String(hypothesisId) } : null,\n action: {\n id: actionId,\n drift: !!driftEnabled,\n selected_by: selectedBy || 'selector',\n selector: selector || null,\n },\n capsules: {\n used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n };\n\n appendJsonl(memoryGraphPath(), ev);\n\n // State is mutable; graph is append-only.\n const statePath = memoryGraphStatePath();\n const state = readJsonIfExists(statePath, { last_action: null });\n state.last_action = {\n action_id: actionId,\n signal_key: signalKey,\n signals: Array.isArray(signals) ? signals : [],\n mutation_id: mutNorm ? mutNorm.id : null,\n mutation_category: mutNorm ? mutNorm.category : null,\n mutation_risk_level: mutNorm ? mutNorm.risk_level : null,\n personality_key: psNorm ? personalityKey(psNorm) : null,\n personality_state: psNorm || null,\n gene_id: geneId,\n gene_category: geneCategory,\n hypothesis_id: hypothesisId ? String(hypothesisId) : null,\n capsules_used: Array.isArray(capsulesUsed) ? capsulesUsed.map(String).filter(Boolean) : [],\n had_error: hasErrorSignal(signals),\n created_at: ts,\n outcome_recorded: false,\n baseline_observed: observations && typeof observations === 'object' ? observations : null,\n };\n writeJsonAtomic(statePath, state);\n\n return { actionId, signalKey };\n}\n\nfunction inferOutcomeFromSignals({ prevHadError, currentHasError }) {\n if (prevHadError && !currentHasError) return { status: 'success', score: 0.85, note: 'error_cleared' };\n if (prevHadError && currentHasError) return { status: 'failed', score: 0.2, note: 'error_persisted' };\n if (!prevHadError && currentHasError) return { status: 'failed', score: 0.15, note: 'new_error_appeared' };\n return { status: 'success', score: 0.6, note: 'stable_no_error' };\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction tryParseLastEvolutionEventOutcome(evidenceText) {\n // Scan tail text for an EvolutionEvent JSON line and extract its outcome.\n const s = String(evidenceText || '');\n if (!s) return null;\n const lines = s.split('\\n').slice(-400);\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim();\n if (!line) continue;\n if (!line.includes('\"type\"') || !line.includes('EvolutionEvent')) continue;\n try {\n const obj = JSON.parse(line);\n if (!obj || obj.type !== 'EvolutionEvent') continue;\n const o = obj.outcome && typeof obj.outcome === 'object' ? obj.outcome : null;\n if (!o) continue;\n const status = o.status === 'success' || o.status === 'failed' ? o.status : null;\n const score = Number.isFinite(Number(o.score)) ? clamp01(Number(o.score)) : null;\n if (!status && score == null) continue;\n return {\n status: status || (score != null && score >= 0.5 ? 'success' : 'failed'),\n score: score != null ? score : status === 'success' ? 0.75 : 0.25,\n note: 'evolutionevent_observed',\n };\n } catch (e) {\n continue;\n }\n }\n return null;\n}\n\nfunction inferOutcomeEnhanced({ prevHadError, currentHasError, baselineObserved, currentObserved }) {\n const evidence =\n currentObserved &&\n currentObserved.evidence &&\n (currentObserved.evidence.recent_session_tail || currentObserved.evidence.today_log_tail)\n ? currentObserved.evidence\n : null;\n const combinedEvidence = evidence\n ? `${String(evidence.recent_session_tail || '')}\\n${String(evidence.today_log_tail || '')}`\n : '';\n const observed = tryParseLastEvolutionEventOutcome(combinedEvidence);\n if (observed) return observed;\n\n const base = inferOutcomeFromSignals({ prevHadError, currentHasError });\n\n const prevErrCount =\n baselineObserved && Number.isFinite(Number(baselineObserved.recent_error_count))\n ? Number(baselineObserved.recent_error_count)\n : null;\n const curErrCount =\n currentObserved && Number.isFinite(Number(currentObserved.recent_error_count))\n ? Number(currentObserved.recent_error_count)\n : null;\n\n let score = base.score;\n if (prevErrCount != null && curErrCount != null) {\n const delta = prevErrCount - curErrCount;\n score += Math.max(-0.12, Math.min(0.12, delta / 50));\n }\n\n const prevScan =\n baselineObserved && Number.isFinite(Number(baselineObserved.scan_ms)) ? Number(baselineObserved.scan_ms) : null;\n const curScan =\n currentObserved && Number.isFinite(Number(currentObserved.scan_ms)) ? Number(currentObserved.scan_ms) : null;\n if (prevScan != null && curScan != null && prevScan > 0) {\n const ratio = (prevScan - curScan) / prevScan;\n score += Math.max(-0.06, Math.min(0.06, ratio));\n }\n\n return { status: base.status, score: clamp01(score), note: `${base.note}|heuristic_delta` };\n}\n\nfunction buildConfidenceEdgeEvent({ signalKey, signals, geneId, geneCategory, outcomeEventId, halfLifeDays }) {\n const events = tryReadMemoryGraphEvents(2000);\n const edges = aggregateEdges(events);\n const k = `${signalKey}::${geneId}`;\n const edge = edges.get(k) || { success: 0, fail: 0, last_ts: null };\n const ex = edgeExpectedSuccess(edge, { half_life_days: halfLifeDays });\n const ts = nowIso();\n return {\n type: 'MemoryGraphEvent',\n kind: 'confidence_edge',\n id: `mge_${Date.now()}_${stableHash(`${signalKey}|${geneId}|confidence|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [] },\n gene: { id: geneId, category: geneCategory || null },\n edge: { signal_key: signalKey, gene_id: geneId },\n stats: {\n success: Number(edge.success) || 0,\n fail: Number(edge.fail) || 0,\n attempts: Number(ex.total) || 0,\n p: ex.p,\n decay_weight: ex.w,\n value: ex.value,\n half_life_days: halfLifeDays,\n updated_at: ts,\n },\n derived_from: { outcome_event_id: outcomeEventId || null },\n };\n}\n\nfunction buildGeneOutcomeConfidenceEvent({ geneId, geneCategory, outcomeEventId, halfLifeDays }) {\n const events = tryReadMemoryGraphEvents(2000);\n const geneOutcomes = aggregateGeneOutcomes(events);\n const edge = geneOutcomes.get(String(geneId)) || { success: 0, fail: 0, last_ts: null };\n const ex = edgeExpectedSuccess(edge, { half_life_days: halfLifeDays });\n const ts = nowIso();\n return {\n type: 'MemoryGraphEvent',\n kind: 'confidence_gene_outcome',\n id: `mge_${Date.now()}_${stableHash(`${geneId}|gene_outcome|confidence|${ts}`)}`,\n ts,\n gene: { id: String(geneId), category: geneCategory || null },\n edge: { gene_id: String(geneId) },\n stats: {\n success: Number(edge.success) || 0,\n fail: Number(edge.fail) || 0,\n attempts: Number(ex.total) || 0,\n p: ex.p,\n decay_weight: ex.w,\n value: ex.value,\n half_life_days: halfLifeDays,\n updated_at: ts,\n },\n derived_from: { outcome_event_id: outcomeEventId || null },\n };\n}\n\nfunction recordOutcomeFromState({ signals, observations }) {\n const statePath = memoryGraphStatePath();\n const state = readJsonIfExists(statePath, { last_action: null });\n const last = state && state.last_action ? state.last_action : null;\n if (!last || !last.action_id) return null;\n if (last.outcome_recorded) return null;\n\n const currentHasError = hasErrorSignal(signals);\n const inferred = inferOutcomeEnhanced({\n prevHadError: !!last.had_error,\n currentHasError,\n baselineObserved: last.baseline_observed || null,\n currentObserved: observations || null,\n });\n const ts = nowIso();\n const errsig = extractErrorSignatureFromSignals(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'outcome',\n id: `mge_${Date.now()}_${stableHash(`${last.action_id}|outcome|${ts}`)}`,\n ts,\n signal: {\n key: String(last.signal_key || '(none)'),\n signals: Array.isArray(last.signals) ? last.signals : [],\n error_signature: errsig || null,\n },\n mutation:\n last.mutation_id || last.mutation_category || last.mutation_risk_level\n ? {\n id: last.mutation_id || null,\n category: last.mutation_category || null,\n risk_level: last.mutation_risk_level || null,\n }\n : null,\n personality:\n last.personality_key || last.personality_state\n ? {\n key: last.personality_key || null,\n state: last.personality_state || null,\n }\n : null,\n gene: { id: last.gene_id || null, category: last.gene_category || null },\n action: { id: String(last.action_id) },\n hypothesis: last.hypothesis_id ? { id: String(last.hypothesis_id) } : null,\n outcome: {\n status: inferred.status,\n score: inferred.score,\n note: inferred.note,\n observed: { current_signals: Array.isArray(signals) ? signals : [] },\n },\n confidence: {\n // This is an interpretable, decayed success estimate derived from outcomes; aggregation is computed at read-time.\n half_life_days: 30,\n },\n observed: observations && typeof observations === 'object' ? observations : null,\n baseline: last.baseline_observed || null,\n capsules: {\n used: Array.isArray(last.capsules_used) ? last.capsules_used : [],\n },\n };\n\n appendJsonl(memoryGraphPath(), ev);\n\n // Persist explicit confidence snapshots (append-only) for auditability.\n try {\n if (last.gene_id) {\n const edgeEv = buildConfidenceEdgeEvent({\n signalKey: String(last.signal_key || '(none)'),\n signals: Array.isArray(last.signals) ? last.signals : [],\n geneId: String(last.gene_id),\n geneCategory: last.gene_category || null,\n outcomeEventId: ev.id,\n halfLifeDays: 30,\n });\n appendJsonl(memoryGraphPath(), edgeEv);\n\n const geneEv = buildGeneOutcomeConfidenceEvent({\n geneId: String(last.gene_id),\n geneCategory: last.gene_category || null,\n outcomeEventId: ev.id,\n halfLifeDays: 45,\n });\n appendJsonl(memoryGraphPath(), geneEv);\n }\n } catch (e) {}\n\n last.outcome_recorded = true;\n last.outcome_recorded_at = ts;\n state.last_action = last;\n writeJsonAtomic(statePath, state);\n\n return ev;\n}\n\nfunction recordExternalCandidate({ asset, source, signals }) {\n // Append-only annotation: external assets enter as candidates only.\n // This does not affect outcome aggregation (which only uses kind === 'outcome').\n const a = asset && typeof asset === 'object' ? asset : null;\n const type = a && a.type ? String(a.type) : null;\n const id = a && a.id ? String(a.id) : null;\n if (!type || !id) return null;\n\n const ts = nowIso();\n const signalKey = computeSignalKey(signals);\n const ev = {\n type: 'MemoryGraphEvent',\n kind: 'external_candidate',\n id: `mge_${Date.now()}_${stableHash(`${type}|${id}|external|${ts}`)}`,\n ts,\n signal: { key: signalKey, signals: Array.isArray(signals) ? signals : [] },\n external: {\n source: source || 'external',\n received_at: ts,\n },\n asset: { type, id },\n candidate: {\n // Minimal hints for later local triggering/validation.\n trigger: type === 'Capsule' && Array.isArray(a.trigger) ? a.trigger : [],\n gene: type === 'Capsule' && a.gene ? String(a.gene) : null,\n confidence: type === 'Capsule' && Number.isFinite(Number(a.confidence)) ? Number(a.confidence) : null,\n },\n };\n\n appendJsonl(memoryGraphPath(), ev);\n return ev;\n}\n\nmodule.exports = {\n memoryGraphPath,\n computeSignalKey,\n tryReadMemoryGraphEvents,\n getMemoryAdvice,\n recordSignalSnapshot,\n recordHypothesis,\n recordAttempt,\n recordOutcomeFromState,\n recordExternalCandidate,\n};\n\n",
526 "inputSchema": {},
527 "outputSchema": null,
528 "icons": null,
529 "annotations": null,
530 "meta": null,
531 "execution": null
532 },
533 {
534 "name": "solidify.js",
535 "title": null,
536 "description": "Script: solidify.js. Code:\nconst fs = require('fs');\nconst path = require('path');\nconst { execSync } = require('child_process');\nconst { loadGenes, upsertGene, appendEventJsonl, appendCapsule, upsertCapsule, getLastEventId } = require('./assetStore');\nconst { computeSignalKey, memoryGraphPath } = require('./memoryGraph');\nconst { computeCapsuleSuccessStreak, isBlastRadiusSafe } = require('./a2a');\nconst { getRepoRoot, getMemoryDir, getEvolutionDir } = require('./paths');\nconst { extractSignals } = require('./signals');\nconst { selectGene } = require('./selector');\nconst { isValidMutation, normalizeMutation, isHighRiskMutationAllowed, isHighRiskPersonality } = require('./mutation');\nconst {\n isValidPersonalityState,\n normalizePersonalityState,\n personalityKey,\n updatePersonalityStats,\n} = require('./personality');\nconst { computeAssetId, SCHEMA_VERSION } = require('./contentHash');\nconst { captureEnvFingerprint } = require('./envFingerprint');\nconst { buildValidationReport } = require('./validationReport');\n\nfunction nowIso() {\n return new Date().toISOString();\n}\n\nfunction clamp01(x) {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(1, n));\n}\n\nfunction safeJsonParse(text, fallback) {\n try {\n return JSON.parse(text);\n } catch {\n return fallback;\n }\n}\n\nfunction readJsonIfExists(filePath, fallback) {\n try {\n if (!fs.existsSync(filePath)) return fallback;\n const raw = fs.readFileSync(filePath, 'utf8');\n if (!raw.trim()) return fallback;\n return JSON.parse(raw);\n } catch {\n return fallback;\n }\n}\n\nfunction stableHash(input) {\n const s = String(input || '');\n let h = 2166136261;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return (h >>> 0).toString(16).padStart(8, '0');\n}\n\nfunction runCmd(cmd, opts = {}) {\n const cwd = opts.cwd || getRepoRoot();\n const timeoutMs = Number.isFinite(Number(opts.timeoutMs)) ? Number(opts.timeoutMs) : 120000;\n return execSync(cmd, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: timeoutMs });\n}\n\nfunction tryRunCmd(cmd, opts = {}) {\n try {\n return { ok: true, out: runCmd(cmd, opts), err: '' };\n } catch (e) {\n const stderr = e && e.stderr ? String(e.stderr) : '';\n const stdout = e && e.stdout ? String(e.stdout) : '';\n const msg = e && e.message ? String(e.message) : 'command_failed';\n return { ok: false, out: stdout, err: stderr || msg };\n }\n}\n\nfunction gitListChangedFiles({ repoRoot }) {\n const files = new Set();\n const s1 = tryRunCmd('git diff --name-only', { cwd: repoRoot, timeoutMs: 60000 });\n if (s1.ok) for (const line of String(s1.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n const s2 = tryRunCmd('git diff --cached --name-only', { cwd: repoRoot, timeoutMs: 60000 });\n if (s2.ok) for (const line of String(s2.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n const s3 = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n if (s3.ok) for (const line of String(s3.out).split('\\n').map(l => l.trim()).filter(Boolean)) files.add(line);\n return Array.from(files);\n}\n\nfunction parseNumstat(text) {\n const lines = String(text || '').split('\\n').map(l => l.trim()).filter(Boolean);\n let added = 0;\n let deleted = 0;\n for (const line of lines) {\n const parts = line.split('\\t');\n if (parts.length < 3) continue;\n const a = Number(parts[0]);\n const d = Number(parts[1]);\n if (Number.isFinite(a)) added += a;\n if (Number.isFinite(d)) deleted += d;\n }\n return { added, deleted };\n}\n\nfunction countFileLines(absPath) {\n try {\n if (!fs.existsSync(absPath)) return 0;\n const buf = fs.readFileSync(absPath);\n if (!buf || buf.length === 0) return 0;\n let n = 1;\n for (let i = 0; i < buf.length; i++) if (buf[i] === 10) n++;\n return n;\n } catch {\n return 0;\n }\n}\n\nfunction computeBlastRadius({ repoRoot, baselineUntracked }) {\n let changedFiles = gitListChangedFiles({ repoRoot });\n if (Array.isArray(baselineUntracked) && baselineUntracked.length > 0) {\n const baselineSet = new Set(baselineUntracked);\n changedFiles = changedFiles.filter(f => !baselineSet.has(f));\n }\n const filesCount = changedFiles.length;\n const u = tryRunCmd('git diff --numstat', { cwd: repoRoot, timeoutMs: 60000 });\n const c = tryRunCmd('git diff --cached --numstat', { cwd: repoRoot, timeoutMs: 60000 });\n const unstaged = u.ok ? parseNumstat(u.out) : { added: 0, deleted: 0 };\n const staged = c.ok ? parseNumstat(c.out) : { added: 0, deleted: 0 };\n const untracked = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n let untrackedLines = 0;\n if (untracked.ok) {\n const rels = String(untracked.out).split('\\n').map(l => l.trim()).filter(Boolean);\n const baselineSet = new Set(Array.isArray(baselineUntracked) ? baselineUntracked : []);\n for (const rel of rels) {\n if (baselineSet.has(rel)) continue;\n const abs = path.join(repoRoot, rel);\n untrackedLines += countFileLines(abs);\n }\n }\n const churn = unstaged.added + unstaged.deleted + staged.added + staged.deleted + untrackedLines;\n return { files: filesCount, lines: churn, changed_files: changedFiles };\n}\n\nfunction isForbiddenPath(relPath, forbiddenPaths) {\n const rel = String(relPath || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '');\n const list = Array.isArray(forbiddenPaths) ? forbiddenPaths : [];\n for (const fp of list) {\n const f = String(fp || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '').replace(/\\/+$/, '');\n if (!f) continue;\n if (rel === f) return true;\n if (rel.startsWith(f + '/')) return true;\n }\n return false;\n}\n\nfunction checkConstraints({ gene, blast }) {\n const violations = [];\n if (!gene || gene.type !== 'Gene') return { ok: true, violations };\n const constraints = gene.constraints || {};\n const maxFiles = Number(constraints.max_files);\n if (Number.isFinite(maxFiles) && maxFiles > 0) {\n if (Number(blast.files) > maxFiles) violations.push(`max_files exceeded: ${blast.files} > ${maxFiles}`);\n }\n const forbidden = Array.isArray(constraints.forbidden_paths) ? constraints.forbidden_paths : [];\n for (const f of blast.changed_files || []) {\n if (isForbiddenPath(f, forbidden)) violations.push(`forbidden_path touched: ${f}`);\n }\n return { ok: violations.length === 0, violations };\n}\n\nfunction readStateForSolidify() {\n const memoryDir = getMemoryDir();\n const statePath = path.join(getEvolutionDir(), 'evolution_solidify_state.json');\n return readJsonIfExists(statePath, { last_run: null });\n}\n\nfunction writeStateForSolidify(state) {\n const memoryDir = getMemoryDir();\n const statePath = path.join(getEvolutionDir(), 'evolution_solidify_state.json');\n try {\n if (!fs.existsSync(memoryDir)) fs.mkdirSync(memoryDir, { recursive: true });\n } catch {}\n const tmp = `${statePath}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(state, null, 2) + '\\n', 'utf8');\n fs.renameSync(tmp, statePath);\n}\n\nfunction buildEventId(tsIso) {\n const t = Date.parse(tsIso);\n return `evt_${Number.isFinite(t) ? t : Date.now()}`;\n}\n\nfunction buildCapsuleId(tsIso) {\n const t = Date.parse(tsIso);\n return `capsule_${Number.isFinite(t) ? t : Date.now()}`;\n}\n\n// --- Validation command safety ---\nconst VALIDATION_ALLOWED_PREFIXES = ['node ', 'npm ', 'npx '];\n\nfunction isValidationCommandAllowed(cmd) {\n const c = String(cmd || '').trim();\n if (!c) return false;\n if (!VALIDATION_ALLOWED_PREFIXES.some(p => c.startsWith(p))) return false;\n if (/`|\\$\\(/.test(c)) return false;\n const stripped = c.replace(/\"[^\"]*\"/g, '').replace(/'[^']*'/g, '');\n if (/[;&|><]/.test(stripped)) return false;\n return true;\n}\n\nfunction runValidations(gene, opts = {}) {\n const repoRoot = opts.repoRoot || getRepoRoot();\n const timeoutMs = Number.isFinite(Number(opts.timeoutMs)) ? Number(opts.timeoutMs) : 180000;\n const validation = Array.isArray(gene && gene.validation) ? gene.validation : [];\n const results = [];\n const startedAt = Date.now();\n for (const cmd of validation) {\n const c = String(cmd || '').trim();\n if (!c) continue;\n if (!isValidationCommandAllowed(c)) {\n results.push({ cmd: c, ok: false, out: '', err: 'BLOCKED: validation command rejected by safety check (allowed prefixes: node/npm/npx; shell operators prohibited)' });\n return { ok: false, results, startedAt, finishedAt: Date.now() };\n }\n const r = tryRunCmd(c, { cwd: repoRoot, timeoutMs });\n results.push({ cmd: c, ok: r.ok, out: String(r.out || ''), err: String(r.err || '') });\n if (!r.ok) return { ok: false, results, startedAt, finishedAt: Date.now() };\n }\n return { ok: true, results, startedAt, finishedAt: Date.now() };\n}\n\nfunction rollbackTracked(repoRoot) {\n tryRunCmd('git restore --staged --worktree .', { cwd: repoRoot, timeoutMs: 60000 });\n tryRunCmd('git reset --hard', { cwd: repoRoot, timeoutMs: 60000 });\n}\n\nfunction gitListUntrackedFiles(repoRoot) {\n const r = tryRunCmd('git ls-files --others --exclude-standard', { cwd: repoRoot, timeoutMs: 60000 });\n if (!r.ok) return [];\n return String(r.out).split('\\n').map(l => l.trim()).filter(Boolean);\n}\n\nfunction rollbackNewUntrackedFiles({ repoRoot, baselineUntracked }) {\n const baseline = new Set((Array.isArray(baselineUntracked) ? baselineUntracked : []).map(String));\n const current = gitListUntrackedFiles(repoRoot);\n const toDelete = current.filter(f => !baseline.has(String(f)));\n for (const rel of toDelete) {\n const safeRel = String(rel || '').replace(/\\\\/g, '/').replace(/^\\.\\/+/, '');\n if (!safeRel) continue;\n const abs = path.join(repoRoot, safeRel);\n const normRepo = path.resolve(repoRoot);\n const normAbs = path.resolve(abs);\n if (!normAbs.startsWith(normRepo + path.sep) && normAbs !== normRepo) continue;\n try {\n if (fs.existsSync(normAbs) && fs.statSync(normAbs).isFile()) fs.unlinkSync(normAbs);\n } catch (e) {}\n }\n return { deleted: toDelete };\n}\n\nfunction inferCategoryFromSignals(signals) {\n const list = Array.isArray(signals) ? signals.map(String) : [];\n if (list.includes('log_error')) return 'repair';\n if (list.includes('protocol_drift')) return 'optimize';\n return 'optimize';\n}\n\nfunction buildAutoGene({ signals, intent }) {\n const sigs = Array.isArray(signals) ? Array.from(new Set(signals.map(String))).filter(Boolean) : [];\n const signalKey = computeSignalKey(sigs);\n const id = `gene_auto_${stableHash(signalKey)}`;\n const category = intent && ['repair', 'optimize', 'innovate'].includes(String(intent))\n ? String(intent)\n : inferCategoryFromSignals(sigs);\n const signalsMatch = sigs.length ? sigs.slice(0, 8) : ['(none)'];\n const gene = {\n type: 'Gene',\n schema_version: SCHEMA_VERSION,\n id,\n category,\n signals_match: signalsMatch,\n preconditions: [`signals_key == ${signalKey}`],\n strategy: [\n 'Extract structured signals from logs and user instructions',\n 'Select an existing Gene by signals match (no improvisation)',\n 'Estimate blast radius (files, lines) before editing and record it',\n 'Apply smallest reversible patch',\n 'Validate using declared validation steps; rollback on failure',\n 'Solidify knowledge: append EvolutionEvent, update Gene/Capsule store',\n ],\n constraints: { max_files: 12, forbidden_paths: ['.git', 'node_modules'] },\n validation: ['node -e \"require(\\'./src/gep/solidify\\'); console.log(\\'ok\\')\"'],\n };\n gene.asset_id = computeAssetId(gene);\n return gene;\n}\n\nfunction ensureGene({ genes, selectedGene, signals, intent, dryRun }) {\n if (selectedGene && selectedGene.type === 'Gene') return { gene: selectedGene, created: false, reason: 'selected_gene_id_present' };\n const res = selectGene(Array.isArray(genes) ? genes : [], Array.isArray(signals) ? signals : [], {\n bannedGeneIds: new Set(), preferredGeneId: null, driftEnabled: false,\n });\n if (res && res.selected) return { gene: res.selected, created: false, reason: 'reselected_from_existing' };\n const auto = buildAutoGene({ signals, intent });\n if (!dryRun) upsertGene(auto);\n return { gene: auto, created: true, reason: 'no_match_create_new' };\n}\n\nfunction readRecentSessionInputs() {\n const repoRoot = getRepoRoot();\n const memoryDir = getMemoryDir();\n const rootMemory = path.join(repoRoot, 'MEMORY.md');\n const dirMemory = path.join(memoryDir, 'MEMORY.md');\n const memoryFile = fs.existsSync(rootMemory) ? rootMemory : dirMemory;\n const userFile = path.join(repoRoot, 'USER.md');\n const todayLog = path.join(memoryDir, new Date().toISOString().split('T')[0] + '.md');\n const todayLogContent = fs.existsSync(todayLog) ? fs.readFileSync(todayLog, 'utf8') : '';\n const memorySnippet = fs.existsSync(memoryFile) ? fs.readFileSync(memoryFile, 'utf8').slice(0, 50000) : '';\n const userSnippet = fs.existsSync(userFile) ? fs.readFileSync(userFile, 'utf8') : '';\n const recentSessionTranscript = '';\n return { recentSessionTranscript, todayLog: todayLogContent, memorySnippet, userSnippet };\n}\n\nfunction solidify({ intent, summary, dryRun = false, rollbackOnFailure = true } = {}) {\n const repoRoot = getRepoRoot();\n const state = readStateForSolidify();\n const lastRun = state && state.last_run ? state.last_run : null;\n const genes = loadGenes();\n const geneId = lastRun && lastRun.selected_gene_id ? String(lastRun.selected_gene_id) : null;\n const selectedGene = geneId ? genes.find(g => g && g.type === 'Gene' && g.id === geneId) : null;\n const parentEventId =\n lastRun && typeof lastRun.parent_event_id === 'string' ? lastRun.parent_event_id : getLastEventId();\n const signals =\n lastRun && Array.isArray(lastRun.signals) && lastRun.signals.length\n ? Array.from(new Set(lastRun.signals.map(String)))\n : extractSignals(readRecentSessionInputs());\n const signalKey = computeSignalKey(signals);\n\n const mutationRaw = lastRun && lastRun.mutation && typeof lastRun.mutation === 'object' ? lastRun.mutation : null;\n const personalityRaw =\n lastRun && lastRun.personality_state && typeof lastRun.personality_state === 'object' ? lastRun.personality_state : null;\n const mutation = mutationRaw && isValidMutation(mutationRaw) ? normalizeMutation(mutationRaw) : null;\n const personalityState =\n personalityRaw && isValidPersonalityState(personalityRaw) ? normalizePersonalityState(personalityRaw) : null;\n const personalityKeyUsed = personalityState ? personalityKey(personalityState) : null;\n const protocolViolations = [];\n if (!mutation) protocolViolations.push('missing_or_invalid_mutation');\n if (!personalityState) protocolViolations.push('missing_or_invalid_personality_state');\n if (mutation && mutation.risk_level === 'high' && !isHighRiskMutationAllowed(personalityState || null)) {\n protocolViolations.push('high_risk_mutation_not_allowed_by_personality');\n }\n if (mutation && mutation.risk_level === 'high' && !(lastRun && lastRun.personality_known)) {\n protocolViolations.push('high_risk_mutation_forbidden_under_unknown_personality');\n }\n if (mutation && mutation.category === 'innovate' && personalityState && isHighRiskPersonality(personalityState)) {\n protocolViolations.push('forbidden_innovate_with_high_risk_personality');\n }\n\n const ensured = ensureGene({ genes, selectedGene, signals, intent, dryRun: !!dryRun });\n const geneUsed = ensured.gene;\n const blast = computeBlastRadius({\n repoRoot,\n baselineUntracked: lastRun && Array.isArray(lastRun.baseline_untracked) ? lastRun.baseline_untracked : [],\n });\n const constraintCheck = checkConstraints({ gene: geneUsed, blast });\n\n // Capture environment fingerprint before validation.\n const envFp = captureEnvFingerprint();\n\n let validation = { ok: true, results: [], startedAt: null, finishedAt: null };\n if (geneUsed) {\n validation = runValidations(geneUsed, { repoRoot, timeoutMs: 180000 });\n }\n\n // Build standardized ValidationReport (machine-readable, interoperable).\n const validationReport = buildValidationReport({\n geneId: geneUsed && geneUsed.id ? geneUsed.id : null,\n commands: validation.results.map(function (r) { return r.cmd; }),\n results: validation.results,\n envFp: envFp,\n startedAt: validation.startedAt,\n finishedAt: validation.finishedAt,\n });\n\n const success = constraintCheck.ok && validation.ok && protocolViolations.length === 0;\n const ts = nowIso();\n const outcomeStatus = success ? 'success' : 'failed';\n const score = clamp01(success ? 0.85 : 0.2);\n\n const selectedCapsuleId =\n lastRun && typeof lastRun.selected_capsule_id === 'string' && lastRun.selected_capsule_id.trim()\n ? String(lastRun.selected_capsule_id).trim() : null;\n const capsuleId = success ? selectedCapsuleId || buildCapsuleId(ts) : null;\n const derivedIntent = intent || (mutation && mutation.category) || (geneUsed && geneUsed.category) || 'repair';\n const intentMismatch =\n intent && mutation && typeof mutation.category === 'string' && String(intent) !== String(mutation.category);\n if (intentMismatch) protocolViolations.push(`intent_mismatch_with_mutation:${String(intent)}!=${String(mutation.category)}`);\n\n const event = {\n type: 'EvolutionEvent',\n schema_version: SCHEMA_VERSION,\n id: buildEventId(ts),\n parent: parentEventId || null,\n intent: derivedIntent,\n signals,\n genes_used: geneUsed && geneUsed.id ? [geneUsed.id] : [],\n mutation_id: mutation && mutation.id ? mutation.id : null,\n personality_state: personalityState || null,\n blast_radius: { files: blast.files, lines: blast.lines },\n outcome: { status: outcomeStatus, score },\n capsule_id: capsuleId,\n env_fingerprint: envFp,\n validation_report_id: validationReport.id,\n meta: {\n at: ts,\n signal_key: signalKey,\n selector: lastRun && lastRun.selector ? lastRun.selector : null,\n blast_radius_estimate: lastRun && lastRun.blast_radius_estimate ? lastRun.blast_radius_estimate : null,\n mutation: mutation || null,\n personality: {\n key: personalityKeyUsed,\n known: !!(lastRun && lastRun.personality_known),\n mutations: lastRun && Array.isArray(lastRun.personality_mutations) ? lastRun.personality_mutations : [],\n },\n gene: {\n id: geneUsed && geneUsed.id ? geneUsed.id : null,\n created: !!ensured.created,\n reason: ensured.reason,\n },\n constraints_ok: constraintCheck.ok,\n constraint_violations: constraintCheck.violations,\n validation_ok: validation.ok,\n validation: validation.results.map(r => ({ cmd: r.cmd, ok: r.ok })),\n validation_report: validationReport,\n protocol_ok: protocolViolations.length === 0,\n protocol_violations: protocolViolations,\n memory_graph: memoryGraphPath(),\n },\n };\n event.asset_id = computeAssetId(event);\n\n let capsule = null;\n if (success) {\n const s = String(summary || '').trim();\n const autoSummary = geneUsed\n ? `\u56fa\u5316\uff1a${geneUsed.id} \u547d\u4e2d\u4fe1\u53f7 ${signals.join(', ') || '(none)'}\uff0c\u53d8\u66f4 ${blast.files} \u6587\u4ef6 / ${blast.lines} \u884c\u3002`\n : `\u56fa\u5316\uff1a\u547d\u4e2d\u4fe1\u53f7 ${signals.join(', ') || '(none)'}\uff0c\u53d8\u66f4 ${blast.files} \u6587\u4ef6 / ${blast.lines} \u884c\u3002`;\n let prevCapsule = null;\n try {\n if (selectedCapsuleId) {\n const list = require('./assetStore').loadCapsules();\n prevCapsule = Array.isArray(list) ? list.find(c => c && c.type === 'Capsule' && String(c.id) === selectedCapsuleId) : null;\n }\n } catch (e) {}\n capsule = {\n type: 'Capsule',\n schema_version: SCHEMA_VERSION,\n id: capsuleId,\n trigger: prevCapsule && Array.isArray(prevCapsule.trigger) && prevCapsule.trigger.length ? prevCapsule.trigger : signals,\n gene: geneUsed && geneUsed.id ? geneUsed.id : prevCapsule && prevCapsule.gene ? prevCapsule.gene : null,\n summary: s || (prevCapsule && prevCapsule.summary ? String(prevCapsule.summary) : autoSummary),\n confidence: clamp01(score),\n blast_radius: { files: blast.files, lines: blast.lines },\n outcome: { status: 'success', score },\n success_streak: 1,\n env_fingerprint: envFp,\n metadata: {\n author: process.env.A2A_NODE_ID || process.env.AGENT_NAME || 'unknown',\n tags: signals.slice(0, 5),\n created_at: ts,\n },\n performance_metrics: {\n reuse_potential: prevCapsule ? 'high' : 'medium',\n blast_efficiency: blast.files > 0 ? Math.round((blast.lines / blast.files) * 10) / 10 : 0,\n },\n a2a: { eligible_to_broadcast: false },\n };\n capsule.asset_id = computeAssetId(capsule);\n }\n\n // Bug fix: dry-run must NOT trigger rollback (it should only observe, not mutate).\n if (!dryRun && !success && rollbackOnFailure) {\n rollbackTracked(repoRoot);\n rollbackNewUntrackedFiles({ repoRoot, baselineUntracked: lastRun && lastRun.baseline_untracked ? lastRun.baseline_untracked : [] });\n }\n\n if (!dryRun) {\n appendEventJsonl(validationReport);\n if (capsule) upsertCapsule(capsule);\n appendEventJsonl(event);\n if (capsule) {\n const streak = computeCapsuleSuccessStreak({ capsuleId: capsule.id });\n capsule.success_streak = streak || 1;\n capsule.a2a = {\n eligible_to_broadcast:\n isBlastRadiusSafe(capsule.blast_radius) &&\n (capsule.outcome.score || 0) >= 0.7 &&\n (capsule.success_streak || 0) >= 2,\n };\n capsule.asset_id = computeAssetId(capsule);\n upsertCapsule(capsule);\n }\n try {\n if (personalityState) {\n updatePersonalityStats({ personalityState, outcome: outcomeStatus, score, notes: `event:${event.id}` });\n }\n } catch (e) {}\n }\n\n const runId = lastRun && lastRun.run_id ? String(lastRun.run_id) : stableHash(`${parentEventId || 'root'}|${geneId || 'none'}|${signalKey}`);\n state.last_solidify = {\n run_id: runId, at: ts, event_id: event.id, capsule_id: capsuleId, outcome: event.outcome,\n };\n if (!dryRun) writeStateForSolidify(state);\n\n return { ok: success, event, capsule, gene: geneUsed, constraintCheck, validation, validationReport, blast };\n}\n\nmodule.exports = {\n solidify,\n readStateForSolidify,\n writeStateForSolidify,\n isValidationCommandAllowed,\n};\n",
537 "inputSchema": {},
538 "outputSchema": null,
539 "icons": null,
540 "annotations": null,
541 "meta": null,
542 "execution": null
543 },
544 {
545 "name": "index.js",
546 "title": null,
547 "description": "Script: index.js. Code:\nconst evolve = require('./src/evolve');\nconst { solidify } = require('./src/gep/solidify');\nconst path = require('path');\nconst fs = require('fs');\nconst { spawn } = require('child_process');\n\nfunction sleepMs(ms) {\n const n = parseInt(String(ms), 10);\n const t = Number.isFinite(n) ? Math.max(0, n) : 0;\n return new Promise(resolve => setTimeout(resolve, t));\n}\n\nfunction readJsonSafe(p) {\n try {\n if (!fs.existsSync(p)) return null;\n const raw = fs.readFileSync(p, 'utf8');\n if (!raw.trim()) return null;\n return JSON.parse(raw);\n } catch (e) {\n return null;\n }\n}\n\nfunction isPendingSolidify(state) {\n const lastRun = state && state.last_run ? state.last_run : null;\n const lastSolid = state && state.last_solidify ? state.last_solidify : null;\n if (!lastRun || !lastRun.run_id) return false;\n if (!lastSolid || !lastSolid.run_id) return true;\n return String(lastSolid.run_id) !== String(lastRun.run_id);\n}\n\nfunction parseMs(v, fallback) {\n const n = parseInt(String(v == null ? '' : v), 10);\n if (Number.isFinite(n)) return Math.max(0, n);\n return fallback;\n}\n\n// Singleton Guard - prevent multiple evolver daemon instances\nfunction acquireLock() {\n const lockFile = path.join(__dirname, 'evolver.pid');\n try {\n if (fs.existsSync(lockFile)) {\n const pid = parseInt(fs.readFileSync(lockFile, 'utf8').trim(), 10);\n try {\n process.kill(pid, 0); // Check if process exists\n console.log(`[Singleton] Evolver loop already running (PID ${pid}). Exiting.`);\n return false;\n } catch (e) {\n console.log(`[Singleton] Stale lock found (PID ${pid}). Taking over.`);\n }\n }\n fs.writeFileSync(lockFile, String(process.pid));\n return true;\n } catch (err) {\n console.error('[Singleton] Lock acquisition failed:', err);\n return false;\n }\n}\n\nfunction releaseLock() {\n const lockFile = path.join(__dirname, 'evolver.pid');\n try {\n if (fs.existsSync(lockFile)) {\n const pid = parseInt(fs.readFileSync(lockFile, 'utf8').trim(), 10);\n if (pid === process.pid) fs.unlinkSync(lockFile);\n }\n } catch (e) { /* ignore */ }\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n const command = args[0];\n const isLoop = args.includes('--loop') || args.includes('--mad-dog');\n\n if (command === 'run' || command === '/evolve' || isLoop) {\n console.log('Starting capability evolver...');\n \n if (isLoop) {\n // Internal daemon loop (no wrapper required).\n if (!acquireLock()) process.exit(0);\n process.on('exit', releaseLock);\n process.on('SIGINT', () => { releaseLock(); process.exit(); });\n process.on('SIGTERM', () => { releaseLock(); process.exit(); });\n\n process.env.EVOLVE_LOOP = 'true';\n process.env.EVOLVE_BRIDGE = 'false';\n console.log('Loop mode enabled (internal daemon).');\n\n const solidifyStatePath = path.join(__dirname, 'memory', 'evolution_solidify_state.json');\n\n const minSleepMs = parseMs(process.env.EVOLVER_MIN_SLEEP_MS, 2000);\n const maxSleepMs = parseMs(process.env.EVOLVER_MAX_SLEEP_MS, 300000);\n const idleThresholdMs = parseMs(process.env.EVOLVER_IDLE_THRESHOLD_MS, 500);\n const pendingSleepMs = parseMs(\n process.env.EVOLVE_PENDING_SLEEP_MS ||\n process.env.EVOLVE_MIN_INTERVAL ||\n process.env.FEISHU_EVOLVER_INTERVAL,\n 120000\n );\n\n const maxCyclesPerProcess = parseMs(process.env.EVOLVER_MAX_CYCLES_PER_PROCESS, 100) || 100;\n const maxRssMb = parseMs(process.env.EVOLVER_MAX_RSS_MB, 500) || 500;\n const suicideEnabled = String(process.env.EVOLVER_SUICIDE || '').toLowerCase() !== 'false';\n\n let currentSleepMs = Math.min(maxSleepMs, Math.max(minSleepMs, minSleepMs));\n let cycleCount = 0;\n\n while (true) {\n cycleCount += 1;\n\n // Ralph-loop gating: do not run a new cycle while previous run is pending solidify.\n const st0 = readJsonSafe(solidifyStatePath);\n if (isPendingSolidify(st0)) {\n await sleepMs(Math.max(pendingSleepMs, minSleepMs));\n continue;\n }\n\n const t0 = Date.now();\n let ok = false;\n try {\n await evolve.run();\n ok = true;\n } catch (error) {\n const msg = error && error.message ? String(error.message) : String(error);\n console.error(`Evolution cycle failed: ${msg}`);\n }\n const dt = Date.now() - t0;\n\n // Adaptive sleep: treat very fast cycles as \"idle\", backoff; otherwise reset to min.\n if (!ok || dt < idleThresholdMs) {\n currentSleepMs = Math.min(maxSleepMs, Math.max(minSleepMs, currentSleepMs * 2));\n } else {\n currentSleepMs = minSleepMs;\n }\n\n // Suicide check (memory leak protection)\n if (suicideEnabled) {\n const memMb = process.memoryUsage().rss / 1024 / 1024;\n if (cycleCount >= maxCyclesPerProcess || memMb > maxRssMb) {\n console.log(`[Daemon] Restarting self (cycles=${cycleCount}, rssMb=${memMb.toFixed(0)})`);\n releaseLock(); // Release before spawning to allow child to acquire\n const child = spawn(process.execPath, [__filename, ...args], {\n detached: true,\n stdio: 'ignore',\n env: process.env,\n });\n child.unref();\n process.exit(0);\n }\n }\n\n // Jitter to avoid lockstep restarts.\n const jitter = Math.floor(Math.random() * 250);\n await sleepMs(currentSleepMs + jitter);\n }\n } else {\n // Normal Single Run\n try {\n await evolve.run();\n } catch (error) {\n console.error('Evolution failed:', error);\n process.exit(1);\n }\n }\n\n // Post-run hint\n console.log('\\n' + '=======================================================');\n console.log('Capability evolver finished. If you use this project, consider starring the upstream repository.');\n console.log('Upstream: https://github.com/autogame-17/capability-evolver');\n console.log('=======================================================\\n');\n \n } else if (command === 'solidify') {\n const dryRun = args.includes('--dry-run');\n const noRollback = args.includes('--no-rollback');\n const intentFlag = args.find(a => typeof a === 'string' && a.startsWith('--intent='));\n const summaryFlag = args.find(a => typeof a === 'string' && a.startsWith('--summary='));\n const intent = intentFlag ? intentFlag.slice('--intent='.length) : null;\n const summary = summaryFlag ? summaryFlag.slice('--summary='.length) : null;\n\n try {\n const res = solidify({\n intent: intent || undefined,\n summary: summary || undefined,\n dryRun,\n rollbackOnFailure: !noRollback,\n });\n const st = res && res.ok ? 'SUCCESS' : 'FAILED';\n console.log(`[SOLIDIFY] ${st}`);\n if (res && res.gene) console.log(JSON.stringify(res.gene, null, 2));\n if (res && res.event) console.log(JSON.stringify(res.event, null, 2));\n if (res && res.capsule) console.log(JSON.stringify(res.capsule, null, 2));\n process.exit(res && res.ok ? 0 : 2);\n } catch (error) {\n console.error('[SOLIDIFY] Error:', error);\n process.exit(2);\n }\n } else {\n console.log(`Usage: node index.js [run|/evolve|solidify] [--loop]\n - solidify flags:\n - --dry-run\n - --no-rollback\n - --intent=repair|optimize|innovate\n - --summary=...`);\n }\n}\n\nif (require.main === module) {\n main();\n}\n",
548 "inputSchema": {},
549 "outputSchema": null,
550 "icons": null,
551 "annotations": null,
552 "meta": null,
553 "execution": null
554 }
555 ]
556 },
557 "error": null
558 }
559 ],
560 "issues": [
561 {
562 "code": "W004",
563 "message": "The MCP server is not in our registry.",
564 "reference": [
565 0,
566 null
567 ],
568 "extra_data": null
569 },
570 {
571 "code": "W011",
572 "message": "Third-party content exposure detected (high risk: 0.90). The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.",
573 "reference": [
574 0,
575 null
576 ],
577 "extra_data": {
578 "risk_score": 0.9,
579 "reason": "The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.",
580 "thought_process": "<reason>The repo explicitly ingests and stages external, potentially untrusted A2A assets via scripts/a2a_ingest.js (stdin/arbitrary input) and then the evolver (evolve.js) reads and matches recent external Gene/Capsule candidates as part of its selection/preview workflow, exposing the agent to third\u2011party user-generated content that it will interpret.</reason>\n<answer>0.9</answer>",
581 "severity": "high"
582 }
583 },
584 {
585 "code": "W008",
586 "message": "Attempt to compromise machine state in skill instructions detected (high risk: 0.70). This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.",
587 "reference": [
588 0,
589 null
590 ],
591 "extra_data": {
592 "risk_score": 0.7,
593 "reason": "This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.",
594 "thought_process": "<reason>This skill autonomously scans runtime memory and history, writes and applies code patches, and recommends running continuously (cron/loop), which lets it read potentially sensitive local files and persistently modify the machine's state even though it does not explicitly request sudo or create users.</reason>\n<answer>0.7</answer>",
595 "severity": "high"
596 }
597 }
598 ],
599 "labels": [
600 [
601 {
602 "is_public_sink": 0,
603 "destructive": 0,
604 "untrusted_content": 0,
605 "private_data": 0
606 },
607 {
608 "is_public_sink": 0,
609 "destructive": 0,
610 "untrusted_content": 0,
611 "private_data": 0
612 },
613 {
614 "is_public_sink": 0,
615 "destructive": 0,
616 "untrusted_content": 0,
617 "private_data": 0
618 },
619 {
620 "is_public_sink": 0,
621 "destructive": 0,
622 "untrusted_content": 0,
623 "private_data": 0
624 },
625 {
626 "is_public_sink": 0,
627 "destructive": 0,
628 "untrusted_content": 0,
629 "private_data": 0
630 },
631 {
632 "is_public_sink": 0,
633 "destructive": 0,
634 "untrusted_content": 0,
635 "private_data": 0
636 },
637 {
638 "is_public_sink": 0,
639 "destructive": 0,
640 "untrusted_content": 0,
641 "private_data": 0
642 },
643 {
644 "is_public_sink": 0,
645 "destructive": 0,
646 "untrusted_content": 0,
647 "private_data": 0
648 },
649 {
650 "is_public_sink": 0,
651 "destructive": 0,
652 "untrusted_content": 0,
653 "private_data": 0
654 },
655 {
656 "is_public_sink": 0,
657 "destructive": 0,
658 "untrusted_content": 0,
659 "private_data": 0
660 },
661 {
662 "is_public_sink": 0,
663 "destructive": 0,
664 "untrusted_content": 0,
665 "private_data": 0
666 },
667 {
668 "is_public_sink": 0,
669 "destructive": 0,
670 "untrusted_content": 0,
671 "private_data": 0
672 },
673 {
674 "is_public_sink": 0,
675 "destructive": 0,
676 "untrusted_content": 0,
677 "private_data": 0
678 },
679 {
680 "is_public_sink": 0,
681 "destructive": 0,
682 "untrusted_content": 0,
683 "private_data": 0
684 },
685 {
686 "is_public_sink": 0,
687 "destructive": 0,
688 "untrusted_content": 0,
689 "private_data": 0
690 },
691 {
692 "is_public_sink": 0,
693 "destructive": 0,
694 "untrusted_content": 0,
695 "private_data": 0
696 },
697 {
698 "is_public_sink": 0,
699 "destructive": 0,
700 "untrusted_content": 0,
701 "private_data": 0
702 },
703 {
704 "is_public_sink": 0,
705 "destructive": 0,
706 "untrusted_content": 0,
707 "private_data": 0
708 },
709 {
710 "is_public_sink": 0,
711 "destructive": 0,
712 "untrusted_content": 0,
713 "private_data": 0
714 },
715 {
716 "is_public_sink": 0,
717 "destructive": 0,
718 "untrusted_content": 0,
719 "private_data": 0
720 },
721 {
722 "is_public_sink": 0,
723 "destructive": 0,
724 "untrusted_content": 0,
725 "private_data": 0
726 },
727 {
728 "is_public_sink": 0,
729 "destructive": 0,
730 "untrusted_content": 0,
731 "private_data": 0
732 },
733 {
734 "is_public_sink": 0,
735 "destructive": 0,
736 "untrusted_content": 0,
737 "private_data": 0
738 },
739 {
740 "is_public_sink": 0,
741 "destructive": 0,
742 "untrusted_content": 0,
743 "private_data": 0
744 },
745 {
746 "is_public_sink": 0,
747 "destructive": 0,
748 "untrusted_content": 0,
749 "private_data": 0
750 },
751 {
752 "is_public_sink": 0,
753 "destructive": 0,
754 "untrusted_content": 0,
755 "private_data": 0
756 },
757 {
758 "is_public_sink": 0,
759 "destructive": 0,
760 "untrusted_content": 0,
761 "private_data": 0
762 },
763 {
764 "is_public_sink": 0,
765 "destructive": 0,
766 "untrusted_content": 0,
767 "private_data": 0
768 },
769 {
770 "is_public_sink": 0,
771 "destructive": 0,
772 "untrusted_content": 0,
773 "private_data": 0
774 },
775 {
776 "is_public_sink": 0,
777 "destructive": 0,
778 "untrusted_content": 0,
779 "private_data": 0
780 },
781 {
782 "is_public_sink": 0,
783 "destructive": 0,
784 "untrusted_content": 0,
785 "private_data": 0
786 },
787 {
788 "is_public_sink": 0,
789 "destructive": 0,
790 "untrusted_content": 0,
791 "private_data": 0
792 },
793 {
794 "is_public_sink": 0,
795 "destructive": 0,
796 "untrusted_content": 0,
797 "private_data": 0
798 },
799 {
800 "is_public_sink": 0,
801 "destructive": 0,
802 "untrusted_content": 0,
803 "private_data": 0
804 },
805 {
806 "is_public_sink": 0,
807 "destructive": 0,
808 "untrusted_content": 0,
809 "private_data": 0
810 },
811 {
812 "is_public_sink": 0,
813 "destructive": 0,
814 "untrusted_content": 0,
815 "private_data": 0
816 },
817 {
818 "is_public_sink": 0,
819 "destructive": 0,
820 "untrusted_content": 0,
821 "private_data": 0
822 },
823 {
824 "is_public_sink": 0,
825 "destructive": 0,
826 "untrusted_content": 0,
827 "private_data": 0
828 },
829 {
830 "is_public_sink": 0,
831 "destructive": 0,
832 "untrusted_content": 0,
833 "private_data": 0
834 },
835 {
836 "is_public_sink": 0,
837 "destructive": 0,
838 "untrusted_content": 0,
839 "private_data": 0
840 },
841 {
842 "is_public_sink": 0,
843 "destructive": 0,
844 "untrusted_content": 0,
845 "private_data": 0
846 },
847 {
848 "is_public_sink": 0,
849 "destructive": 0,
850 "untrusted_content": 0,
851 "private_data": 0
852 },
853 {
854 "is_public_sink": 0,
855 "destructive": 0,
856 "untrusted_content": 0,
857 "private_data": 0
858 },
859 {
860 "is_public_sink": 0,
861 "destructive": 0,
862 "untrusted_content": 0,
863 "private_data": 0
864 },
865 {
866 "is_public_sink": 0,
867 "destructive": 0,
868 "untrusted_content": 0,
869 "private_data": 0
870 },
871 {
872 "is_public_sink": 0,
873 "destructive": 0,
874 "untrusted_content": 0,
875 "private_data": 0
876 },
877 {
878 "is_public_sink": 0,
879 "destructive": 0,
880 "untrusted_content": 0,
881 "private_data": 0
882 }
883 ]
884 ],
885 "error": null
886 }
887}
888
889Process exited with code 0
890✓ Completed in 235872ms
npm-audit
0 findings155803ms
No findings — all checks passed.
View logs
npm-audit155803ms
1[2026-02-11T20:10:36.996Z] $ npm audit --json --prefix /tmp/clawguard-scan-6GJWeh/repo/skills/autogame-17/evolver
2{
3 "error": {
4 "code": "ENOLOCK",
5 "summary": "This command requires an existing lockfile.",
6 "detail": "Try creating one first with: npm i --package-lock-only\nOriginal error: loadVirtual requires existing shrinkwrap file"
7 }
8}
9
10⚠ stderr output:
11npm error code ENOLOCK
12npm error audit This command requires an existing lockfile.
13npm error audit Try creating one first with: npm i --package-lock-only
14npm error audit Original error: loadVirtual requires existing shrinkwrap file
15npm error A complete log of this run can be found in: /home/runner/.npm/_logs/2026-02-11T20_10_16_715Z-debug-0.log
16
17Process exited with code 1
18✓ Completed in 155803ms

Scanned: 2/11/2026, 8:12:54 PM