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
- Held
Repo - The waiting episodes of one repo that
borg learnholds in a store because the repo routes elsewhere now (held). - 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.- CORRECT
Episode::viaof a correction the engineer recorded in a collective by name (borg correct --collective): placed there explicitly, soborg learnnever holds it for its repo’s route (held).- 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 (the merge targets: team and personal lessons, no
tombstone):
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).- held
- The episodes of the store
homethatborg learnholds undercfg, per repo: not learned, not skipped, not recorded here by name (CORRECT), of a repo that routes to another store (or off) now. They wait, never learned here, until they are moved where they belong (borg move <repo>). Reads this store and the config only. - 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_ config learn_in_reportingunder an explicit collectives config: an episode whose repo routes to another store undercfgis held, never learned here (held).- 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).- learned_
episodes - The episodes the store
homehas folded into a lesson, team or personal (tombstones included: they keep their episodes). - 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 - Records the hook’s episode
ein this session’s store (record_episode_locked). - record_
episode_ in record_episodeintostore(the end-of-session job writes to the route’s store).- record_
episode_ locked record_episode_inunder the store’sepisodes.jsonllock (live.rslocked): aborg moveof a repo’s evidence rewrites that file under the lock, and an append landing between its read and its rename would be lost. Contended only by those moves and the captures that also lock it; uncontended, one lock taken on a path that writes anyway.- record_
new_ in - Appends to
storeeach ofepsit does not hold yet (Known), each counted asrecord_episode_incounts it, and returns those appended, in order.readycompletes an episode (its repo, its engineer) just before it is appended, so one already held costs nothing. The one entry for transcript capture (the transcript sweep,borg assimilate --apply). - 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. - store_
lessons - The lessons of the store
homeas this engineer has them:lessons.jsonlwith the store’s personal lessons (reach.rsPERSONAL_FILE) over it, a personal version winning over the team one of its id (the tombstone that withdrew it). For counts and “learned” (learned_episodes);borg status. - 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.