Skip to main content

Module learn

Module learn 

Source
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 learn asks 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 (“Before in , 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 learn retries 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 Challenge plus 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 (done of total), and what came of it.

Constants§

ANSWER
Episode::via of an answer to the agent’s own question, and its why in 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’s agent text.
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 .task state file and each episode’s task (a pasted spec would otherwise go in whole); the learn prompt shows its first EXCERPT_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_MODEL picks the model, runner::choose the CLI.
count_correction
A correction in the usage statistics: a rejected tool call, a pushback, an answer to the agent’s question (why ANSWER, rolled up apart from the corrections, stats.rs fold) 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, Err no verdict. ask performs 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_pending on the store in home. With track, 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, are asked_then_corrected (outcome::contradicted); at the end of session, and in every session idle for outcome::IDLE_MS at now, the other asked lessons are asked_not_corrected. So any run settles, not only the end hook’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 after MAX_FAILURES failures in a row the run stops asking. Returns (new lessons, merges, episodes still waiting for a verdict).
learn_in_reporting
learn_in, calling report after 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. --session is 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 missing end hook 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_episode into store (the end-of-session job writes to the route’s store).
record_new_in
Append e to store (counted as record_episode_in counts it) unless known holds it; known then 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 with veto::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 not off (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’s tool_use_id, omp’s toolCallId, opencode’s part id, Codex’s call_id), else <session8>-<ms> as the hook names a prompt’s. Content, never a position: a transcript still being written cannot shift it.