instar 0.9.21 → 0.9.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/cli.js +51 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/init.d.ts.map +1 -1
  4. package/dist/commands/init.js +209 -14
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/knowledge.d.ts +25 -0
  7. package/dist/commands/knowledge.d.ts.map +1 -0
  8. package/dist/commands/knowledge.js +127 -0
  9. package/dist/commands/knowledge.js.map +1 -0
  10. package/dist/commands/nuke.d.ts +22 -0
  11. package/dist/commands/nuke.d.ts.map +1 -0
  12. package/dist/commands/nuke.js +175 -0
  13. package/dist/commands/nuke.js.map +1 -0
  14. package/dist/commands/server.d.ts.map +1 -1
  15. package/dist/commands/server.js +32 -24
  16. package/dist/commands/server.js.map +1 -1
  17. package/dist/core/Config.d.ts +2 -0
  18. package/dist/core/Config.d.ts.map +1 -1
  19. package/dist/core/Config.js +42 -0
  20. package/dist/core/Config.js.map +1 -1
  21. package/dist/core/GitSync.d.ts +6 -0
  22. package/dist/core/GitSync.d.ts.map +1 -1
  23. package/dist/core/GitSync.js +11 -0
  24. package/dist/core/GitSync.js.map +1 -1
  25. package/dist/core/PostUpdateMigrator.d.ts +6 -0
  26. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  27. package/dist/core/PostUpdateMigrator.js +181 -5
  28. package/dist/core/PostUpdateMigrator.js.map +1 -1
  29. package/dist/core/types.d.ts +9 -0
  30. package/dist/core/types.d.ts.map +1 -1
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/knowledge/KnowledgeManager.d.ts +85 -0
  36. package/dist/knowledge/KnowledgeManager.d.ts.map +1 -0
  37. package/dist/knowledge/KnowledgeManager.js +194 -0
  38. package/dist/knowledge/KnowledgeManager.js.map +1 -0
  39. package/dist/messaging/NotificationBatcher.d.ts +73 -0
  40. package/dist/messaging/NotificationBatcher.d.ts.map +1 -0
  41. package/dist/messaging/NotificationBatcher.js +193 -0
  42. package/dist/messaging/NotificationBatcher.js.map +1 -0
  43. package/dist/messaging/TelegramAdapter.d.ts +38 -1
  44. package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
  45. package/dist/messaging/TelegramAdapter.js +157 -9
  46. package/dist/messaging/TelegramAdapter.js.map +1 -1
  47. package/dist/monitoring/SessionWatchdog.d.ts +15 -1
  48. package/dist/monitoring/SessionWatchdog.d.ts.map +1 -1
  49. package/dist/monitoring/SessionWatchdog.js +74 -3
  50. package/dist/monitoring/SessionWatchdog.js.map +1 -1
  51. package/dist/scaffold/templates.d.ts.map +1 -1
  52. package/dist/scaffold/templates.js +25 -0
  53. package/dist/scaffold/templates.js.map +1 -1
  54. package/package.json +2 -1
  55. package/src/templates/hooks/compaction-recovery.sh +165 -0
  56. package/src/templates/hooks/dangerous-command-guard.sh +100 -0
  57. package/src/templates/hooks/grounding-before-messaging.sh +52 -0
  58. package/src/templates/hooks/settings-template.json +63 -0
  59. package/src/templates/scripts/convergence-check.sh +90 -0
  60. package/src/templates/scripts/health-watchdog.sh +63 -0
  61. package/src/templates/scripts/telegram-reply.sh +67 -0
  62. package/upgrades/0.9.22.md +41 -0
  63. package/upgrades/0.9.23.md +37 -0
@@ -0,0 +1,90 @@
1
+ #!/bin/bash
2
+ # Lightweight convergence check — heuristic content quality gate before messaging.
3
+ # No LLM calls. Fast. Catches the most common agent failure modes.
4
+ #
5
+ # Usage: echo "message content" | bash .instar/scripts/convergence-check.sh
6
+ # Exit codes: 0 = converged (safe to send), 1 = issues found (review needed)
7
+ #
8
+ # Inspired by Dawn's convergence-check.py (PROP-159) but simplified for
9
+ # generic agents. Checks 6 criteria via pattern matching:
10
+ #
11
+ # 1. capability_claims — Claims about what the agent can't do (may be wrong)
12
+ # 2. commitment_overreach — Promises the agent may not be able to keep
13
+ # 3. settling — Accepting empty/failed results without investigation
14
+ # 4. experiential_fabrication — Claiming to see/read/feel without verification
15
+ # 5. sycophancy — Reflexive agreement, excessive apology, capitulation
16
+ # 6. url_provenance — URLs with unfamiliar domains that may be fabricated
17
+ #
18
+ # This is Structure > Willpower: the check runs automatically before
19
+ # external messaging, not when the agent remembers to do it.
20
+
21
+ CONTENT=$(cat)
22
+ ISSUES=()
23
+ ISSUE_COUNT=0
24
+
25
+ # 1. CAPABILITY CLAIMS — Watch for "I can't" / "I don't have" / "not available"
26
+ if echo "$CONTENT" | grep -qiE "(unfortunately.{0,20}(i can.t|i.m unable|not (possible|available|supported))|i don.t have (the ability|access|a way)|this (isn.t|is not) (possible|available|supported))"; then
27
+ ISSUES+=("CAPABILITY: You're claiming a limitation. Did you check /capabilities first? Many 'I can't' statements are wrong — verify before sending.")
28
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
29
+ fi
30
+
31
+ # 2. COMMITMENT OVERREACH — Promises that may not survive session boundaries
32
+ if echo "$CONTENT" | grep -qiE "(i.ll (make sure|ensure|guarantee|always|never forget)|i (promise|commit to|will always)|you can count on me to|i.ll remember (to|this)|from now on i.ll)"; then
33
+ ISSUES+=("COMMITMENT: You're making a promise that may not survive context compaction or session end. Can your infrastructure actually keep this commitment? If not, reframe as intent rather than guarantee.")
34
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
35
+ fi
36
+
37
+ # 3. SETTLING — Accepting empty results without digging deeper
38
+ if echo "$CONTENT" | grep -qiE "(no (data|results|information) (available|found|exists)|nothing (to report|happened|was found)|there (is|are) no|could(n.t| not) find (any|the)|appears to be empty|no (relevant|matching|applicable))"; then
39
+ ISSUES+=("SETTLING: You're reporting nothing found. Did you check multiple sources? Could the data source be stale or the search terms wrong? Empty results deserve investigation, not acceptance.")
40
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
41
+ fi
42
+
43
+ # 4. EXPERIENTIAL FABRICATION — Claiming first-person experience without tool verification
44
+ if echo "$CONTENT" | grep -qiE "(i (can see|noticed|observed|felt|sensed|perceived) (that |the |a |an )|looking at (this|the|your)|from what i.ve (seen|read|observed)|i.ve (reviewed|examined|analyzed|inspected) (the|your|this))"; then
45
+ ISSUES+=("EXPERIENTIAL: You're claiming a first-person experience. Did you actually access this data with a tool in THIS session, or are you completing a social script? Verify before claiming.")
46
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
47
+ fi
48
+
49
+ # 5. SYCOPHANCY — Reflexive agreement, excessive apology
50
+ if echo "$CONTENT" | grep -qiE "(you.re (absolutely|totally|completely) right|i (completely|totally|fully) (agree|understand)|great (question|point|observation)|i apologize for|sorry.{0,20}(mistake|confusion|error|oversight)|that.s (a |an )?(excellent|great|wonderful|fantastic) (point|question|idea|suggestion))"; then
51
+ ISSUES+=("SYCOPHANCY: You may be reflexively agreeing or over-apologizing. If you genuinely agree, state why. If you don't fully agree, say what you actually think. Politeness is not a substitute for honesty.")
52
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
53
+ fi
54
+
55
+ # 6. URL PROVENANCE — URLs with unfamiliar domains may be fabricated
56
+ # Common confabulation: agent constructs plausible URL from project name
57
+ # (e.g., "deepsignal.xyz" from project "deep-signal"). Catch and require verification.
58
+ # Known-safe domains are whitelisted; anything else gets flagged.
59
+ URLS_IN_MSG=$(echo "$CONTENT" | grep -oE 'https?://[^ )"'"'"'>]+' 2>/dev/null || true)
60
+ if [ -n "$URLS_IN_MSG" ]; then
61
+ UNFAMILIAR_URLS=""
62
+ while IFS= read -r url; do
63
+ [ -z "$url" ] && continue
64
+ # Skip well-known service domains
65
+ if echo "$url" | grep -qE '(github\.com|vercel\.app|vercel\.com|netlify\.app|netlify\.com|npmjs\.com|npmjs\.org|cloudflare\.com|google\.com|twitter\.com|x\.com|youtube\.com|reddit\.com|discord\.com|discord\.gg|telegram\.org|t\.me|localhost|127\.0\.0\.1|stackoverflow\.com|developer\.mozilla\.org|docs\.anthropic\.com|anthropic\.com|openai\.com|claude\.ai|notion\.so|linear\.app|fly\.io|render\.com|railway\.app|heroku\.com|amazonaws\.com|azure\.com|gitlab\.com|bitbucket\.org|docker\.com|hub\.docker\.com|pypi\.org|crates\.io|rubygems\.org|pkg\.go\.dev|wikipedia\.org|medium\.com|substack\.com|circle\.so|ghost\.io|telegraph\.ph)'; then
66
+ continue
67
+ fi
68
+ UNFAMILIAR_URLS="$UNFAMILIAR_URLS $url\n"
69
+ done <<< "$URLS_IN_MSG"
70
+
71
+ if [ -n "$UNFAMILIAR_URLS" ]; then
72
+ ISSUES+=("URL_PROVENANCE: Your message contains URLs with unfamiliar domains:\n${UNFAMILIAR_URLS}Before including a URL in a message, verify it appeared in actual tool output in THIS session OR confirm it resolves with curl. A common confabulation pattern is constructing plausible-looking domains from project names (e.g., 'deepsignal.xyz' from project 'deep-signal'). If you did not get this URL from a tool, do NOT include it.")
73
+ ISSUE_COUNT=$((ISSUE_COUNT + 1))
74
+ fi
75
+ fi
76
+
77
+ # Output results
78
+ if [ "$ISSUE_COUNT" -gt "0" ]; then
79
+ echo "=== CONVERGENCE CHECK: ${ISSUE_COUNT} ISSUE(S) FOUND ==="
80
+ echo ""
81
+ for ISSUE in "${ISSUES[@]}"; do
82
+ echo " - $ISSUE"
83
+ echo ""
84
+ done
85
+ echo "Review and revise before sending. Re-run this check after revision."
86
+ echo "=== END CONVERGENCE CHECK ==="
87
+ exit 1
88
+ else
89
+ exit 0
90
+ fi
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # health-watchdog.sh — Monitor instar server and auto-recover.
3
+ #
4
+ # Install as a cron job:
5
+ # */5 * * * * /path/to/health-watchdog.sh >> /path/to/.instar/logs/watchdog.log 2>&1
6
+ #
7
+ # Or run via launchd on macOS.
8
+
9
+ # Configuration — set these for your project
10
+ PROJECT_DIR="${INSTAR_PROJECT_DIR:-$(dirname "$(dirname "$(realpath "$0")")")}"
11
+ PORT="${INSTAR_PORT:-4040}"
12
+ SERVER_SESSION="${INSTAR_SERVER_SESSION:-agent-server}"
13
+ TMUX_PATH="${INSTAR_TMUX:-/opt/homebrew/bin/tmux}"
14
+
15
+ # Find tmux if not at default path
16
+ if [ ! -f "$TMUX_PATH" ]; then
17
+ TMUX_PATH=$(which tmux 2>/dev/null)
18
+ fi
19
+
20
+ if [ -z "$TMUX_PATH" ] || [ ! -f "$TMUX_PATH" ]; then
21
+ echo "[$(date -Iseconds)] ERROR: tmux not found"
22
+ exit 1
23
+ fi
24
+
25
+ # Check if server is responding
26
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${PORT}/health" 2>/dev/null)
27
+
28
+ if [ "$HTTP_CODE" = "200" ]; then
29
+ # Server is healthy — nothing to do
30
+ exit 0
31
+ fi
32
+
33
+ echo "[$(date -Iseconds)] Server not responding (HTTP: ${HTTP_CODE}). Checking tmux..."
34
+
35
+ # Check if tmux session exists
36
+ if $TMUX_PATH has-session -t "=${SERVER_SESSION}" 2>/dev/null; then
37
+ echo "[$(date -Iseconds)] Session '${SERVER_SESSION}' exists but server not responding. Killing and restarting..."
38
+ $TMUX_PATH kill-session -t "=${SERVER_SESSION}" 2>/dev/null
39
+ sleep 2
40
+ fi
41
+
42
+ # Restart the server
43
+ CLI_PATH="${PROJECT_DIR}/node_modules/.bin/instar"
44
+ if [ ! -f "$CLI_PATH" ]; then
45
+ CLI_PATH=$(which instar 2>/dev/null)
46
+ fi
47
+
48
+ if [ -z "$CLI_PATH" ] || [ ! -f "$CLI_PATH" ]; then
49
+ echo "[$(date -Iseconds)] ERROR: instar CLI not found"
50
+ exit 1
51
+ fi
52
+
53
+ cd "$PROJECT_DIR" && $CLI_PATH server start
54
+ echo "[$(date -Iseconds)] Server restart initiated"
55
+
56
+ # Wait and verify
57
+ sleep 5
58
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:${PORT}/health" 2>/dev/null)
59
+ if [ "$HTTP_CODE" = "200" ]; then
60
+ echo "[$(date -Iseconds)] Server recovered successfully"
61
+ else
62
+ echo "[$(date -Iseconds)] WARNING: Server still not responding after restart (HTTP: ${HTTP_CODE})"
63
+ fi
@@ -0,0 +1,67 @@
1
+ #!/bin/bash
2
+ # telegram-reply.sh — Send a message back to a Telegram topic via instar server.
3
+ #
4
+ # Usage:
5
+ # ./telegram-reply.sh TOPIC_ID "message text"
6
+ # echo "message text" | ./telegram-reply.sh TOPIC_ID
7
+ # cat <<'EOF' | ./telegram-reply.sh TOPIC_ID
8
+ # Multi-line message here
9
+ # EOF
10
+ #
11
+ # Reads INSTAR_PORT from environment (default: 4040).
12
+
13
+ TOPIC_ID="$1"
14
+ shift
15
+
16
+ if [ -z "$TOPIC_ID" ]; then
17
+ echo "Usage: telegram-reply.sh TOPIC_ID [message]" >&2
18
+ exit 1
19
+ fi
20
+
21
+ # Read message from args or stdin
22
+ if [ $# -gt 0 ]; then
23
+ MSG="$*"
24
+ else
25
+ MSG="$(cat)"
26
+ fi
27
+
28
+ if [ -z "$MSG" ]; then
29
+ echo "No message provided" >&2
30
+ exit 1
31
+ fi
32
+
33
+ PORT="${INSTAR_PORT:-4040}"
34
+
35
+ # Read auth token from config (if present)
36
+ AUTH_TOKEN=""
37
+ if [ -f ".instar/config.json" ]; then
38
+ AUTH_TOKEN=$(python3 -c "import json; print(json.load(open('.instar/config.json')).get('authToken',''))" 2>/dev/null)
39
+ fi
40
+
41
+ # Escape for JSON
42
+ JSON_MSG=$(printf '%s' "$MSG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null)
43
+ if [ -z "$JSON_MSG" ]; then
44
+ # Fallback if python3 not available: basic escape
45
+ JSON_MSG="\"$(printf '%s' "$MSG" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\n/\\n/g')\""
46
+ fi
47
+
48
+ if [ -n "$AUTH_TOKEN" ]; then
49
+ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "http://localhost:${PORT}/telegram/reply/${TOPIC_ID}" \
50
+ -H 'Content-Type: application/json' \
51
+ -H "Authorization: Bearer ${AUTH_TOKEN}" \
52
+ -d "{\"text\":${JSON_MSG}}")
53
+ else
54
+ RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "http://localhost:${PORT}/telegram/reply/${TOPIC_ID}" \
55
+ -H 'Content-Type: application/json' \
56
+ -d "{\"text\":${JSON_MSG}}")
57
+ fi
58
+
59
+ HTTP_CODE=$(echo "$RESPONSE" | tail -1)
60
+ BODY=$(echo "$RESPONSE" | sed '$d')
61
+
62
+ if [ "$HTTP_CODE" = "200" ]; then
63
+ echo "Sent $(echo "$MSG" | wc -c | tr -d ' ') chars to topic $TOPIC_ID"
64
+ else
65
+ echo "Failed (HTTP $HTTP_CODE): $BODY" >&2
66
+ exit 1
67
+ fi
@@ -0,0 +1,41 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ ## What Changed
4
+
5
+ ### Anti-Confabulation Infrastructure (Convergence Check Pipeline)
6
+
7
+ The grounding-before-messaging hook has been upgraded from a simple text reminder ("remember who you are") to a **full three-phase defense pipeline**:
8
+
9
+ 1. **Identity injection** — Injects full AGENT.md content directly into context before any external message
10
+ 2. **Convergence check** — Heuristic quality gate that scans outgoing messages for 6 failure modes
11
+ 3. **URL provenance verification** — Flags URLs with unfamiliar domains that may be fabricated
12
+
13
+ **New convergence check category: URL Provenance (Category 6)**
14
+
15
+ Agents commonly confabulate plausible-looking URLs by pattern-matching from project names — e.g., a project called "deep-signal" produces "deepsignal.xyz" in outgoing messages. The convergence check now extracts all URLs from outgoing messages and flags any with domains not in a curated allowlist of well-known services (GitHub, Vercel, npm, Cloudflare, etc.).
16
+
17
+ This check runs **automatically** before every external message (Telegram, email, API posts). Structure > Willpower.
18
+
19
+ **New CLAUDE.md gravity wells:**
20
+ - **"Defensive Fabrication"** — Warns agents about the doubling-down pattern: when caught in an error, constructing a plausible excuse ("the CLI returned that URL") instead of admitting the fabrication
21
+ - **"Output Provenance"** — Every URL, status code, or data point in an outgoing message must be traceable to actual tool output in the current session
22
+
23
+ **New CLAUDE.md anti-pattern:**
24
+ - **"Cite Without Source"** — Anti-pattern for including URLs/data in messages without verifying they came from tool output
25
+
26
+ ### Technical Details
27
+
28
+ - `convergence-check.sh` now installed at `.instar/scripts/convergence-check.sh` during both fresh setup and auto-update
29
+ - `grounding-before-messaging.sh` upgraded to call the convergence check pipeline (blocking: exit 2 on failure)
30
+ - `src/templates` now included in npm package for template file access
31
+
32
+ ## What to Tell Your User
33
+
34
+ Your agent now has structural protection against URL fabrication and other forms of confabulation in outgoing messages. Before sending any Telegram message, email, or API post, your agent's messages are automatically scanned for common failure modes including fabricated URLs, unsupported capability claims, and experiential fabrication. This runs automatically — no configuration needed.
35
+
36
+ ## Summary of New Capabilities
37
+
38
+ - **URL provenance check**: Outgoing messages are scanned for fabricated URLs before sending
39
+ - **Full convergence check pipeline**: 6-category quality gate runs before every external message
40
+ - **Identity injection before messaging**: Full AGENT.md content injected, not just a reminder to re-read it
41
+ - **New gravity wells**: "Defensive Fabrication" and "Output Provenance" teach agents about confabulation patterns
@@ -0,0 +1,37 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ ## What Changed
4
+
5
+ ### LLM-Supervised Execution: Intelligence Layer Wired Throughout
6
+
7
+ Previously, several critical pathways bypassed the intelligence layer and relied on regex pattern matching alone for decisions that affect user experience. This release wires a shared `IntelligenceProvider` through all critical decision points:
8
+
9
+ **MessageSentinel (Layer 2 now active)**
10
+ - The sentinel's LLM classification layer was dead code — constructed with `new MessageSentinel({})` (no intelligence). Now wired with a shared intelligence provider. Messages that pass the word count gate but don't match fast-path patterns are classified by LLM instead of defaulting to pass-through.
11
+
12
+ **Telegram Stall/Promise Alerts (LLM-gated)**
13
+ - Fallback stall alerts (when StallTriageNurse is unavailable) now pass through an LLM confirmation before sending user-facing messages. Prevents false positive alerts about sessions that are actually working on complex tasks.
14
+ - Promise expiration alerts follow the same LLM gate.
15
+
16
+ **SessionWatchdog (LLM command analysis)**
17
+ - Before escalating from monitoring to Ctrl+C, the watchdog now asks the intelligence provider whether the long-running command is legitimately slow (builds, installs, migrations) or actually stuck. Legitimate commands are temporarily excluded from escalation.
18
+
19
+ **Shared Intelligence Provider**
20
+ - A single `IntelligenceProvider` instance (Anthropic API preferred, Claude CLI fallback) is created at startup and shared across Sentinel, TelegramAdapter, SessionWatchdog, and StallTriageNurse. This eliminates redundant provider creation and ensures consistent LLM access.
21
+
22
+ ### Technical Details
23
+
24
+ - All LLM gates are fail-open: if the intelligence provider fails, the original behavior is preserved
25
+ - Shared intelligence is created early in startup, before component initialization
26
+ - Startup log now shows intelligence status: `sentinel=LLM-supervised`, `stall alerts: LLM-gated`
27
+
28
+ ## What to Tell Your User
29
+
30
+ Your agent's safety systems now use LLM intelligence for critical decisions that previously relied on regex alone. The message sentinel can now classify ambiguous messages using an LLM instead of just pattern matching. Stall alerts and the session watchdog check with an LLM before taking action, reducing false positives. No configuration needed — this works automatically when an Anthropic API key or Claude CLI is available.
31
+
32
+ ## Summary of New Capabilities
33
+
34
+ - **Sentinel LLM classification**: Ambiguous messages now classified by LLM (Layer 2 was previously dead code)
35
+ - **LLM-gated stall alerts**: Fallback alerts confirmed by intelligence before sending to user
36
+ - **LLM-gated watchdog**: Long-running commands evaluated by LLM before escalation
37
+ - **Shared intelligence provider**: Single provider instance shared across all components