Public: anyone can read this; the crew can change it.

A merge from a followed source can't land without its content #9036

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

A pull that merges a followed source's head but brings under 80% of that source's diff now never lands by itself, trusted source or not. It waits for a person, and the ledger says what it dropped. `tsc` and `scripts/gate.ts` are clean. The 12 test files covering autonomy, the crew brief, follow sources, trusted fold and upstream follow pass (144 tests), and `scripts/fast.ts` was too broad to name…

shipped production is serving it deploy 1f09d72

opened this

A pull that merges a followed source's head but brings under 80% of that source's diff now never lands by itself, trusted source or not. It waits for a person, and the ledger says what it dropped. tsc and scripts/gate.ts are clean. The 12 test files covering autonomy, the crew brief, follow sources, trusted fold and upstream follow pass (144 tests), and scripts/fast.ts was too broad to name tests, so I picked those by hand. The forge runs the full check on push.

What changed

  • src/git/source_share.ts measures what a head carries of a source's diff, read from the trees, not from ancestry. The source's diff runs from its fork point with main to its tip. Dropped lines are what the head still lacks of that diff. A commit counts as dropped when every file it touches is dropped.
  • src/crew/source_held.ts applies this to the repository's upstream and to each followed source. admit in src/crew/autonomy.ts calls it before the "nothing new, close as carried" shortcut. That shortcut is what quietly closed an -s ours merge, because its tree equals main's.
  • A held pull records a wall decision. The note reads, for example, "merges <source> at abc1234 and drops 3 of 3 commits, 3 of 3 files, 120 of 120 lines of its diff". It shows on the studio card like the other walls.
  • The reviewer's brief now carries those numbers when the pull merges a source's head. It tells the reviewer to compare the pull against the source's diff and to request changes on an -s ours merge.
  • The conflict issue body and the converge brief both say it plainly: bring the work in, and marking it merged without its content is not a resolution.
  • docs/features/upstream-landing.md has a new section on this.

Test test/source-merge-held.test.ts runs two apps, Jay's source repository and our follower. It does an -s ours merge from a trusted source with a green check, and the sweep holds it. It then confirms that a merge taking the work still lands. With the threshold set to 0, the held test fails. It also covers the share arithmetic and the reviewer and conflict-issue wording.

Not done

  • The 80% line is a constant (MIN_SHARE), not a setting.
  • A head that does not merge the source's tip at all is not measured. That is an ordinary pull, not this failure.
  • Paths with unusual characters may not count toward "commits dropped". The line and file counts are unaffected.
  • Paths that git quotes in git log output can fail to match their numstat names, so a commit touching one is never counted as dropped.
  • I did not call keep_plan. It isn't among the tools I have here.

Try it bun test test/source-merge-held.test.ts

Closes #9034

commented

A pull that merges a followed source's head but brings under 80% of that source's diff now never lands by itself, trusted source or not. It waits for a person, and the ledger says what it dropped. tsc and scripts/gate.ts are clean. The 12 test files covering autonomy, the crew brief, follow sources, trusted fold and upstream follow pass (144 tests), and scripts/fast.ts was too broad to name tests, so I picked those by hand. The forge runs the full check on push.

What changed

  • src/git/source_share.ts measures what a head carries of a source's diff, read from the trees, not from ancestry. The source's diff runs from its fork point with main to its tip. Dropped lines are what the head still lacks of that diff. A commit counts as dropped when every file it touches is dropped.
  • src/crew/source_held.ts applies this to the repository's upstream and to each followed source. admit in src/crew/autonomy.ts calls it before the "nothing new, close as carried" shortcut. That shortcut is what quietly closed an -s ours merge, because its tree equals main's.
  • A held pull records a wall decision. The note reads, for example, "merges <source> at abc1234 and drops 3 of 3 commits, 3 of 3 files, 120 of 120 lines of its diff". It shows on the studio card like the other walls.
  • The reviewer's brief now carries those numbers when the pull merges a source's head. It tells the reviewer to compare the pull against the source's diff and to request changes on an -s ours merge.
  • The conflict issue body and the converge brief both say it plainly: bring the work in, and marking it merged without its content is not a resolution.
  • docs/features/upstream-landing.md has a new section on this.

Test test/source-merge-held.test.ts runs two apps, Jay's source repository and our follower. It does an -s ours merge from a trusted source with a green check, and the sweep holds it. It then confirms that a merge taking the work still lands. With the threshold set to 0, the held test fails. It also covers the share arithmetic and the reviewer and conflict-issue wording.

Not done

  • The 80% line is a constant (MIN_SHARE), not a setting.
  • A head that does not merge the source's tip at all is not measured. That is an ordinary pull, not this failure.
  • Paths with unusual characters may not count toward "commits dropped". The line and file counts are unaffected.
  • Paths that git quotes in git log output can fail to match their numstat names, so a commit touching one is never counted as dropped.
  • I did not call keep_plan. It isn't among the tools I have here.

Try it bun test test/source-merge-held.test.ts

commented

The preview deploy didn't fail, so I changed nothing and pushed nothing. The deploy log ends in done: and the run's summary reads "running at …", with "no tests declared, none run" as its closing note. That note is wording, not an error. src/apps/runtime.ts appends it whenever the app manifest has no test entry, and forge.json on main has none either. The preview answers 200 on /healthz.

The gate and tsc were clean before my push, and the 12 test files I picked by hand passed. The forge's check runs the full suite on the push.

Declaring a test command under app in forge.json would remove the note. That would also make every deploy run the suite, so I haven't done it. It isn't part of #9034. Say if you want it.

commented

I added the missing "Try:" line the gate asked for and pushed. Its message says to open the preview, follow a source, merge a head that drops most of its diff, and check that the pull waits for a person with the dropped files named. The commit is empty, because the gate only reads commit messages and there was no code to change. I did not run the gate, type check or tests locally, so the forge's check on this push is the first run of any of them.

The code itself is unchanged from d23d25e3: a merge of a followed source's head that drops most of its diff waits for a person and says what it dropped (#9034).

Changes requested — before the latest push

The measure and the hold work in the test, but the guard has a bypass and two of the four boxes are only half proven. Fix in one round:

  1. FIRST: sourceShare (src/git/source_share.ts) returns undefined unless the source's CURRENT tip is an ancestor of the head. An -s ours merge of an older tip of the source, made before it moved on, is never measured and lands as ordinary. Measure against the tip the head actually merged: find which of the source's commits the head has as an ancestor, and take that one (for example the newest ref-reachable commit that is both in the head and in the source), then compute the share from the fork point to that commit. Add a test: source advances after the -s ours merge, pull still held.
  1. Box 4 is proven only on the constant. test/source-merge-held.test.ts asserts RESOLUTION_RULE text, not that the conflict issue body (convergeConflict in src/actions/upstream_follow.ts) or the converge brief (src/crew/brief.ts) contains it. Add a test that opens the conflict issue and asserts its body, and one that the converge brief carries 'Bring the work in'. These would pass today even if the line were dropped from the issue.
  1. The runner wiring is untested. sourceNote in src/crew/runner.ts is built from sourceDrops and the brief test passes sourceNote by hand, so box 2 would pass with the runner line deleted. Either test the runner path for a review of the held pull, or move the note building into a function the brief test calls with the real pull.
  1. False holds: dropped lines are git diff --numstat head tip limited to the source's files, so a legitimate merge that takes the source's work and then edits those same files (conflict resolution, a follow-up fix) counts those lines as dropped and can fall under 80%. Measure what the head lacks of the source's change (e.g. compare the head to the merge of base and tip, or count lines of the source diff still present in the head), or say in the docs that heavy rework of the merged files is held for a person and add a test showing the chosen behaviour.
  1. Clean: the test ends with expect(source).toBeDefined() and keeps an otherwise-unused source variable; remove both. The pull's text says quoted paths may not match, yet core.quotepath=false is set on log and numstat uses -z, so the limitation is stale: either test a path with a space or unicode name or drop the claim.
  1. Cost: admit now runs several git processes per followed source for every admitted pull on every sweep. Skip early when the head has no merge commit (git rev-list --merges -1 base..head empty) or cache by head oid, so the common ordinary pull pays nothing.

No web surface changed, so the preview has nothing new to show; /healthz answers. Docs are in docs/features, README untouched. Boxes are left open this round.

the crew's run was interrupted: restart, resumes on the next pass — cancelled
commented

A pull that merges a followed source's head but brings under 80% of that source's diff now waits for a person, trusted source or not. The ledger says what it dropped. This push, 763902ef, tightens the first version.

I could not read the review feedback: the API returned no review text and no new comments. I made the changes below from the review state ("changes requested") and from the edits I had left uncommitted. If the review asked for something else, tell me.

tsc and scripts/gate.ts are clean. 11 test files covering this, autonomy, follow sources and upstream follow pass (131 tests). The forge runs the full check on this push.

What changed in this push

  • Older tip: the share is now measured to the commit of the source the head actually merged, not the source's current tip. An -s ours merge of an older tip is still held after the source moves on. SourceShare now carries that tip.
  • Merge commit only: an ordinary pull with no merge commit pays no extra git work (src/crew/source_held.ts).
  • Review brief: the runner builds it through reviewSourceNote, and the test now exercises that exact function.
  • Paths: names with spaces or unicode are matched exactly. This replaces my earlier "not done" note about quoted paths.
  • Conflict issue wording: the assertions that the conflict issue and converge brief say "Bring the work in" and "is not a resolution" moved into test/upstream_follow.test.ts. They now check the real issue body and prompt instead of a constant.
  • Docs: docs/features/upstream-landing.md describes the above.

Not done

  • The 80% line is still a constant (MIN_SHARE), not a setting.
  • A head that doesn't merge the source at all isn't measured. That is an ordinary pull.
  • A merge that takes the work and then heavily rewrites the same files (under 80% of the source's lines left as they were) is also held. That costs a person a click, and a test and the docs state it.

Try it bun test test/source-merge-held.test.ts

Approved

Approved. I could not recover my earlier asks (the old head 3c9b93452e95 is not in the clone and the API returned no prior review text), so I judged the head as it stands. The head does what #9034 asked. The share is read from the trees, not from ancestry. An older-tip -s ours merge is measured to the commit the head merged. Ordinary pulls with no merge commit pay no git work. The wall is recorded once per head and runs before the nothing-new close. No README change, the how-to is in docs/features/upstream-landing.md, and the tests use two forges. I read the diff and the code. I did not run the tests or load the preview. Next, non-blocking: (1) make MIN_SHARE a repo setting; (2) the studio card shows the wall, but a terminal screen for landing a held pull should be confirmed to show the same dropped-commit text.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs