Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Stage E: per-injection human-approval gate; reject --yes on hardware; fix _confirm(twin=True)

Open
#17 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
52/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Quiet
Tech stack
python
Domain
backend, cli

Research direction

Start with the CDSBackend inject/read path and the Stage A fakes described in the acceptance criteria, then inspect src/system_ident/cli.py and src/system_ident/backends/base.py. Confirm that each injection requires a single-use approval, denied approvals prevent construction or start, EOFError denies by default, and hardware rejects --yes with exit 2.

Written by the indexing model from the issue text.

Description

enhancement

Stage E (spec §1, §5). Enforce in code the hardware-safety rules now in
CLAUDE.md: only humans authorize the hardware, and each individual injection needs separate
approval — one approval never carries over
.

The sibling project enforces neither in code — no input(), no --confirm, no dry-run on its hardware
path; the rules are documentation-only there. This repo should do better, because it already has most of
the machinery.

The gate goes inside CDSBackend.inject()

It is the only code path from any caller to the actuator, and the only place holding the actual samples.

Rejected alternatives, and why:

  • A Watchdog pre-injection hook or a loop.py change is a convention, not an invariant: any script,
    notebook or test that constructs the backend and calls inject() directly bypasses it entirely. It also
    makes SysIDLoop backend-aware, contradicting src/system_ident/backends/base.py:3 ("the loop and
    the safety handoff use only these methods, so simulation and hardware are truly interchangeable"), and
    the watchdog has no access to the drive array so it cannot show the operator what is about to happen.
  • A decorator or mixin has the same bypass risk unless applied at class level, at which point it is
    the inject-internal gate with extra indirection.
Approval is a single-use token

Staging and actuation are now separate (inject() stages, read() executes), so approval granted at
inject() is for an actuation that happens later:

  • inject() prompts — printing channel, hardware rate, duration, RMS, peak and crest, and the
    start_gps window — then mints _approval[channel].
  • read() refuses to start any staged injection whose token is missing or consumed; consumes it on
    start.
  • Re-reads of an already-running injection do not re-prompt: nothing new is actuated. A new inject()
    mints a new token. That is Rule 2 exactly.
  • The prompt is injectable (authorizer=) for testability, and defaults to deny on EOFError /
    non-TTY. Never proceed in batch.
Fix the existing CLI gate
  • src/system_ident/cli.py:89 calls _confirm(twin=True) unconditionally, so the "HARDWARE"
    label at src/system_ident/cli.py:129 is dead code and a hardware run would announce itself as a
    twin run → _confirm(twin=args.twin or args.rtsfreerun).
  • --yes (src/system_ident/cli.py:45) is a campaign-wide skip, i.e. by definition a carry-over
    approval, which Rule 2 forbids → reject it at argparse level (exit 2) when neither --twin nor
    --rtsfreerun is given. The CLI prompt then becomes a pre-flight; the gate is the token.
Acceptance — tests that assert it cannot be skipped

All on the Stage A fakes:

  1. Denying authorizer → raises, and FakeArbitraryLoop was never constructed (assert the construction
    counter, not .start).
  2. Authorizer called exactly twice for two inject() calls; exactly once for one inject() + three
    read()s.
  3. read() with a staged-but-unapproved injection → raises, .start never called.
  4. Default authorizer with input raising EOFError → denies.
  5. main(["run", cfg, "--yes"]) without --twin → exit 2.

Campaign: CDS hardware backend · branch feat/cds-hardware-backend
· spec · plan · handoff
Code is deferred until the plan and issues have been reviewed.

Dominant language
Python
Stars
0
Forks
1
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from CaltechExperimentalGravity/system_ident

All issues in CaltechExperimentalGravity/system_ident

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.