Skip to content

Add a self-merge Step and tighten-only limits to a Custom process - #1431

Merged
JacobStephens2 merged 4 commits into
issue-877from
issue-1390
Oct 27, 2026
Merged

JacobStephens2 merged 4 commits into
issue-877from
issue-1390

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

thirdshift process ship issue 7 merge
  delivery
    publish the Issue branch
    Repair loop, capped by the file when it sets a lower repair_cap
  self-merge
    asked by merge, or by merge_always, and the file does not set self_merge = false
      a changed path matching protected_paths
        leave the pull request ready for review and name the path
      otherwise
        gh pr merge --merge --match-head-commit
        delete the Issue branch and close the issue
    not asked, or no-merge
      leave the pull request ready for review

A self-merge Step directly after delivery is the existing Self-merge. It merges only when the command's merge flag or the User config's merge_always asks. Otherwise the pull request stays ready for review. A file can only tighten limits: repair_cap no higher than 5, self_merge = false to hold a merge the command asked for, and protected_paths globs. * stays inside one path segment, ** crosses segments, and ? is one character other than /.

check prints a limit only when the file tightens one. A self-merge Step anywhere but directly after delivery is refused before a session.

Evidence

  • Before: Delivery on a Custom process always left the pull request ready for review. A file could not name a Self-merge or tighten the Repair cap, and merge was not a process flag.
    After: cargo test --test process — 93 passed, 1 ignored — including self_merge_after_delivery_merges_when_asked_and_stays_ready_otherwise, self_merge_false_holds_the_merge_and_says_why, a_protected_path_holds_the_self_merge_and_names_the_path, a_quoted_protected_name_still_holds_the_self_merge, a_lower_repair_cap_stops_the_repair_loop, and a_repair_cap_above_the_effective_cap_is_a_loosening_limit. After the glob fix, cargo test --bin thirdshift protected_path_globs_match_on_segment_boundaries passed, and the protected-path process test passed again. cargo clippy --all-targets -- -D warnings passed. cd site && npm run docs:check passed. The quoted-name hold fix lists names with git diff --name-only -z and matches on the raw bytes: cargo test --bin thirdshift delivery:: — 69 passed — and cargo clippy --bin thirdshift --tests passed with no warnings. scripts/affected-tests issue-877 ran the full suite: 3192 passed, 70 skipped.

Merge Danger

Door: two-way

Revert these commits. A Process file that does not mention self-merge or [limits] behaves as it did. A Ticket run still passes no protected paths and the effective Repair cap.

Blast Radius: processes

A Custom process that asks to merge now merges the same way a Ticket run does. A bad protected-path glob can hold that merge and leave the pull request ready for review.

Seams

  1. thirdshift process check and a run refuse a file whose shape loosens a limit or places self-merge anywhere but directly after delivery.
  2. thirdshift process <name> issue N merges when asked, holds when self_merge = false or a protected path matches, and stops the Repair loop at a lower cap.

Unaddressed findings

Standards

  1. Duplicated Code (judgement) — refuse_self_merge repeats delivery's "not optional / not parallel / Issue-branch worktree" checks. src/processes.rs around the self-merge cannot be optional rule. Plan: each catalogue keeps its own refusal text, as refuse_published does. The messages differ (self-merge cannot be optional versus delivery cannot be optional), and refuse_issue_branch also finds the last editing Step. Sharing a helper would only swap the rule name.

  2. Duplicated Code (judgement) — publish_steps and InWorktree::take_to_goal both build RunOutside. src/delivery.rs InWorktree::take_to_goal hardcodes protected_paths: &[] and MAX_REPAIRS; publish_steps passes the file's cap and globs. Plan: those are the two callers on purpose. A Ticket run stays on the open limits. A shared constructor would be another long argument list, and clippy's too_many_arguments limit is 7.

  3. Glossary length (judgement) — .agents/skills/domain-modeling/GLOSSARY-FORMAT.md says one or two sentences, and docs/agents/domain.md says glossary definitions stay implementation-free. The added sentences are on Custom process, Self-merge, and Repair loop in GLOSSARY.md. Plan: those entries were already procedural before this change (the Self-merge entry already describes the merge commit, the observation, and deleting the branch). The new sentences state the tighten rule beside those terms. docs/code-navigation.md holds the paths. The reviewer did not label this a hard breach.

The duplicated merge-flag parse was fixed: take_flag calls take_merge_flag, and Goal::from_flag is what a Ticket run and a Process both use.

The quoted-name hold fix raised no new Standards findings: Git::run_bytes reuses run's failure path, and the byte-slice change stays inside the existing private seam.

Spec

None. The protected-path glob finding was fixed. The reviewer's rustc command, as written, stopped before glob_match's closing brace and did not compile. The same asserts, with that brace included, panicked on **/key.txt versus mykey.txt. delivery::tests::protected_path_globs_match_on_segment_boundaries now locks those asserts and passed. The quoted-name hold fix is spec-clean: it performs the specified hold for quoted names and adds no new limit, flag, or Step.

Security

No unaddressed introduced findings. Review found one introduced finding — the protected-path hold missed a changed name git quotes, so the Self-merge went ahead — and it is fixed on this branch: merge_hold lists names with git diff --name-only -z and matches on the raw bytes (src/delivery.rs, Git::run_bytes in src/git.rs), locked by a_quoted_protected_name_still_holds_the_self_merge in tests/process.rs. No pre-existing findings were touched; those belong to a separate Security run.

Security review outcome

No unaddressed introduced findings.

Review coverage

No changed file was left unread. site/docs/index.html is generated from docs/guide.md by site/generate-docs.mjs. cd site && npm run docs:check passed, and the new self-merge, repair-cap, and protected-path sentences are in the HTML. The reviewers did not count that file as read.

Closes #1390

Built with grok grok 1.0.70 (f50904eaee6c) [stable] · default model · default effort

)

A self-merge Step directly after delivery is the existing Self-merge. It
merges when the merge flag or merge_always asks, and otherwise leaves the
pull request ready for review. A file may only tighten the Repair cap,
forbid the merge, or name protected paths that hold it.
`**` resumed at every byte, so `**/key.txt` matched `mykey.txt`. It now
resumes at the next path segment, and `?` is one character. A Ticket run
and a Process share the merge-flag parse.
git diff --name-only quotes names with non-ASCII, quote, backslash or
newline bytes, so a protected path such as secrets/** never matched the
quoted listing and the merge went ahead. List names NUL-delimited (-z)
and match on the raw bytes.
@JacobStephens2
JacobStephens2 merged commit 568aa84 into issue-877 Oct 27, 2026
18 checks passed
@JacobStephens2
JacobStephens2 deleted the issue-1390 branch October 27, 2026 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant