- resetLLMFailStreaksForTest helper: the package-global streak is in-memory
state, so the no-switch-on-ordinary-error subtests now reset it before each
case (accumulation across subtests sharing task/profile keys made the third
case escalate, breaking the contract the test guards)
- core lifecycle and credentials fixtures: goals now name the lab target, per
the ambiguity gate (these tests exercise lifecycle/credentials, not the gate)
- canonical reset helper moved into task_llm.go next to the counter it resets
Implements the per-intent rotation shape from #85: a task created with
llm_rotate=true distributes worker intents round-robin over its LLM chain
heads, so lane A can hunt on one model while lane B hunts on another
(different lenses per intent, no extra tokens). Default stays the classic
ordered failover from the active head; planner/goals/mainagent keep the
active head always.
Mechanics: the engine pins the next chain head into the run context when a
worker claims an intent; the pin travels through the provider resolver
(hooks.current now takes ctx). A pin is only a dispatch preference - it must
belong to the task chain and never bypasses failover state (an exhausted
chain stays exhausted). Schema: tasks.llm_rotate boolean, default false,
idempotent ALTER; exposed on the create payload and the task DTO.
Closes#85 (the ensemble/P4 shape stays parked as before)
Three orchestration mechanisms from the Q00/ouroboros evaluation (#99):
- Goal ambiguity gate at task creation: a goal must name a target (URL,
domain, IPv4, localhost:port or absolute path) and reach a length floor,
else the API returns 400 before any token is spent. Deliberately
target-less goals opt out with the literal marker [targetless]. Guards
against the live failure where a goal naming no target sent every worker
to an unrelated asset.
- Consecutive-failure escalation on the task LLM chain: quota exhaustion
already advances the chain; now 3 consecutive non-quota call failures on
the same chain profile advance it too, with the true reason recorded.
Escalation-only by design (no auto-downgrade: mid-task model swaps risk
behavior drift; the operator keeps the manual chain reset).
- Stagnation surfacing in the planner overview: finished intents are
fingerprinted (case-folded, digits collapsed); a direction dispatched 3+
times with zero findings since its first attempt is flagged in a
self-describing stagnation_warning payload that instructs the planner to
diversify instead of grinding. Absent when nothing stagnates.
Closes#99
Extracts candidate lessons from terminal tasks (confirmed, negative,
retest caution), gates them on cue + action + evidence, and makes
extraction idempotent through a per-source evidence key.
ARTEX_RSI_LESSONS selects off / shadow / inject. Shadow logs what would
have been shown; inject appends a code-owned, data-not-instructions block
after the planner and worker system prompts. No prompt mutation and no
adoption: status stays candidate.
Credit: the Library admission rule comes from harness2 (Google Research,
Apache-2.0, arXiv 2610.14224); the gain taxonomy from awesome-rsi
(lobehub).
Comments, doc comments, UI labels, log and error messages, LLM prompt
strings, markdown docs, test data and assertions. Identifiers, enum
keys, routes, placeholders and code structure are unchanged.
Notes:
- docs/漏洞流量证据.md renamed to docs/vulnerability-traffic-evidence.md
- tests that exercised CJK specific handling (GBK zip names, Chinese
full text search) now use ASCII equivalents; go build passes and the
test suite matches the pre translation baseline (remaining failures
need a PostgreSQL DSN and fail identically on the original)
- frontend mention syntax now uses English kinds (finding, asset, ...)
matching the backend, chat mentions tests pass