Skip to content

AmsPolicySpec: add selfLoopAutonomy config field (default auto) #6559

Description

@JSONbored

Context

#6060's decided ADR (see that issue's closing comment for the full decision) adds a new .loopover-ams.yml/AmsPolicySpec field, selfLoopAutonomy: AutonomyLevel, gating the iterate-loop's self-directed pass->handoff transition. This issue is the config-schema half only -- get the field parsed, defaulted, and warned-on with zero behavior change to decideNextAction itself. A separate, blocked-on-this issue consumes the field.

AmsPolicySpec (packages/loopover-engine/src/ams-policy-spec.ts:40-54) is the OPERATOR's own local execution-risk policy type for .loopover-ams.yml -- deliberately distinct from .loopover-miner.yml/MinerGoalSpec (packages/loopover-engine/src/miner-goal-spec.ts:9-14), which is the TARGET REPO's own checked-in preferences file. The type's own header (ams-policy-spec.ts:9-13) explains why an autonomy dial belongs here and not there: a target repo's own checked-in file must never get to raise the operator's own risk tolerance against that exact repo. selfLoopAutonomy is exactly that kind of risk-tolerance knob, so it sits alongside submissionMode/capLimits on AmsPolicySpec, resolved operator-locally per ams-policy-spec.ts:15-18.

The AutonomyLevel type ("observe" | "auto_with_approval" | "auto") already exists at packages/loopover-engine/src/types/manifest-deps-types.ts:138, and the level vocabulary is already enumerated as AUTONOMY_LEVELS at packages/loopover-engine/src/settings/autonomy.ts:7. Neither is currently re-exported from the engine's public barrel (packages/loopover-engine/src/index.ts) -- but every OTHER field-specific type on AmsPolicySpec (AmsSubmissionMode, AmsSlopThreshold, AmsCapLimits) IS exported alongside AmsPolicySpec itself in the barrel's existing export block (index.ts:519-529), so AutonomyLevel needs the same treatment for surface consistency.

Requirements

  • Default MUST be "auto", not "observe". This is a deliberate, required deviation from settings/autonomy.ts's own DEFAULT_AUTONOMY_LEVEL = "observe" (settings/autonomy.ts:18). That default is correct for the maintainer auto-maintain dial because it gates a capability with zero prior acting behavior. This field gates behavior that ALREADY happens unconditionally today (a clean self-review pass -> "handoff", iterate-policy.ts:154-156): defaulting to "observe" here would silently change existing behavior for every repo that leaves the field unset. Do not copy settings/autonomy.ts's default.
  • Add selfLoopAutonomy: AutonomyLevel to the AmsPolicySpec type (ams-policy-spec.ts:40-54), importing AutonomyLevel the same way settings/autonomy.ts:1 does: import type { AutonomyLevel } from "./types/manifest-deps-types.js";.
  • Add selfLoopAutonomy: "auto" to DEFAULT_AMS_POLICY_SPEC (ams-policy-spec.ts:67-74) and to cloneDefaultAmsPolicySpec (ams-policy-spec.ts:78-87).
  • Add a normalizeSelfLoopAutonomy(value, fallback, warnings) validator mirroring normalizeSubmissionMode's exact shape (ams-policy-spec.ts:93-98), but validating against the three AUTONOMY_LEVELS values instead of AmsSubmissionMode's two.
  • Wire it into hasConfiguredPolicyFields (ams-policy-spec.ts:159-171: add a spec.selfLoopAutonomy !== DEFAULT_AMS_POLICY_SPEC.selfLoopAutonomy clause) and into parseAmsPolicySpec's field assignment (ams-policy-spec.ts:196-212), same pattern as every existing field.
  • Export type AutonomyLevel from the engine barrel's existing ams-policy-spec.js export block in index.ts:519-529, alongside AmsCapLimits/AmsPolicySpec/etc., for surface consistency with every other AmsPolicySpec field type.
  • No behavior change to decideNextAction/iterate-policy.ts in this issue -- pure config-surface addition. The field is inert until the follow-up consultation issue consumes it.

Deliverables

  • selfLoopAutonomy: AutonomyLevel on AmsPolicySpec, default "auto", threaded through DEFAULT_AMS_POLICY_SPEC/cloneDefaultAmsPolicySpec/hasConfiguredPolicyFields/parseAmsPolicySpec.
  • normalizeSelfLoopAutonomy validator, warning on any value outside AUTONOMY_LEVELS.
  • type AutonomyLevel exported from the engine barrel.

Test Coverage Requirements

Read this before starting. packages/loopover-engine/src/** is measured by Codecov's 99% patch gate ONLY via the ROOT vitest suite (test/**/*.test.ts, per vitest.config.ts's coverage.include and test.include). packages/loopover-engine's OWN test/*.test.ts files run via node --test (its package.json's test script) and are entirely invisible to Codecov. A PR that only adds tests under packages/loopover-engine/test/ will show near-0% patch coverage on this diff and get auto-closed. Update BOTH suites, for different reasons:

  • test/unit/ams-policy-spec-parser.test.ts (root, vitest, imports from ../../packages/loopover-engine/src/index per that file's own existing pattern) -- REQUIRED for Codecov patch coverage.
  • packages/loopover-engine/test/ams-policy-spec-parser.test.ts (package-local, node --test, imports from ../dist/index.js) -- REQUIRED to keep npm run test --workspace @loopover/engine (part of test:ci) green, since it exercises the built output.
  • Cover every new branch: default-omitted ("auto"), each of the 3 valid values accepted with present: true, an invalid string value (falls back to "auto" with a warning mentioning selfLoopAutonomy and the three allowed values), and a non-string value.
  • A regression test asserting parseAmsPolicySpec({}) (or any input with zero configured fields) still returns present: false and spec deep-equal to the full, unmodified DEFAULT_AMS_POLICY_SPEC -- proving hasConfiguredPolicyFields's new clause doesn't false-positive on the default value.

Expected Outcome

.loopover-ams.yml accepts selfLoopAutonomy: observe|auto_with_approval|auto, tolerantly parsed and warned-on like every other AmsPolicySpec field, defaulting to "auto" (today's implicit behavior) when unset. decideNextAction is not yet touched -- a separate issue consumes this field.

Links & Resources

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions