Skip to content

Port the pins, vendoring, preapproval and APM sync task logic #330

Closed
1 of 9 issues completed
Closed

Description

@tbhb-agent

Problem

The original #330 combines several independent ports and exceeds one reviewable pull request. This body covers the first remaining unassigned slice only: add the existing Python type-check adapter's behavior to the Go CLI, without changing consumer dispatch. The pins, vendoring, preapproval, APM, preview, source-selection, and build-metadata ports already have separate open issues; fuzz orchestration is already implemented. Do not duplicate those issues.

The current adapter invokes pyrefly, normalizes its output, and permits one narrow empty-view exemption. These decisions still live in shell. Under #588, implement this adapter in Go rather than the original inventory's proposed Python destination.

Baseline: origin/main at 2f74b1bccf476f8d142c3b4f6ac14e72302807b1. Behavioral evidence is .devtools/scripts/lint-types.sh, its forwarding entry point tools/lint-types.sh, and the devtools:lint-types task in .devtools/tasks/python.toml. The existing Go command tree is internal/agentrepo/command.go, reached through cmd/agentrepo/main.go.

Acceptance criteria

For agentrepo lint-types, supported inputs require the environment to contain a non-empty PATH. Relative directories and empty components within a non-empty PATH remain supported. An empty or absent PATH is outside this parity contract, because the frozen adapter has no PATH handling and Bash's diagnostic and default search path for those inputs are not part of its interface. This boundary is specific to lint-types.

  1. AC1: Invoking agentrepo lint-types runs uv run pyrefly check exactly once with LC_ALL=C.
  2. AC2: A successful type-check invocation returns status 0 and prints its combined output with trailing newlines normalized to one newline, including a single newline for empty output.
  3. AC3: A failed invocation whose working-directory spelling matches */.claude/worktrees/* and whose combined output contains No Python files matched patterns returns 0 with the existing skip diagnostic instead of the captured output.
  4. AC4: Every other failed invocation returns the failing command's exit status and prints its combined output with the same newline normalization as a successful invocation. When the executable is missing, the adapter returns exit status 127 and prints the shell's command-not-found diagnostic on standard output, matching the frozen adapter at .devtools/scripts/lint-types.sh:23 on origin/main.
  5. AC5: Extra arguments supplied to the adapter remain ignored, matching the existing adapter's invocation of pyrefly.
  6. AC6: Non-functional: identical supported inputs produce the frozen adapter's status, stdout, and stderr on macOS and Linux; the same ordinary-path success and failure cases pass on Windows.
  7. AC7: Non-functional: the adapter preserves the caller's working directory and environment apart from the existing child-process locale override.
  8. AC8: Existing consumer task and executable entry points retain their current behavior without requiring a newer binary.

Scope and non-goals

Include the additive Go CLI, behavior tests, CLI help, and documentation of its availability. Preserve the exact existing skip diagnostic, substring matching, logical working-directory spelling, output merging, empty output, command-not-found behavior, and exit statuses. No real type-check exemption is exercised against repository code as a substitute for tests; use controlled fixtures.

Non-goal: changing the hidden-path exemption, selecting first-party files, forwarding previously ignored arguments, or fixing the distinct defect in #374. This is behavior parity only. If #374 lands first, rebaseline against its accepted behavior before implementing this slice; do not restore an exemption that it removed.

Out of scope: the other task ports, consumer dispatch, binary distribution, shell removal, configuration changes, and editing or deleting any frozen shell implementation or its existing Bats coverage. Add no new shell. Consumer cutover is a separate slice after distribution and compatibility are settled.

Approach

Reuse the existing Cobra command tree in internal/agentrepo/command.go and the entry point in cmd/agentrepo/main.go; add the adapter under internal/ with Go tests rather than introducing another executable or command framework. Follow the existing subprocess and CLI-test patterns in internal/agentrepo/fuzz.go and internal/agentrepo/fuzz_test.go, which already support an external-tool adapter. Do not reuse the fuzz runner's discovery-error policy for type checking.

Establish failing Go tests for each branch before implementing it. Use a Go test helper as the external-command substitute, and compare Unix fixture results against the unchanged shell as an oracle. Preserve shell command-substitution output semantics explicitly. Document the Go command as additive; leave the existing tasks and shell files untouched throughout this PR, preserving the N-2 policy in docs/compatibility.md.

Dependencies

Native blockers: None; this additive command can land independently of the other ports.

Size

S. One PR, estimated 250–450 code lines including Go tests and under 200 prose lines; hard limits are 800 code and 2000 prose lines. Consumer cutover and every other original task family remain separate slices.

Verify plan

  • AC1: A Go command recorder asserts one invocation, exact arguments, and the child's C locale.
  • AC2: Go table tests cover empty output, stdout only, stderr only, interleaved streams, and multiple trailing newlines on success.
  • AC3: Go table tests cover matching and nonmatching directory spellings, matching text on either stream, embedded matching text, and status 0 with matching text. Compare the exact skip diagnostic with the frozen oracle.
  • AC4: Go tests cover ordinary-path empty-view failure, hidden-path unrelated failure, mixed output, missing executable under a non-empty PATH that lacks uv, and representative nonzero statuses; Unix parity tests compare status and both adapter streams separately, and for the missing-executable case compare the exit status (127) and the command-not-found diagnostic on standard output against the frozen adapter.
  • AC4 (lookup): Unix parity tests keep relative directories, current-directory lookup, leading and trailing empty components, entry order, symlinks, and permission failures. They drop only the whole-empty PATH and absent PATH cases, with the supported-inputs sentence as the reason.
  • AC5: Go CLI tests pass extra options and positional values and assert that none reach the child.
  • AC6: Run focused Go tests on macOS, Linux, and Windows; run frozen-shell parity tests on macOS and Linux, and document the same PATH boundary in the command's availability notes. Use simulated child tools rather than invoking Python or resolving dependencies in these tests.
  • AC7: Go tests assert the child receives the unchanged directory and unrelated environment values, and that invoking the adapter does not change the parent's directory or environment. Include logical-directory spelling fixtures.
  • AC8: Diff inspection confirms no task-dispatch or shell changes; existing type-check entry-point checks retain their baseline result. Run go test ./internal/agentrepo, applicable repository lint and test gates, and verify the documented N-2 behavior remains unchanged.

Risks

Go stream capture or newline trimming could alter diagnostics. Resolving a logical directory to a physical path could alter the exemption. Incorrect subprocess status mapping could hide a failure. Fixture comparisons must cover each boundary.

This parity port preserves the known exemption defect tracked by #374; it does not claim to fix type-check coverage. Shipping only an additive command avoids changing the current consumer path. Undo: revert this PR to remove the new command; the unchanged consumer path continues to operate.

Operator authority

None

Activity

  1. added
    change:featPR adds or changes a feature (Conventional Commit type feat)
    on Oct 20, 2026
  2. removed
    change:featPR adds or changes a feature (Conventional Commit type feat)
    on Oct 22, 2026
  3. 10 remaining items

  4. moved this from Backlog to In progress in devtoolson Oct 31, 2026
  5. added 3 commits that reference this issue on Oct 31, 2026
    d0c404d
    2fa3d4c
    4a33b36
  6. added
    refinement:activeA refinement round is open; not ready for implementation
    and removed
    refinement:readyPassed the Definition of Ready; may be picked up
    on Nov 1, 2026
  7. tbhb-agent commented on Nov 1, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: READY — PATH boundary is a legitimate scope clarification

    Checked

    • .devtools/scripts/lint-types.sh:20 and .devtools/scripts/lint-types.sh:23 show the adapter sets LC_ALL=C and delegates uv lookup to Bash; .devtools/scripts/lint-types.sh:25 and .devtools/scripts/lint-types.sh:39 handle success and failure output. The script defines behavior for empty or absent PATH, but does not establish those environments as supported inputs to this additive parity command. A caller could plausibly supply either through a sanitized environment; no existing contract or production caller establishes that they are supported. The boundary is specific and explicit, so I judge it a legitimate clarification.
    • AC IDs 1–8 remain present. The new sentence is testable via the PATH boundary and does not prescribe implementation. AC4’s .devtools/scripts/lint-types.sh:23 reference is correct.
    • AC4’s plan checks missing uv with a non-empty PATH and compares status and both streams. Its lookup coverage retains the remaining listed PATH cases. AC6 keeps macOS and Linux parity checks and Windows ordinary-path checks.
    • The additions are limited to this boundary’s tests and documentation; no unnecessary implementation requirement is apparent.

    Gaps

    None.

    Split

    S fits one additive PR; consumer cutover remains separate.

    Loosens: no

    Definition of done

    • D1 — Problem and goal are stated.
    • D2 — Acceptance criteria describe observable behavior.
    • D3 — Verify plan maps checks to criteria.
    • D4 — Failure behavior is specified and verified.
    • D5 — Scope and non-goals are bounded.
    • D6 — Dependencies and blockers are accurate.
    • D7 — Size is appropriate.
    • D8 — Approach fits the Go-port direction.
    • D9 — Risks and undo are covered.
    • D10 — Operator authority is correct.

    Round: 2 of 3

  8. added
    refinement:readyPassed the Definition of Ready; may be picked up
    and removed
    refinement:activeA refinement round is open; not ready for implementation
    on Nov 1, 2026
  9. added 3 commits that reference this issue on Nov 1, 2026
    b6d2acb
    b43ad24
    f0d36d6
  10. moved this from In progress to Done in devtoolson Nov 1, 2026
  11. tbhb-agent commented on Nov 1, 2026

    @tbhb-agent
    ContributorAuthor

    Status: Done

    Done

    PR #1023 (f0d36d63ece339a7b9d65e56b4a069be45e796e9) merged at 2026-11-01T04:35:53Z as 37f71fd4f085d8354eb6bd1803b57c4c0385830c. It adds the lint-types command to agentrepo. Its review approved the exact head: #1023 (review)

    Next

    Remaining children of #588.

    Blocked on

    None.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refinement:readyPassed the Definition of Ready; may be picked up

    Fields

    Priority

    Intangible

    Work type

    Planned

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions