Skip to content

Verify chg stories from verified/master (US-47.6) - #1007

Merged
mkreyman merged 3 commits into
masterfrom
feature/us-47.6-verified-master
Oct 19, 2026
Merged

mkreyman merged 3 commits into
masterfrom
feature/us-47.6-verified-master

Conversation

@mkreyman

@mkreyman mkreyman commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

US-47.6: a story bound to a chg change reaches verified only from verified/master.

What changes

  • Loopctl.Changes.TrunkEvidence decides it. The landed trunk commit is the newest applied landed event's data.merge_sha. The forge compare GET /repos/:repo/compare/<merge_sha>...verified/master must answer ahead or identical. An applied reverted event after that landing refuses without a forge call.
  • The gate applies to all five ways a story reaches verified: verify, verify-all, bulk verify, backfill and bulk mark-complete. It sits next to the US-47.5 landed-review gate. Stories with no change binding never reach the forge.
  • The forge read runs before the transaction (batches 4 at a time, 15 s per call). Under the story lock, the answer is applied only if it was made for the same landing. Otherwise the result is landing_changed, which is unevaluated.
  • The existing PullRequestSource.contains?/3 callback is reused, so there is no new egress host.
  • New responses:
    • 409 chg_landing_not_trunk_verified
    • 409 chg_landing_reverted
    • 503 chg_trunk_unevaluated with Retry-After; the body carries decision, reason and retry_after_seconds.
  • OpenAPI, Messages, the chain-of-custody skill, the root CHANGELOG (forge token scope) and the CLAUDE.md citations are all updated.
  • mcp-server 3.4.0: the verify_story, verify_all_in_epic, bulk_mark_complete and backfill_story descriptions name the new refusals.

Defaults Mark may want to overrule

  1. The gate runs on all five verify paths. On backfill and mark-complete it is a second line of defence. To narrow it, change guard_backfill/3 in lib/loopctl/progress.ex and process_mark_complete in lib/loopctl/bulk_operations.ex.
  2. Every forge error is a 503, including a 404 and a permanent 401/403. A token that is permanently wrong therefore keeps answering 503, and reason names the cause. To change this, edit code/1 and retry_after/1 in trunk_evidence.ex.
  3. Retry-After is 30 s by default, or 3600 s when the credential is missing.
  4. A merge sha that is not yet an ancestor of verified/master is a 409, not a 503: the forge did answer.

Post-verify CI run on a chg story

The verification run queued after verify reads CI the way it does for a PR, so on a chg story it used to record no_story_branch. CiTarget now answers chg_landed_on_trunk for a story with a change binding: the same key the trunk gate uses, so an unbound PR-delivered story in a chg-mode project is still read as before. That records why CI was not read: the trunk gate above decided the verdict.

Review round (one, /lean-review high)

All 9 findings are fixed in the commit "Review round on #1007":

  1. ci_target.ex: the source mode was used as the trigger. Fixed: the trigger is now the story's binding (Landings.newest_binding/3), and both cases are tested.
  2. trunk_evidence_test.exs transaction probe was vacuous on the bulk paths. It now reads the transaction state of the calling process, plus a positive-control test.
  3. The binding and landing queries were duplicated in ReviewCustody. Both modules now use Loopctl.Changes.Landings.
  4. The forge was read before the cheap gates. assess/3 and assess_many/3 now take ask?, so verify, verify-all, backfill and the bulk paths ask the forge only when their local gates pass. Covered by a test that runs every path with no forge call (mutation-checked).
  5. verify-all read the forge one story at a time. It now prefetches with assess_many/3.
  6. facts/3 was N+1. It now makes three set-based queries per batch.
  7. The dead :not_chg branches in assess_many are removed.
  8. ensure_mark_complete_allowed/2 docs corrected to /3.
  9. The assess/3 and assess_many/3 docs now match their arities.

Tests

  • trunk_evidence_test.exs covers AC-47.6.1–3: ancestor, not an ancestor, revert, re-landing, forge errors, stale assessment, and tenant isolation.
  • chg_trunk_verification_controller_test.exs covers the HTTP shapes and the OpenAPI spec.
  • The forge client tests were extended.
  • Mutation checks: removing each gate or check makes a test fail.

🤖 Generated with Claude Code

A story bound to a chg change now reaches verified only when the landed
trunk commit (data.merge_sha of the newest applied landed event) is an
ancestor of verified/master, read through the forge compare API, and no
reverted event follows that landing. A forge timeout or error answers
503 chg_trunk_unevaluated with Retry-After; every other gate is unchanged.
The gate covers verify, verify-all, bulk verify, backfill and bulk
mark-complete. The forge read runs outside the transaction and is applied
under the story lock only if it was made for the same landing.

mcp-server 3.4.0 documents the new refusals on the verify tools.
The run queued after verify read CI like a pull request and recorded
no_story_branch for a chg story. A chg source now records why CI is not
read: verify required the landing on verified/master.
@mkreyman

Copy link
Copy Markdown
Owner Author

Review round 1 (code) counted at 7fd5e3f2691c via Skill lean-review. The review-round counter's merge gate reads this marker on any machine.

- Loopctl.Changes.Landings holds the newest-binding and newest-applied-
  landing reads; ReviewCustody and TrunkEvidence both use them, so the
  landed-review and trunk gates judge the same landing.
- TrunkEvidence reads bindings, landings and reverts in one query each
  for any batch, and the dead :not_chg branches are gone.
- assess/3 and assess_many/3 take an ask? callback: verify, verify-all,
  backfill and the bulk paths ask the forge only for a story their cheap
  local gates would pass. verify-all makes its forge reads in one batch.
- CiTarget records chg_landed_on_trunk for a story with a change binding,
  not for every story of a chg-mode source.
- The forge stub's transaction probe now reads the calling process's
  transaction state too, so the bulk paths' task workers are covered.
- Doc arities corrected (assess/3, assess_many/3,
  ensure_mark_complete_allowed/3).
@mkreyman
mkreyman enabled auto-merge (squash) October 19, 2026 11:14
@mkreyman
mkreyman merged commit a8da572 into master Oct 19, 2026
17 checks passed
@mkreyman
mkreyman deleted the feature/us-47.6-verified-master branch October 19, 2026 11:22
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