feat(v0.3.0): paradigm shift — TimeWeb-only LLM + persistent advisor trail + improvement queue
This is the rc.4 batch the user requested:
1. Emergency triggers (low HP + close hostile, lava-under-foot)
bypass the long cooldown so the LLM is consulted BEFORE the bot
dies, not after.
2. Active manifesto need is now included in the advisor user prompt
— the LLM picks suggestions that satisfy the bot's current
concrete need (L2 tools_wood → "gather logs nearby" not
"explore further").
3. Every advisor recommendation is persisted to SQLite
(advisor_recommendations table) with full token usage. The
reflex marks 'applied=1' when it dispatches and updates
outcome_ok/code when the dispatch completes. Ground truth for
"is the LLM actually helping" lives in the DB, not in logs.
4. Pi CLI is OUT of every background loop. coach/postmortem and
coach/reflect now go through the same TimeWeb endpoint
fast-advisor uses, via the shared coach/llm-call.js helper.
Pi is reserved for manual operator commands.
5. The LLM (postmortem, reflect, advisor) can flag "structural
gaps" — missing skills/features the operator should implement.
These land in the new improvement_requests table. Dedup by
title bumps `votes` instead of inserting duplicates so the
queue doesn't bloat. Operator views via
`node scripts/list-improvements.js`.
6. A deterministic trigger-tuner runs hourly: reads 24h of
recommendation stats, flags triggers whose success rate is
below 25% (sample ≥ 5) or whose prompts are expensive (>1000
input tokens) with mediocre payoff. Improvements get
source="tuner", category="tuning". No LLM call.
New files:
runtime/coach/llm-call.js — askAnalytical() helper
runtime/coach/trigger-tuner.js — stats → improvements
runtime/coach/trigger-tuner.test.js
scripts/list-improvements.js — operator CLI
Schema additions:
advisor_recommendations: id, ts, trigger_reason, planned_skill,
recommended_skill, action, rationale, active_need, tokens_in,
tokens_out, latency_ms, applied, outcome_ok, outcome_code, outcome_at
improvement_requests: id, ts, source, category, title, description,
context, priority, status, duplicate_of, votes, implemented_at, notes
Renamed env-var consumers:
Pi-coach drainOnce({ askPi }) → drainOnce({ askAnalyticalFn? })
Pi-reflect runOnce({ askPi }) → runOnce({ askAnalyticalFn? })
bot.js attachCoach/attachReflect no longer pass askPi
attachTuner() added to bot.js spawn handler
lessons.source 'pi-coach' → 'timeweb-coach'
lessons.source 'pi-reflect' → 'timeweb-reflect'
Token cost measured live:
~705 input + 45 output = ~750 total per advisor call
worst case @ 6 calls/hour rate cap = ~108K tokens/day
OpenAI gpt-5-mini reference price: ~$0.60/month
Operator usage:
node scripts/list-improvements.js # open queue
node scripts/list-improvements.js --stats # advisor performance
node scripts/list-improvements.js --done 17 "shipped in 0.3.1"
node scripts/list-improvements.js --reject 18 "duplicate"
Tests: 360 green (was 332, +28 new).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,72 @@ Tests: 315 green (was 279 on rc.1, +36 new):
|
||||
- `runtime/reflex.test.js` — 2 new integration tests (manifesto-on
|
||||
overrides curriculum; well-fed bot pursues tools_stone)
|
||||
|
||||
### rc.4 (this commit batch) — Paradigm shift: TimeWeb-only LLM + improvement queue
|
||||
**What changed**: Pi (CLI subscription) was removed from every
|
||||
background loop. The bot's analytical LLM path (`coach/postmortem`,
|
||||
`coach/reflect`) now goes through the same TimeWeb endpoint the fast
|
||||
advisor already uses. The trigger system was extended with
|
||||
emergency conditions (low HP + close hostile, lava under foot)
|
||||
that bypass the long cooldown. Every recommendation is persisted to
|
||||
SQLite with its outcome, and a deterministic tuner watches the
|
||||
stats to flag underperforming triggers. The LLM also writes a
|
||||
queue of "structural gaps" — missing skills or features —
|
||||
that the operator reviews and implements by hand.
|
||||
|
||||
- [`runtime/coach/llm-call.js`](../../runtime/coach/llm-call.js) —
|
||||
shared `askAnalytical()` helper that wraps `runtime/llm/provider.js#complete()`
|
||||
with a longer (30s) timeout suitable for postmortem and reflect.
|
||||
- [`runtime/coach/postmortem.js`](../../runtime/coach/postmortem.js):
|
||||
- Drain loop runs through TimeWeb, not Pi CLI
|
||||
- `buildPrompt()` returns `{system, user}` (was a single concatenated string)
|
||||
- Reply schema includes `improvements[]` for missing-skill callouts
|
||||
- `lessons` source is now `timeweb-coach` (was `pi-coach`)
|
||||
- [`runtime/coach/reflect.js`](../../runtime/coach/reflect.js) — same
|
||||
treatment. `lessons` source is now `timeweb-reflect`.
|
||||
- [`runtime/coach/advisor-trigger.js`](../../runtime/coach/advisor-trigger.js):
|
||||
- **Emergency triggers** added: HP≤6 + hostile≤8b, or lava under foot.
|
||||
Use a much shorter 20s cooldown — wait-on-cooldown would be lethal.
|
||||
- Active need now passed to the LLM so suggestions track the manifesto.
|
||||
- Every recommendation is `insertRecommendation()`-ed; reflex marks
|
||||
`applied=1` when it dispatches, and `outcome_ok` when the skill returns.
|
||||
- [`runtime/knowledge/schema.sql`](../../runtime/knowledge/schema.sql):
|
||||
two new tables.
|
||||
- `advisor_recommendations` — ground truth for the LLM trail with
|
||||
full token usage + outcome attribution
|
||||
- `improvement_requests` — operator-facing queue. Dedup by title
|
||||
bumps `votes` instead of inserting duplicates.
|
||||
- [`runtime/coach/trigger-tuner.js`](../../runtime/coach/trigger-tuner.js)
|
||||
(new) — hourly: reads 24h of recommendation stats, flags low-success
|
||||
triggers and expensive-prompt-mediocre-payoff cases as
|
||||
`improvement_requests` with `source="tuner"`. No LLM call needed
|
||||
— pure SQL.
|
||||
- [`runtime/llm/provider.js`](../../runtime/llm/provider.js):
|
||||
`complete()` now returns `usage: {in, out, total}` and logs
|
||||
`in=Nt/out=Mt` on every call.
|
||||
- [`runtime/coach/fast-advisor.js`](../../runtime/coach/fast-advisor.js):
|
||||
`getUsageSnapshot()` aggregates total tokens across the session;
|
||||
surfaces in `scripts/list-improvements.js --stats`.
|
||||
- [`scripts/list-improvements.js`](../../scripts/list-improvements.js)
|
||||
(new) — operator CLI. `--status open` (default), `--stats`,
|
||||
`--done <id> [note]`, `--inprogress <id>`, `--reject <id>`,
|
||||
`--source <postmortem|reflect|advisor|tuner|manual>`,
|
||||
`--category <skill|tuning|...>`.
|
||||
|
||||
Cost measurement (smoke-test against TimeWeb gpt-5.4-mini):
|
||||
per advise(): ~705 input + 45 output = ~750 tokens
|
||||
rate cap: 6 calls/hour
|
||||
worst case @ full hourly cap: ~108K tokens/day
|
||||
estimated cost (OpenAI gpt-5-mini reference pricing): ~$0.60/month
|
||||
|
||||
Tests: 360 green (was 332 on v0.3.0-rc.3, +28 new):
|
||||
+3 abortSignal tests in skills/contract.test.js
|
||||
+13 advisor-trigger tests
|
||||
+4 emergency-trigger tests
|
||||
+4 knowledge-recommendation tests
|
||||
+3 knowledge-improvement tests
|
||||
+2 postmortem/reflect rewrites for TimeWeb path
|
||||
+7 trigger-tuner tests (low success / expensive / healthy / dedup)
|
||||
|
||||
### rc.3 — Event-driven awareness + skill pre-emption
|
||||
**Root problem solved**: in v0.2.x the reflex was purely polling. The
|
||||
loop took a snapshot every DISPATCH_INTERVAL_MS (~2s) and decided what
|
||||
|
||||
Reference in New Issue
Block a user