Skip to content

contract: pin the four unpinned engine/miner enum restatements and stop re-inlining #9660

Description

@JSONbored

⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.

Context

@loopover/contract is a zod-only leaf: it cannot import src/, the engine, or the miner package,
so a handful of vocabularies are deliberately restated there and pinned by meta-test against
their live source. test/unit/contract-registry.test.ts:223-284 does this for AUTONOMY_LEVELS,
MAINTAIN_ACTION_CLASSES, PROPOSE_ACTION_CLASSES, PUBLIC_SURFACE_SKIP_REASONS,
PREFLIGHT_LIMITS, SCENARIO_LIMITS and PLAN_STEP_STATUSES. enums.ts:1-18 explains why: the
hand-copies this package replaced had drifted before, and "the drift this invites is real and has
bitten once already".

Four restatements have no pin:

contract live source consequence of drift
TEST_FRAMEWORKS (src/enums.ts:50) packages/loopover-engine/src/signals/test-evidence.ts:126 a framework the engine recognises is rejected by the tool's input schema
QUEUE_STATUSES (src/tools/miner.ts:17) packages/loopover-miner/lib/portfolio-queue.ts:88 MinerManageStatusOutput.rows[].queueStatus (miner.ts:99) rejects a real row
CLAIM_STATUSES (src/tools/miner.ts:20) packages/loopover-miner/lib/claim-ledger.ts:91 MinerListClaimsInput.status (miner.ts:136) rejects a filter the ledger accepts
MINER_RUN_STATES (src/tools/miner.ts:208) RunState in packages/loopover-miner/lib/run-state.ts:8 MinerGetRunStateOutput.state / .states[].state (miner.ts:220-221) rejects a real persisted state

The three miner ones are worse than the engine one because they sit in tools/miner.ts rather than
enums.ts, so they escape even the convention that shared vocabularies live in enums.ts, and two of
them are used in output schemas — a new run state or queue status makes the tool's real
structuredContent fail the schema the same tool advertises. validate:mcp only notices if the cold
fixture environment happens to produce the new value.

Separately, FEASIBILITY_VERDICTS (enums.ts:68) already exists and is imported correctly at
packages/loopover-contract/src/tools/local-branch.ts:27, :324 — but the identical literal is
re-inlined at packages/loopover-contract/src/tools/agent.ts:48 and :67, inside the very package
whose stated purpose is eliminating hand-copies, and again at src/openapi/schemas.ts:2392 and
:2427.

Requirements

  1. TEST_FRAMEWORKS, and the three miner vocabularies moved out of tools/miner.ts into
    packages/loopover-contract/src/enums.ts (where every other shared vocabulary lives), each gain a
    pin in test/unit/contract-registry.test.ts's "contract enums" block, asserting array equality
    against the live source module — the same shape as the existing PUBLIC_SURFACE_SKIP_REASONS pin
    at :250-254.
  2. Each pin imports the live source directly (packages/loopover-engine/src/signals/test-evidence,
    packages/loopover-miner/lib/portfolio-queue, packages/loopover-miner/lib/claim-ledger,
    packages/loopover-miner/lib/run-state) exactly as the existing pins import
    packages/loopover-engine/src/settings/autonomy and src/scenarios/input-model. RunState is a
    type union, so the pin needs a runtime array in run-state.ts to compare against — export one
    (RUN_STATES, constrained with satisfies readonly RunState[]) rather than hand-listing the
    members in the test.
  3. agent.ts:48 and :67 import FEASIBILITY_VERDICTS from ../enums.js;
    src/openapi/schemas.ts:2392 and :2427 import it from @loopover/contract. No inline
    go/raise/avoid enum literal remains in src/ or packages/.
  4. Each moved constant keeps its exported name and is re-exported from
    packages/loopover-contract/src/tools/miner.ts so no downstream import path breaks.

⚠️ Required pattern: test/unit/contract-registry.test.ts:250-254 (the
PUBLIC_SURFACE_SKIP_REASONS pin) and :256-261 (the PREFLIGHT_LIMITS pin) — a direct import of
the live module and an array/object equality assertion. Asserting only that the contract's list is a
subset of the live one, asserting a hardcoded expected array in the test instead of importing the
source, or leaving the three miner vocabularies in tools/miner.ts, do NOT satisfy this issue.

Deliverables

  • QUEUE_STATUSES, CLAIM_STATUSES and MINER_RUN_STATES live in
    packages/loopover-contract/src/enums.ts and are re-exported from tools/miner.ts
  • RUN_STATES exported from packages/loopover-miner/lib/run-state.ts as a runtime array
    constrained by satisfies readonly RunState[]
  • Four new pins in test/unit/contract-registry.test.ts (TEST_FRAMEWORKS, QUEUE_STATUSES,
    CLAIM_STATUSES, MINER_RUN_STATES), each asserting equality against the imported live source
  • No inline go/raise/avoid enum literal remains under src/ or packages/; agent.ts and
    src/openapi/schemas.ts import FEASIBILITY_VERDICTS
  • npm run typecheck and npm run validate:mcp green with no schema shape change

All Deliverables above are required in a single PR. A PR that satisfies only some of them — for
example adding the four pins while leaving the miner vocabularies in tools/miner.ts and the
feasibility-verdict literals in place — does not resolve this issue.

Test Coverage Requirements

99%+ Codecov patch coverage, branch-counted, applies: packages/loopover-contract/src/**,
packages/loopover-miner/lib/** and src/** are all in coverage.include
(vitest.config.ts:55-100). The new RUN_STATES export needs a test; every changed z.enum(...)
needs an accept case and a reject case so the branch counts, and the four pins themselves are the
regression tests for the drift.

Expected Outcome

Every vocabulary @loopover/contract restates is mechanically pinned to its live source, so adding a
run state, queue status, claim status or test framework on one side fails CI instead of producing a
tool whose advertised output schema rejects its own real payload; and FEASIBILITY_VERDICTS has one
definition and no copies.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions