Expand description
The conscience’s live learning loop.
Capture (hooks, deterministic, 0 tokens): an engineer correction is a prompt that pushes back on what the drone just proposed (“no…”, “double check…”, “why do you…”), or a rejected tool call / plan whose rejection carries the engineer’s words. Each becomes a raw episode: the task, the drone’s proposal, the correction.
Generalise (borg learn, at session end, one model call per episode): the episode becomes a
lesson (question + situations → consequence) or is merged into an existing lesson that
expresses the same concern — the old wording is kept in history and support grows, so the
library consolidates instead of piling up near-duplicates. Each lesson lists the engineers
(git user.email) whose corrections it was learned from, its area (the kind of concern, for trust per
engineer × area, trust.rs) and, when the correction contradicts a lesson it was shown, which
lessons it supersedes; all from the same model call.
Outcomes (borg learn, 0 tokens): a merge into a lesson the conscience asked earlier in the
same session, or a new lesson superseding one it asked, means asking did not prevent the
correction; a correction siding with one side of a rendered disagreement corrects the other
sides instead; see outcome.rs.
Vetoes (borg no, veto.rs): an engineer’s “no” is an episode of kind veto, asked with its own
prompt (veto::OPENING), whose answer may also name an invariant. It is learned at the end of any
session, not only its own (a terminal veto may name an ended session). A veto merged into a lesson
an earlier veto made counts as veto_repeat; an invariant of a lesson placed in this store becomes
a proposed constraint in the queen’s queue (veto::propose), never a constraint.
Modules§
- regret
- A regret: an earlier session’s decision whose lines a later session fixed (notes/regress.rs).
borg learnasks about it as about a correction, one model call, with its own opening and sections: the lesson is a question to ask at the decision point (“Beforein , has been considered?”). Reach, merging and superseding follow the correction prompt’s rules unchanged.
Structs§
- AskFailed
- The model call failed (quota, rate limit, not logged in, network, malformed answer): unlike a
verdict of “not a lesson”, the episode stays waiting and a later
borg learnretries it. - Episode
- Known
- What a store already holds, so an episode read again (the transcript sweep, session end,
borg assimilate) is never appended twice. Read once, then grown with what is appended. - Lesson
- A lesson as stored: the conscience’s
Challengeplus provenance and consolidation state. Append-only: a merge writes a new version with the same id; readers keep the latest. - Step
- One model verdict during a learn run, for a progress line: the episode’s place among those this
run asks about (
doneoftotal), and what came of it.
Constants§
- ANSWER
Episode::viaof an answer to the agent’s own question, and itswhyin the usage statistics.- EXCERPT_
CHARS - The longest excerpt an episode keeps of a correction, a rejected tool call, and the task as the
learn prompt shows it. Guard: bounds what one episode adds to the store and to its prompt (a pasted
log would otherwise go in whole); a regret’s excerpts share it (regret.rs
CAP). - PROPOSAL_
CHARS - The end of the drone’s last proposal an episode keeps (hook.rs
proposal). Guard: bounds one episode’sagenttext. - SAME_MS
- Two prompt episodes of one session this close together are the same correction. Method: a dedupe
window; the live hook’s capture time and the transcript’s message time of one prompt differ by a
second or two, two corrections of a session by far more. Episodes of a tool call are matched by
their id and words instead (
Known::holds). - TASK_
CHARS - The session’s task an episode keeps (hook.rs
capture_prompt): the prompt it started from. Guard: bounds the.taskstate file and each episode’stask(a pasted spec would otherwise go in whole); the learn prompt shows its firstEXCERPT_CHARS.
Functions§
- ask_
claude - One structured call to the drone’s model (runner.rs picks claude, omp or opencode).
- ask_
model - The model call behind
ask_claude, for any JSON schema: the structured answer and its cost in USD (None when the CLI reported none).BORG_LEARN_MODELpicks the model,runner::choosethe CLI. - count_
correction - A correction in the usage statistics: a rejected tool call, a pushback, an answer to the agent’s question
(
whyANSWER, rolled up apart from the corrections, stats.rsfold) or a regret, with a short excerpt. - denied
- A refusal that carries no words (see
DENIAL): the engineer’s reason is their next prompt. - engineer
- The engineer working in
cwd: their git user.email, empty when unknown. - generalise
- Generalise one episode against the existing library:
Ok(Some)a new lesson or a merged version of an existing one,Ok(None)not a lesson,Errno verdict.askperforms the model call (injectable for tests). A regret (regret.rs) gets its own prompt, the same verdict. - generalise_
with generalise, with the invariant a veto’s answer named (empty otherwise).- home
- is_
correction - A prompt that pushes back on the drone’s last proposal (same heuristic as the offline miner).
- learn_
in learn_pendingon the store inhome. Withtrack, outcomes of asked lessons are recorded (outcome.rs): a merge into a lesson asked earlier in the episode’s session, and a lesson asked earlier that the new one supersedes, areasked_then_corrected(outcome::contradicted); at the end ofsession, and in every session idle foroutcome::IDLE_MSatnow, the other asked lessons areasked_not_corrected. So any run settles, not only theendhook’s; a session it skipped episodes of is not settled as idle. Only a “not a lesson” verdict is recorded as skipped: an episode whose model call failed stays waiting (and its session unsettled) for the next run, and afterMAX_FAILURESfailures in a row the run stops asking. Returns (new lessons, merges, episodes still waiting for a verdict).- learn_
in_ reporting learn_in, callingreportafter every model call (the CLI prints it; the hooks pass a no-op).- learn_
pending borg learn [--session ID]: generalise every episode not yet folded into a lesson.--sessionis given when that session ended: its asked lessons and the placebos the judge never reached are then settled. Any run also settles sessions idle for a day, so a missingendhook does not bias the outcomes. Returns (new lessons, merges, episodes still waiting because the model gave no verdict).- learning
- False when BORG_LEARN=off (eval drones): nothing is captured or recorded.
- lessons
- The latest version of every lesson.
- now_ms
- print_
step - A progress line on stderr:
[12/104 · 18 s · ~28 min left] new lesson L…: <question>. - record_
episode - record_
episode_ in record_episodeintostore(the end-of-session job writes to the route’s store).- record_
new_ in - Append
etostore(counted asrecord_episode_incounts it) unlessknownholds it;knownthen holds it too. True when appended. The one entry for transcript capture. - regret_
credit - False when BORG_REGRET_CREDIT=off: a regret no longer counts against the lessons asked before the
decision (
credit_regrets). - rejection
- The engineer’s words from a rejected tool call or plan, if any.
- schema_
for - The answer schema for
prompt: a veto’s prompt (it starts withveto::OPENING) gets the invariant field; correction and regret calls stay as they were. - test_
credit - Crediting a session’s own green test runs on (
outcome::tested): learning is, and BORG_TEST_CREDIT is notoff(an eval’s frozen arm). - transcript_
id - The id of an episode read from a transcript:
<session8>-T<call>for one about a tool call (the harness’s own id for it: Claude’stool_use_id, omp’stoolCallId, opencode’s part id, Codex’scall_id), else<session8>-<ms>as the hook names a prompt’s. Content, never a position: a transcript still being written cannot shift it.