# Rubbing Research Orchestrator

> Orchestrate provenance-first research on rubbings, steles, inscriptions, and related historical sources. Use when Codex must initialize a ResearchCase, split an epigraphy question into auditable stages, route work across independent Skills or Agents, react to positive/negative/null/invalid results, enforce research gates, or decide whether to continue, reroute, request human review, stop unresolved, or package a study.

- Skill: `lx050/rubbing-research-orchestrator` (Agent Skill, multi-file: 26 files)
- Install (CLI): `npx skillmds@latest add lx050/rubbing-research-orchestrator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lx050/rubbing-research-orchestrator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Lx050 (https://skillmd.com/u/lx050)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lx050/rubbing-research-orchestrator

---


# Rubbing Research Orchestrator

Manage research state and routing. Do not perform OCR, image restoration, source interpretation, or historical fact generation inside this Skill.

Current contract identity: `rubbing-research-orchestrator` version `1.4.0`.
Current route and record-event Schema version: `1.3`. Preserve the immutable
1.1/Skill-1.2.3 and 1.2/Skill-1.3.0 Schema files only for historical
validation; documents written under them keep validating unchanged.

The additive `question-plan-v1` contract is advisory and provider-neutral. It
does not change route 1.3, select a third-party Skill, admit evidence, or
authorize historical publication.

The router accepts ReflectionMemo schema `1.0` or `1.1` from current
`research-hypothesis-reflection` `1.2.0` and, for read-only historical routing
compatibility, `1.1.0` and `1.0.0`. Every version must bind the same case ID
and the exact current ResearchCase bytes, and must prove that the input was not
overwritten. Reject every unknown or missing Reflection Skill version. A memo
bound to the case before reflection is stale after an updated case is emitted
and must not be reused against that updated case.

## Plan the question profile

Before assembling a workflow, classify what the question actually requires:

```bash
python3 scripts/orchestrate.py plan-question \
  --question "What differs between two precisely located carrier readings?" \
  --profile carrier-comparison \
  --output work/question-plan.json
```

Profiles are `carrier-comparison`, `image-reading`, and
`historical-inference`. Every plan has the same ordered stage matrix, and every
stage status is exactly `required`, `optional`, `not_required`, or `blocked`.
The output binds each stage to a provider-neutral contract rather than a
specific external component:

- `carrier-comparison` requires source acquisition, provenance, precise
  location, deterministic comparison, team review, and a dossier. Image
  preparation and OCR are optional; a historical entity graph and publication
  gate are not required.
- `image-reading` requires image preparation, OCR, precise location, and team
  review. Literature and historical graph work remain optional.
- `historical-inference` requires literature evidence, trusted external
  authentication, and the historical publication gate. Missing declarations
  produce typed `blocked` stages and a blocked plan.

`--available-capability` is a caller assertion that an independently verified
capability contract is available. A catalog/search match, provider confidence,
or component description does not satisfy it. Repeat the flag only after the
caller has verified the relevant contract:

The host-level candidate-role and blocking registry for optional external
Skills/SCPs is `references/external-capability-registry-v1.json`; registry
membership never populates `available_capabilities`.

```bash
python3 scripts/orchestrate.py plan-question \
  --question "What historical appointment can the sources establish?" \
  --profile historical-inference \
  --available-capability literature-evidence \
  --available-capability trusted-external-authentication \
  --available-capability historical-publication-gate
```

Even an actionable plan keeps `publication_authorization: false`; normal
evidence and publication gates still decide what may proceed. Read
[references/question-plan-v1.schema.json](references/question-plan-v1.schema.json)
and [references/orchestration-policy.md](references/orchestration-policy.md)
before consuming the matrix.

## Build the edition-record evidence layer

[`scripts/edition_evidence.py`](scripts/edition_evidence.py) is the shared P0
contract for evidence that says only what fixed carriers attest. It defines and
validates:

- `candidate-envelope-v1`;
- `edition-evidence-case-v1`;
- `edition-evidence-graph-v1`, limited to `attested-at`, `differs-from`,
  `derived-from`, `reviewed-by`, and `left-unresolved-by`;
- `case-dossier-v1`.

The graph cannot contain a raw provider candidate, `same-as` edge, historical
fact, or publication authority. A carrier difference remains `unresolved` with
no preferred reading. Inspect the complete stdlib CLI with:

```bash
python3 scripts/edition_evidence.py --help
```

The optional service in [`scp/`](scp/) exposes this layer through six tools:
`create_case`, `submit_source_candidates`, `register_artifact`,
`submit_observations`, `compare_located_readings`, and
`export_case_dossier`. Its private `case.json` is workspace state, while export
always writes the three public P0 objects through the shared validators.
FastMCP and Streamable HTTP are optional transport dependencies; the core
service remains offline and stdlib-only. See [`scp/README.md`](scp/README.md).

## Compose external Skills and SCPs at the host

External components remain separate providers selected by the project-space
host Agent. Sciverse SCP 43 has a local adapter that emits bibliographic
CandidateEnvelope objects; it never writes the evidence graph directly.
Other catalog Skills are host-composition or manual-advisory options until
their licenses and machine contracts are reviewed. The current allowed roles,
blockers, and observed platform metadata are frozen in
[`references/external-capability-registry-v1.json`](references/external-capability-registry-v1.json).

## Start a case

1. Rewrite the research intent as a falsifiable question.
2. Record at least one falsification condition and one stop condition.
3. Create a new case directory:

```bash
python3 scripts/orchestrate.py init \
  --case-dir work/SYNTHETIC-CASE-001 \
  --case-id SYNTHETIC-CASE-001 \
  --question "Does the named person have the proposed relationship?" \
  --scope "Declared material and cited sources only" \
  --falsification-condition "A verified independent source makes the relationship impossible" \
  --stop-condition "Two independent located sources agree, or the conflict remains unresolved"
```

Never reuse an existing case directory. Preserve every previous case and event.

## Intake first (standing policy, owen 2026-07-27)

Before `init`, a multi-source funnel intake batch must exist for this line of
inquiry: run the `research-source-acquisition` Skill in its default
**funnel-intake** mode (its `funnel_intake` engine, not a script in this Skill),
then register that batch's `batch-manifest.json` absolute path and SHA-256 as the
case's first material. The intake's
`intake-receipt.json` carries `meets_multi_source_floor`, which is
attempted-and-logged (not success-required): failures are recorded, not hidden.
See [references/intake-first-policy.md](references/intake-first-policy.md).

This is a runtime/operational policy, not a ResearchCase schema change: the
router does not machine-enforce it at `init`, and the existing `init` and route
1.3 behavior remains unchanged. The enforceable handle is the funnel's receipt
plus the screening/audit stage that reads the first material — described
honestly rather than pretended to be a router gate.

## Presentation last (standing policy, owen 2026-07-27)

The dual of intake-first: intake binds the entrance, this binds the exit. Before a
presentation-layer artifact (`knowledge-visualisation.html`, a feature deck /
`submission.pptx`, any judge/public-facing chart page) is produced or rebuilt, the
session must load `anthropic-skills:canvas-design` + `dataviz`, write or cite a
visual-philosophy doc **before** touching the canvas (no philosophy doc, no work),
implement, then run a mandatory second polish pass (no new elements, only refine),
and attach the philosophy reference plus a polish record. The machine-checkable
half lives in the presentation builder's `COVENANT_CHECKS` group and its
`self_check_design_philosophy_present`, not in the frozen router.
See [references/presentation-last-policy.md](references/presentation-last-policy.md).

## Record a state transition

Create one JSON object for the next material, hypothesis, evidence, experiment, feedback, claim, uncertainty, or decision. Append it to a new case version:

```bash
python3 scripts/orchestrate.py record \
  --case work/CASE/case-v001.json \
  --collection materials \
  --record work/CASE/records/material-001.json \
  --output-case work/CASE/case-v002.json \
  --output-event work/CASE/events/0002-materials.recorded.json
```

Use `materials`, `hypotheses`, `evidence`, `experiments`, `feedback`, `claims`, `uncertainties`, or `decisions`. The command validates required fields and links, refuses duplicate IDs and existing outputs, preserves both inputs, records before/after hashes, and recalculates the recommended stage and gate. Never hand-edit an existing case version.

A `human_review`, `stop_unresolved`, or `rollback` decision remains blocking
until a later typed decision explicitly names it in
`resolves_decision_id`. A `complete` decision must name an exact registered
`stop_condition`, cite at least two eligible evidence items from two
independence groups, and include a structured per-evidence adjudication.
Completion still requires an integrity audit bound to the exact current case
bytes.

Every case with a persisted decision must carry
`extensions.latest_decision_state` with exactly `decision_id`,
`decision_sha256`, `input_case_sha256`, `activated_at`, and
`collection_counts`. Reject missing markers, malformed fields, and a marker
whose decision ID or canonical decision hash does not match the latest
decision. The timestamp and collection counts are an activation snapshot:
after a valid append they may be well-formed but stale. Staleness deactivates
`continue` and `complete`, but does not silently clear a persisted
`human_review`, `stop_unresolved`, or `rollback` block. Record a later typed
decision to resolve such a block and refresh the snapshot.

This marker is a runtime consumer contract only. ResearchCase schema `1.0`
does not express it, so the P2 contract-versioning gap remains unresolved; do
not describe this repair as complete ResearchCase schema versioning.

Check an exchanged case before routing:

```bash
python3 scripts/orchestrate.py validate --case work/CASE/case-v002.json
```

Treat this as core-and-ID validation. Use the complete project JSON Schema when available.

## Route the next action

Run the router after every material registration, experiment, feedback event, reflection, or integrity audit:

```bash
python3 scripts/orchestrate.py route \
  --case work/SYNTHETIC-CASE-001/research-case.json \
  --audit work/SYNTHETIC-CASE-001/audit.json \
  --reflection work/SYNTHETIC-CASE-001/reflection.json \
  --output work/SYNTHETIC-CASE-001/routes/route-002.json
```

Omit unavailable optional inputs. Treat the emitted route as a proposal; let the named Skill produce evidence before changing a research claim.

When `proposed_skills` names `epigraphy-text-structure`, inspect its
machine-readable entry in `handoff_gates`. The router keeps that Skill out of
the backward-compatible executable `next_skills` list while either the typed
`transcription_qualification_gate` or `physical_reading_order_gate` is
blocked. Do not initialize structure state until an
`epigraphy-transcription-evidence` object independently proves qualified
transcription intake, complete physical-region assignments, continuous reading
order, and per-token locators. Never synthesize that order by sorting OCR
coordinates, voting across image variants, or treating OCR confidence as
transcription truth.

The current router does not accept the downstream evidence object, so both
text gates remain blocked here and the text Skill is only proposed. Its own
intake verifier is the next fail-closed boundary.

`research-literature-evidence` is executable only inside the capability fence
declared by its `handoff_gates` entry and only under
`execution_profile: real-research-audit-v1`: plan, query, discovery, bounded
outcome, and real L0/L1 source-candidate logging. The required downstream input
is a verified-route-bound ResearchCase and literature plan. This pass is
permission to enter that audit lane, not evidence admission. Real
L2/carrier/locator/card/L4, trusted-human, public, ResearchCase `SRC`, and
text-structure authority capabilities remain blocked, and the handoff is never
eligible as completion evidence. When text and literature are proposed
together, only literature may appear in `next_skills`; the aggregate handoff
remains blocked by the text gates.

## Never stop without naming the next research action

A `human_review` or `stop_unresolved` route keeps `next_skills` empty: nothing
may be chained automatically past a human gate. It must still say what to do
next. Such a route names its proposals in `proposed_skills`, gives each one a
proposal-only entry in `handoff_gates` (`executable: false`), and explains the
target in `actions` and `reasons` using content read out of the bound case:

- unadjudicated Han character candidates found in usable, non-`HYP` evidence
  are named with their code points, together with the evidence IDs that record
  them, and `research-literature-evidence` is proposed to look them up;
- when a raw image material is still registered,
  `rubbing-image-preparation` is proposed so a wider region can be re-derived
  without disturbing the existing observations;
- when no character candidate exists, the open question text and the affected
  hypothesis IDs are named instead.

Treat those proposals as research suggestions for the human reviewer. They are
not permission to act; only `next_skills` authorizes execution, and a route
that stops for a human never fills it.

Supply `--created-at` only as a timezone-aware RFC3339 timestamp. A successful
`verify-route` report proves that policy fields were recomputed against bound
inputs whose digests were safely rechecked immediately before success. It does
not authenticate the route's claimed generation time, `route_id`, or `run_id`;
use an external signed checkpoint or append-only run ledger for those claims.

## Apply the gates

- Route missing, unverified, blocked, or rights-unknown materials to provenance work.
- Route missing hypotheses, negative/null/invalid feedback, challenged hypotheses, or conflicting evidence to reflection.
- Detect a hypothesis-level conflict when usable evidence both supports and challenges it, even if no feedback row summarizes the conflict.
- Route claims without an audit to integrity audit.
- Prevent packaging while an audit is `block`.
- Require human review while an audit is `warn` on a high-impact or conflicted claim.
- Stop automated Skill routing when a ReflectionMemo requests `human_review` or `stop_unresolved`.
- Mark complete only when a fresh typed decision proves the registered stop
  condition with eligible independent evidence and an audit for the exact
  current case bytes is `pass`.
- Prefer `stop_unresolved` over invented certainty.

Read [references/orchestration-policy.md](references/orchestration-policy.md)
before changing routing rules. Read
[references/route-handoff-contract.md](references/route-handoff-contract.md)
before consuming a route or upgrading a legacy route. Read
[references/research-case-contract.md](references/research-case-contract.md)
when another Skill needs to exchange ResearchCase objects.

## Coordinate Agents

Give each Agent a bounded task, a dedicated output path, the case path, the relevant Skill, and an explicit validation command. Require the Agent to write inputs, methods, raw outputs, failures, uncertainty, and handoff notes to disk. Merge only persisted artifacts; treat chat messages as coordination signals, not research evidence.

## Preserve research integrity

Keep raw evidence immutable. Keep generated restoration as `HYP`. Keep negative and failed results. Require coordinate- or page-level locators for publishable evidence. Never upgrade a claim from a route decision alone.

