Skip to content

Latest commit

 

History

History
318 lines (257 loc) · 17 KB

File metadata and controls

318 lines (257 loc) · 17 KB

Development support tools

This directory contains both automatic readiness gates and intentionally opt-in support tools. A script is not an automatic PR gate merely because it lives under scripts/dev/; use the invocation surface documented below as the source of truth.

Task index

Fast finder for the most common contributor tasks. Each entry names the maintained entry point; run uv run python scripts/dev/<script>.py --help (shell helpers: scripts/dev/<script>.sh --help) for flags and exit codes.

I want to... Use
Check whether my branch is ready for a PR pr_ready_check.sh (see Required readiness gates)
Format and lint my changes ruff_fix_format.sh
Run the test suite run_tests_parallel.sh, run_focused_tests.sh, run_ci_local.sh
Run a bounded command without flooding the terminal run_compact_validation.py
Count collected tests for validation metadata pytest_collect_count.py
Create a linked worktree for isolated work create_worktree.sh
Restore files without losing uncommitted work safe_checkout.sh
Reuse the main checkout environment in a worktree run_worktree_shared_venv.sh
Check worktree disk capacity or reclaim space check_worktree_capacity.py
Diagnose a worktree or stale CI state worktree_hygiene_snapshot.py, recover_stale_ci_run.py, diagnose_actions_job.py
Check CI status for a PR check_pr_ci_status.py, watch_pr_ci_status.py, compact_ci_snapshot.py
Post a Markdown-heavy GitHub comment or review gh_comment.sh, gh_pr_review_rest.py
Reconcile a PR title/body after a fix push gh_pr_body_rest.py
Read issue or PR state without deprecated GraphQL fields gh_issue_rest.py, gh_issue_view.sh, snapshot_issue_batch.py, snapshot_pr_queue.py
Claim an issue for cross-machine agent work issue_claim.py
Audit what the scripts catalog tracks check_scripts_catalog.py, scripts_catalog.py
Regenerate generated docs surfaces render_scripts_readme.py, generate_cli_reference.py, generate_environment_config_reference.py, generate_skills_readme.py, generate_quickstart_notebooks.py
Check documentation link and evidence integrity check_curated_doc_links.py, check_docs_evidence_integrity.py, check_context_notes.sh
Run docstring TODO ratchets check_docstring_todos_ratchet.sh, check_docstring_todos_diff.sh
Audit code-size, assert, config-family, or helper drift audit_function_lengths.py, audit_production_asserts.py, audit_config_families.py, audit_validation_helpers.py
Run an offline smoke of the local workflow run_offline_smoke.py
Check optional dependencies without importing project code check_worktree_optional_deps.py

Full narrative contracts for the numbered sections below cover the tools that need more explanation than a table row.

Required readiness gates

BASE_REF=origin/main scripts/dev/pr_ready_check.sh is the local readiness entry point for ordinary PR work. CI workflows and the documented PR process own the required checks that run for every applicable change.

If readiness receives a termination signal, it preserves a private, bounded receipt under output/validation/pr_ready/ with the active phase, lane, process-group cleanup result, and small host/cgroup resource snapshot. Set PR_READY_TERMINATION_RECEIPT=/absolute/path/receipt.json when a caller needs a stable handoff path. The receipt never includes the command line or environment, and readiness still returns the conventional signal status (143 for SIGTERM, the termination signal).

When quoting readiness counts, use the named selectors in docs/dev/local_ci.md, including --collect-only -q when only the collected count is needed.

pr_ready_artifact_contract.py validates and reconciles machine-readable readiness receipts with an optional human summary and command log. It emits JSON from byte zero and exits non-zero when artifacts are malformed, terminated, interim, unavailable, or inconsistent:

python scripts/dev/pr_ready_artifact_contract.py \
  --machine-json <readiness.json> \
  [--human-summary RESULT.md] [--command-log readiness.log]

check_base_drift.py backs the readiness gate's base-drift recheck (issue #5782). The gate captures the concrete base SHA before the expensive lanes and invokes this check immediately before recording the stamp, so it can tell whether origin/main moved during the run. Drift that touches none of the PR's changed files recommends reuse; drift that intersects them requires revalidation. One regenerable exception exists: when the intersection is exactly scripts/validation/docstring_todo_baseline.json, the gate re-runs the targeted docstring baseline and ratchet gates and, only on success, revalidates through that narrow path with a recorded baseline_revalidation receipt; mixed drift stays fail-closed. The checker exits 0 when the base is current or the drift is reusable, 1 when revalidation is required, and 2 when the base ref or drift cannot be resolved.

The native merge queue enforcement path is merge_queue_gate.py, invoked by .github/workflows/merge-queue-gate.yml on merge_group. The standalone protection audit below does not replace that workflow or change branch protection.

Agent instruction and skill checks

  • check_instruction_references.py validates the agent instruction graph: the single task-route owner, the Instruction Precedence block, the execution-profile manifest, the maintainer-values drift rule, and repository-local reference resolution. Run uv run python scripts/dev/check_instruction_references.py [--json].
  • check_skills.py validates the repo-local skill registry and runs a skill preflight; use --preflight <skill> before relying on a skill's declared requirements.
  • scripts/tools/sync_ai_config.py --check keeps provider adapters thin, scoped, and linked to canonical sources (see .agents/README.md).
  • check_agent_instructions.sh composes the three checks above into one entry point for instruction-contract changes; run scripts/dev/check_agent_instructions.sh (optional --json). It is also available as the VS Code task Agent Instruction Checks.

These are contract checks for repository instructions, not PR merge gates; pr_ready_check.sh remains the required readiness entry point.

Explicit issue-scoped verification

check_pr_closing_reference.py verifies that GitHub's GraphQL closingIssuesReferences for a specific PR contains an issue number supplied by an already authorized work packet. It must not infer the expected issue from PR prose.

uv run python scripts/dev/check_pr_closing_reference.py \
  <pr-number> <expected-issue-number> --repo ll7/robot_sf_ll7

Add --json for the machine-readable result. Exit status is 0 when the expected issue is present, 1 when it is absent, and 2 when the result is unavailable or the input is invalid. The command is read-only; it does not edit PR bodies, labels, issues, or branches. Because it queries GitHub, an API failure is an unknown result and must remain a blocker.

Repository-administration audits

check_merge_queue_protection.py is a read-only audit for the maintainer-owned merge-queue activation dimensions from issue #6404. Run its deterministic offline contract test with:

uv run python scripts/dev/check_merge_queue_protection.py --self-test

After a maintainer changes branch/ruleset settings, run the live audit with:

uv run python scripts/dev/check_merge_queue_protection.py \
  --check --repo ll7/robot_sf_ll7 [--pr <enqueued-pr-number>]

--pr is optional and is only meaningful for a PR that is actually enqueued; it probes the live ALLGREEN strategy. The audit fails closed when a required dimension is unsatisfied or unverifiable. It performs no ruleset, branch, queue, PR, issue, or workflow mutation, and it cannot claim that a real merge_group run exists unless GitHub provides that evidence.

prune_stale_remote_branches.py is the dry-run-first sweep for stale remote heads (issue #9087). It deletes only two safe classes: merged_code_branch (tip already an ancestor of origin/main with no open PR) and claim_ref_closed_issue (agent-claims/issue-<n> whose issue is closed). Everything else is kept, including protected refs, open-PR heads, claims whose issue is open or unresolved, and any ref whose state cannot be determined. Run a scan (no deletion) at a cadence of roughly once a month or after a large campaign:

uv run python scripts/dev/prune_stale_remote_branches.py --report /tmp/prune.json

Apply is explicit and bounded; rerunning is idempotent because deleted refs no longer classify:

uv run python scripts/dev/prune_stale_remote_branches.py --apply --limit 25 --report /tmp/prune.json

CI inline-logic helpers

The CI aggregate workflow extracts its reusable executable logic into tested helpers (issue #7666):

  • model_cache_key.py derives the exact-repeat model-cache key from registry-pinned digests:

    uv run python scripts/dev/model_cache_key.py --config <ppo-config.yaml> --machine
  • merge_test_durations.py validates and merges the four pytest-split duration shard stores:

    uv run python scripts/dev/merge_test_durations.py \
      --artifact-dir .duration-artifacts --output .test_durations
  • check_ci_needs.py evaluates the aggregate job's required needs results with event-specific coverage rules:

    uv run python scripts/dev/check_ci_needs.py --event-name pull_request --results '{"fast-feedback": "success"}'

Focused tests live in tests/dev/test_ci_helpers.py; the workflow-contract parity checks live in tests/test_ci_script_contract.py.

Open-issue goal-autopilot preparation

prepare_open_issue_contracts.py consumes the report-only open_issue_contract_audit.v1 output from audit_open_issue_contracts.py and emits per-issue goal-autopilot preparation packets (issue #7929). Plan, render, and verify modes are report-only; apply requires an explicit reviewed plan and a bounded, CAS-guarded batch. Real apply additionally requires the exact selected issue list and its content_sha256 passed as --reviewed-plan-digest.

uv run python -m scripts.dev.prepare_open_issue_contracts \
  --audit-json /tmp/open_issue_audit.json \
  --plan-json /tmp/open_issue_preparation_plan.json \
  --batch-id <stable-batch-id>

See docs/ai/open-issue-contract-preparation.md for the operator contract. Focused offline tests live in tests/dev/test_prepare_open_issue_contracts.py.

ready_triage_reconcile.py repairs the contradictory state:ready + needs-triage pair on open issues (issue #9012): report mode derives one evidence-backed action per issue from its classification with the triage label ignored, and apply mode performs only the planned label removal with a per-issue drift check. It never closes issues, merges pull requests, or edits Project #5 state.

uv run python scripts/dev/ready_triage_reconcile.py --json
uv run python scripts/dev/ready_triage_reconcile.py --apply --json

Focused offline tests live in tests/dev/test_ready_triage_reconcile.py.

Parent goal-autopilot arbitration

goal_autopilot_controller.py is the machine-checked parent arbiter for the continuous implement/review/merge/ discover loop. Child workers may report only lane-local exhaustion, such as implementation_queue_exhausted; only the parent can emit genuine_zero_work. A terminal result includes a fresh goal_autopilot_zero_work_proof.v1 receipt bound to the origin/main SHA, issue/claim state, PR heads, preparation audit, and discovery inputs.

uv run python scripts/dev/goal_autopilot_controller.py \
  --snapshot /tmp/goal_autopilot_controller_snapshot.json --json

The arbiter routes merge, review, recovery, implementation, readiness-gate, formalization, and discovery work before considering a terminal result. Focused regression coverage lives in tests/dev/test_goal_autopilot_controller.py.

Classification rule

  • Required automatic enforcement belongs in an explicit workflow or readiness entry point and must have a corresponding contract test.
  • Issue-scoped verification requires explicit authoritative arguments and is run only from the relevant work packet.
  • Repository-administration audits are read-only evidence collectors; they do not become merge gates by implication.

Delegated-worker worktree guard

worktree_receipt.py is the opt-in pre-write boundary for repository-owned delegated workers. Pair create_worktree.sh --receipt PATH --task-id ID with --exec; creation writes an atomic receipt and checks it before launching the command. The check is read-only, fail-closed, and machine-readable. It validates the current working directory, assigned absolute worktree, linked Git common directory, branch/ref, and base ancestry. Human callers that omit receipt options retain the ordinary path.

Receipts may additionally declare the issue's path scope with repeated --allowed-path GLOB (recorded at creation, enforced at check time). With a scope declared, check also rejects cross-scope changes before commit/push or at the handoff boundary: branch commits on the first-parent line touching paths outside the scope (intentional current-main merge commits are exempt) and staged or untracked paths outside the scope. Without a scope the check keeps its identity-only behavior, so existing receipts and human callers are unaffected (issue #9115).

Protected review-worktree guard

Use create_worktree.sh --mode review for review-only or synthetic-integration work. It installs the worktree-local push guard, inert push destinations, and push-only URL rewrites; review_worktree_guard.py integrate then performs an aborting no-commit merge, restores ORIG_HEAD, and compares all remote refs before returning success. Review mode separates push rejection from read operations, keeping direct git fetch and git ls-remote commands operational. If the selected base predates the guard files, the creator temporarily uses the invoking checkout's tracked hook and guard; keep that checkout available for the review worktree's lifetime. The barriers cover ordinary Git invocation paths, but are not an operating-system sandbox: a deliberate per-command Git configuration override can bypass them. In particular, a remote added after activation with an explicit remote.<name>.pushurl remains protected by the ordinary hook path, while a deliberate --no-verify bypass must use the stronger process boundary described below.

Review setup never edits the shared config to mask url.*.pushInsteadOf entries. If an effective repository, global, system, or pre-existing worktree alias could outrank the worktree push barrier, setup fails closed before enabling review mode; remove or relocate the alias and retry. A guard-specific lock would not serialize arbitrary Git processes in other linked worktrees. Read-side url.*.insteadOf rewrites remain enabled for safe configurations.

For the stronger adversarial contract, run the complete command as a descendant of the guard:

python scripts/dev/review_worktree_guard.py run \
  --worktree <review-worktree> -- \
  git -c url.<actual-file-url>.insteadOf=<blocked-file-url> push \
  --no-verify --receive-pack=git-receive-pack origin HEAD:refs/heads/example

This run path installs Linux Landlock application binary interface (ABI) 4+ before exec: reads and execution remain available, filesystem mutation is allowed only in the review worktree and linked Git admin directory, inherited file descriptors are closed, and TCP bind/connect is denied. It fails closed when that policy cannot be installed. This is a Linux-only process boundary for local filesystem remotes, not a portable all-host guarantee. It does not attach to the directory, so commands launched later from another terminal or raw Git invocations outside run are outside the contract; use run -- ... bash for a bounded session. Landlock's policy also deliberately excludes remotes inside its writable roots, Unix-domain/existing privileged helper channels, and privileged host escapes. The creation helper clears copied per-worktree configuration before applying the requested mode, so an implementation worktree created from a protected review checkout remains independently pushable. Implementation worktrees keep the default pushable behavior. See worktree_lifecycle.md for the complete invocation and restoration procedure.