Skip to content

Release: idempotent negotiation turns + standalone moralmod package - #1872

Merged
serefyarar merged 15 commits into
mainfrom
dev
Oct 27, 2026
Merged

serefyarar merged 15 commits into
mainfrom
dev

Conversation

@serefyarar

Copy link
Copy Markdown
Contributor

Promotes dev to main. Carries:

🤖 Generated with Claude Code

serefyarar and others added 15 commits October 27, 2026 08:24
Design for running the Sydney Levine Lab's MoralMod experiment arms
inside the Index negotiation stack: consult as a NegotiateHook, lab
decision-service workers hosted in our infra, clientTurnId idempotency
on turn submission, outcome export, and a staged ramp. Draft pending
approval and the lab's answers to the open contract questions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A retry carrying the same clientTurnId replays the committed turn as
success instead of being refused not_your_turn; a reused id from another
seat or with another payload is refused as raced. No side effects re-fire
on replay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When NegotiateInput carries assessment guidance, the negotiator reads the
private context block, records which assessed option its turn implements
with a divergence kind and reason, and an exact top tie stalls before any
model call. Absent guidance, prompt and tools are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…guard, hook

New private workspace package carrying the ported selection templates and
statistics, assessment-result validation, the verbatim publication guard,
the draft moralmod-consult-0 client, a consult semaphore, and the
NegotiateHook that assesses ON-arm turns, measures shadow-arm turns, and
falls back to the plain negotiator on any consult failure.

Ported pieces come from Sydney-Levine-Lab/decision-studio
custom-negotiator (commit 196153c) with the lab's cooperation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nt hook

The lab cp pushes per-resident arm assignments to
PUT /integrations/moralmod/arms and pulls the outcome export from
GET /integrations/moralmod/outcomes, both behind MORALMOD_CP_TOKEN and
absent (404) without it. The hosted agent consults MoralMod for ON and
shadow arm residents when MORALMOD_ASSESSMENT_URL is set; exposure events
land in opportunity_events and optionally the lab's research relay.
Unconfigured, every path is byte-identical to before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hyperlink "Research Solutions" (researchsolutions.com) and "ARIA"
(aria.org.uk) in Ashish Uppala's bio on the dataroom overview, the
protocol overview, and the static public copy, matching each page's
existing link markup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Link ARIA and Research Solutions in Ashish's bio
…itical path, no principal leakage, trusted exposure counts

- The consult deadline now covers slot waits, the run, and each fetch;
  saturation degrades to the plain negotiator with reason deadline instead
  of blocking turns. The semaphore hands slots off without a window.
- Shadow-arm consults run off the turn's critical path and report duration
  and failure reason, so Stage 0 measures without changing behaviour.
- Stall reasons and suggested questions pass the publication guard before
  the principal reads them; the tie stall uses plain words; the assessed
  prompt forbids naming the assessment to the principal too; an assessed
  run that throws falls back instead of costing the turn.
- moralmod.* event types are reserved server-side, the outcome export
  counts assessed/fallback/shadow apart, arm pushes are transactional and
  report unknown users, the relay payload carries no user/intent ids or
  free-text reasons, an empty assessed menu is invalid rather than a tie,
  and a bad concurrency env value clamps instead of crashing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The embedded integration (packages/moralmod, assessment guidance on the
agent negotiator, arms table and /integrations/moralmod endpoints,
exposure events, hosted-agent wiring, Railway template) is withdrawn.
MoralMod keeps running as the external negotiator for study residents
through the existing executor mechanism; its assessment service scales in
the lab's stack. Index keeps the generic clientTurnId idempotent turn
submission, which is what made lost sends unreconcilable. The design doc
records the decoupling decision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
packages/moralmod returns as a self-contained workspace package: selection
templates, result validation, assessment context, publication guard, draft
consult client, and the NegotiateHook. No service, agent, schema, or
endpoint references it; the runner that executes study residents' turns is
its consumer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…design

Idempotent negotiation turns (clientTurnId) + MoralMod decoupling decision
@serefyarar
serefyarar merged commit 9b4c6c8 into main Oct 27, 2026
21 of 23 checks passed

This branch was previously deployed

1 inactive deployment
Index / dev — 5381e3f0 Deployed Oct 27, 2026 by railway-app[bot]
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