Skip to content

[RFC] Unify FlyBot's dev harness into a single, versioned layer #874

Closed

Description

@hsliuustc0106

Problem

FlyBot has no single harness. Its knobs are spread across five places:

  • prompt in prompt.js and AGENTS.md
  • tools in tools.js
  • step and retry limits in turns.js
  • model in models.js
  • verification in CI and merge-gate

Every one of these is fixed per bot, so we can't tier work by difficulty, compare variants, or let an RSI loop evolve the harness safely.

Options

A. Status quo plus per-knob tweaks

  • Pros: no refactor and no regression risk. Each fix is small.
  • Cons: no single thing to version, compare, or roll back. Tiering would need special cases across five files, and any RSI loop would have to edit scattered code.

B. Unified declarative harness layer (proposed)
A harness is one config that declares prompt, tools, model, step/retry budget, and verifiers. The runtime loads the config chosen for each task.

  • Pros:
    • Lite, Medium, and Heavy become three configs.
    • HarnessPro can evolve those files, with every change committed to git, so it's auditable and easy to roll back.
    • It's easy to A/B test, and cost can be tracked per harness.
  • Cons:
    • Upfront refactor of the host code paths, with a risk of behavior drift. Mitigation: step 0 must be behavior-neutral and verified by core/dev/eval.
    • Config can't express everything, and some logic will still live in code.

C. Adopt an external harness framework
For example, run coding tasks through an existing coding-agent runtime.

  • Pros: mature tooling, and less to maintain ourselves.
  • Cons:
    • Its abstractions don't match ours: Bot Social, multi-bot rooms, and the Written-by: and merge-gate contracts would all have to be bridged.
    • It adds an outside dependency.
    • We'd lose control over prompt caching and cost.

D. Fully online self-modifying harness (Harness²-style)

  • Pros: adapts to new kinds of issues without an offline cycle.
  • Cons:
    • Hard to predict and audit.
    • Each task needs extra trial runs, so it costs more.
    • It's a poor fit for a merge gate.
  • Better used only as an experience library later on.

Recommendation

Option B, rolled out in phases:

  • Step 0: extract the harness layer with no behavior change. The current setup becomes a single default harness.
  • Step 1: add Lite, Medium, and Heavy tiers, with routing labels set at triage and HarnessPro-style offline evolution checked against real CI, core/dev/eval, and rsi-baseline. Add the issue/PR number, tool-call count, and wall time to the usage records.
  • Step 2: add a Harness²-style experience library, kept separate per repo or tech stack.

Risks

Related: #784, #796, #871

Activity

  1. Birfy commented on Oct 23, 2026

    @Birfy
    Collaborator

    Triaged as a design decision, not a task: labelled enhancement|area:automation|needs-human. Not agent-ready — the first thing it asks for is a choice no agent should make for the owner.

    What the repo actually shows today

    The five knobs are not five independent homes. At 1d81580e:

    • One implementation: core/src/host/prompt.js, tools.js, turns.js, models.js.
    • Three mirrors of it: ds-bot/src/host/…, plus the patch set under patches/ds-bot/files/ — every change there must be byte-identical in all of them (ds-bot-patches check), which the feat(rooms): mint and withdraw a local room invite link (#852) #861 and feat(rooms): answer a local room's invite link (#852) #864 PRs both had to satisfy.
    • A fourth prompt lives in a plugin: plugins/tree/src/prompt.js.
    • core/dev/eval/ exists (run.mjs, judge.mjs, rubric.mjs, specs.mjs, guard.mjs), so the step-0 gate the proposal names is real.
    • core/dev/harness/ is not a harness in this sense: it is ds-bot-test-harness, a private package pinning @deepseek-ai/dsh 0.2.0-rc.2, jsdom and oxlint for the unit tests. The name will mislead whoever picks this up.

    So the cost of Option B is not "one config file": step 0 has to move the same logic through core/, three mirror copies, and a plugin prompt, with ds-bot-patches and arch-docs as gates. That is the number to weigh, and the proposal does not mention it.

    Three options

    A. Status quo, per-knob tweaks. No refactor, no shared artifact; every future tier comparison stays a special case across the mirrors. Cheapest now, most expensive per change.

    B. Unified declarative harness, as proposed. One config declares prompt, tools, model, step/retry budget and verifiers; the runtime loads the config for a task; Lite/Medium/Heavy are three configs. Step 0 must be behavior-neutral across the mirrors above, or the first regression lands in ds-bot/ where a plugin patch also lives. Step 1 needs a routing label set at triage, which does not exist — and adding one means deciding who owns it and who may write it (see #871), plus it interacts with risk:T*, which the controller owns and no bot writes by hand.

    C. Declarative manifest only — no runtime move. Keep the code where it is, add one versioned harness.json per tier that names the existing knobs (prompt file, tool set, model, budgets, verifier list) and a loader that reads it for reporting and for A/B, while the host keeps executing today's code paths. Gives versioning, comparison and rollback with no step-0 behavior risk; tiers become comparable before anything is refactored. It cannot express new behavior, and someone still has to keep the manifest honest against the code — which is exactly what core/dev/eval can check.

    (C is not in the proposal; it is the option that buys the two things the issue actually asks for — comparison and rollback — without the refactor B defers its risk into.)

    D and the self-modifying variant are out of scope until one of the above exists: both assume a gate that does not exist yet, and a merge gate that cannot audit what it merges is worse than a slower one.

    Relation to #871

    What I need from the owner: A, B or C, and for B/C whether tier routing may be a label at all. With that, the first implementable issue is small either way (C: manifest + loader + one eval that reads it; B: the step-0 extraction, gated on the mirrors).

  2. added
    area:automationScheduled tasks and automation
    enhancementNew feature or request
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 23, 2026
  3. hsliuustc0106 commented on Oct 24, 2026

    @hsliuustc0106
    ContributorAuthor

    we decide to choose decision B

  4. hsliuustc0106 commented on Oct 24, 2026

    @hsliuustc0106
    ContributorAuthor

    Option B Step 0–2 done on main: #908 (default harness), #933 (Lite/Medium/Heavy), #941 (repo-scoped experience library). No online self-mod / hot-path tier changes. Further harness work = new issues. Closing this RFC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:automationScheduled tasks and automationenhancementNew feature or requestneeds-humanThe agent loop stopped; a person must decide (reason in the last comment)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions