Skip to content

feat(skills): add roster-tuner#200

Open
jdjioe5-cpu wants to merge 1 commit into
runxhq:mainfrom
jdjioe5-cpu:hermes/roster-tuner-positive-path
Open

feat(skills): add roster-tuner#200
jdjioe5-cpu wants to merge 1 commit into
runxhq:mainfrom
jdjioe5-cpu:hermes/roster-tuner-positive-path

Conversation

@jdjioe5-cpu

Copy link
Copy Markdown

What this PR adds

A new roster-tuner graph-runner skill that reads a sealed agency case
event stream through the hosted data-store, folds each member's
refusal rate and completion time, ranks members against
operator-supplied performance norms, and emits a typed roster-tuning
decision naming the bounded member change as plain data. The skill
records the judgment as a case-keyed append and stops; the human
agency operator is the only lane that acts on it, by re-opening the
case with the revised roster.

Skill files

  • skills/roster-tuner/SKILL.md — name, description, category
    ("ops"), procedure, output contract, evidence requirements.
  • skills/roster-tuner/X.yaml — graph-runner skill with two
    inline harness cases:
    • roster-tuner-escalate-sealed: refusal 0.75 + completion 3x
      case mean with blair (editor) crossing both norms and devon
      (editor, 0.10) as the skill-matched replacement. Expects
      status: sealed, receipt.state: sealed with
      decision.underperformer=true, member_to_remove=blair,
      replacement_candidate=devon, refusal.reason=null.
    • roster-tuner-stop-needs-agent: caller.answers omitted; runner
      seals a typed refusal because no member crosses both norms
      before any decision is appended. Expects status: needs_agent.
  • skills/roster-tuner/run.mjs — deterministic Node.js runner
    that refuses when aggregate_id != case_id, schema mismatches,
    or the roster falls below min_roster_size, ranks members
    against the supplied norms, picks a skill-matched replacement
    with strictly lower refusal rate, and emits one decision plus
    one append_event (or a typed refusal).
  • skills/roster-tuner/fixtures/escalate-sealed.json and
    skills/roster-tuner/fixtures/empty-projection-needs-agent.json
    — runner inputs that drive the local smoke harness via
    RUNX_INPUTS_PATH.

Bug fix

The previous draft's pickReplacement compared entry.skill
against target.skill from rankMembers, but rankMembers
only returns {member, refusal, time} — so target.skill was
undefined and every roster entry was filtered out, producing a
typed refusal ("no skill-matched peer remains") even when one was
clearly available. This PR resolves the target's skill from the
roster snapshot itself (targetEntry = roster.find(...)) before
the skill-match search, so the positive path now correctly
identifies devon as the skill-matched replacement for blair.

Local smoke runs (no signing keys, no hosted gate):

RUNX_INPUTS_PATH=skills/roster-tuner/fixtures/escalate-sealed.json \
  node skills/roster-tuner/run.mjs
=> {
     "decision": { "underperformer": true, "member_to_remove": "blair",
                    "replacement_candidate": "devon", "refusal": null },
     "append_event": { "aggregate_id": "case-2026-07-01-marketing-mandate",
                        "expected_version": 4, "idempotency_key": "...-v1" },
     "exit": 0
   }

RUNX_INPUTS_PATH=skills/roster-tuner/fixtures/empty-projection-needs-agent.json \
  node skills/roster-tuner/run.mjs
=> {
     "decision": { "reason": "No member crossed both refusal and
                                completion norms, so the bounded roster
                                change is empty." },
     "append_event": null,
     "refusal": { "reason": "No member crossed both refusal and
                                completion norms..." },
     "exit": 64
   }

Acceptance alignment (Frantic #72)

The Frantic #72 bounty requires:

  • runx CLI 0.6.14 or newer — verified runx-cli 0.6.14 installed.
  • GitHub star on runxhq/runx from the claimant — verified
    jdjioe5-cpu stars the repo.
  • exact package name roster-tuner — package name in
    X.yaml matches.
  • published registry package, PR head commit, source_url,
    x_yaml, skill_md, evidence_json, verification_json, receipt_ref,
    and report all describe the same package version and source
    revision — registry publish step is gated on Boss-side
    runx login --for publish OAuth and will be completed in a
    follow-up commit on this same branch once the OAuth lands.

Out of scope for this PR

  • runx registry publish — needs Boss-side browser OAuth at
    connect.runx.ai. Cloud cannot complete this autonomously.
  • runx add ... / runx skill ... --json dogfood run — depends
    on the published registry listing.
  • Evidence JSON, verification JSON, receipt, and report —
    constructed locally once the registry publish step completes.

Risk

  • No new external dependencies; pure Node.js runner with
    no network, subprocess, or filesystem access.
  • Skill is read-and-judge only — never mutates the roster, never
    re-opens a case, never pages a human, never mints a token or
    executes an attenuation subset proof.
  • Schema version is declared on every case input; the runner
    refuses mismatched or unreadable case events with a typed
    refusal rather than guessing.

Reads a sealed agency case event stream through the hosted data-store
keyed on the case, folds each member's refusal and completion signals
the same way the agency reducer folds case state, ranks members
against operator-supplied performance norms, and emits a typed
roster-tuning decision naming the bounded member change as plain data.

Includes deterministic run.mjs with two harness cases:
  - roster-tuner-escalate-sealed: refusal 0.75 + completion 3x case
    mean with editor/blair crossed both norms and devon (editor,
    0.10) replaces. decision.underperformer=true, member_to_remove=
    blair, replacement_candidate=devon, refusal.reason=null.
  - roster-tuner-stop-needs-agent: caller.answers omitted; runner
    seals typed refusal because no member crosses both norms before
    any decision is appended.

Fixes target.skill resolution in pickReplacement so the bounded swap
search resolves the target's skill from the roster snapshot itself
rather than relying on rankMembers to carry it.

Bounty: Frantic runxhq#72 (runx skill: roster tuner, 0 USD, x402 payout
to canonical Base/EVM address). Live at
https://gofrantic.com/bounties/p-bab1702abb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant