fix(runtime#131): auto-merge propagated .runtime-version bump PRs on consumer templates #169
Open
agent-dev-b
wants to merge 4 commits from
fix/131-merge-runtime-version-bumps into main
pull from: fix/131-merge-runtime-version-bumps
merge into: molecule-ai:main
molecule-ai:main
molecule-ai:fix/133-compact-context-and-continue
molecule-ai:fix/52-propagate-pr-post-retry-backoff
molecule-ai:fix/86-git-askpass-no-token-in-argv
molecule-ai:fix/162-oauth-via-anthropic-auth-token-under-cp-proxy
molecule-ai:fix/3164-layer2-self-heal-observability
molecule-ai:fix/3164-wire-identity-gate-payload
molecule-ai:fix/llm-auth-drop-oauth-on-cp-proxy
molecule-ai:fix/2970-protect-management-mcp-from-user-plugin-eviction
molecule-ai:feat/3082-loaded-mcp-tools-producer
molecule-ai:fix/38-mcp-tool-ssot
molecule-ai:ssot/mcp-plugin-delivery-contract-gate
molecule-ai:fix/87-boot-routes-regression-test
molecule-ai:fix/143-a2a-client-json-guard
molecule-ai:fix/141-load-config-opt-fallback
molecule-ai:fix/118-empty-workspace-config-path
molecule-ai:fix/138-typed-a2a-marker
molecule-ai:fix/consumer-drift-guard-blind-spot
molecule-ai:fix/propagate-dual-pin-templates
molecule-ai:fix/2832-automemory-redaction
molecule-ai:fix/durable-memory-persistence-injection
molecule-ai:fix/surface-agent-error-detail
molecule-ai:fix/2723-heartbeat-dedicated-thread
molecule-ai:feat/ack-first-responsiveness
molecule-ai:fix/drift-ssot-latest-release
molecule-ai:fix/publish-precheck-not-skip-existing
molecule-ai:fix/runtime-propagation-new-branch-source-base
molecule-ai:fix/propagate-branch-base
molecule-ai:fix/publish-skip-existing
molecule-ai:feat/2606-workspace-request-tools
molecule-ai:feat/spec1-bounded-inbox-queue
molecule-ai:fix/tag-only-auto-release
molecule-ai:release/0.3.14
molecule-ai:ci/auto-bump-publish-on-main
molecule-ai:feat/agent-liveness-a1-tool-timeouts
molecule-ai:feat/agent-responsiveness-e2e
molecule-ai:feat/a2a-nonblocking-default-on
molecule-ai:chore/bump-0.3.13
molecule-ai:fix/a2a-queue-not-interrupt
molecule-ai:fix/heartbeat-skip-nonresult-rows
molecule-ai:chore/bump-runtime-0.3.12
molecule-ai:fix/agent-runtime-per-completion-timeout
molecule-ai:fix/2421-heartbeat-carries-agent-card
molecule-ai:fix/1180-lazy-workspace-id-import
molecule-ai:fix/runtime-104-deterministic-git-credential
molecule-ai:fix/a2a-client-lazy-workspace-id
molecule-ai:fix/98-buffer-api-python312
molecule-ai:fix/executor-helpers-non-string-uri
molecule-ai:bump-0.3.10-cross-cloud
molecule-ai:fix/cross-cloud-advertise-injected-url
molecule-ai:harden/contract-tests-runtime
molecule-ai:fix/a2a-2251-outbound-envelope-role
molecule-ai:feat/runtime91-auto-pin-propagation
molecule-ai:release/runtime-v0.3.9
molecule-ai:fix/2200-desktop-coord-1to1
molecule-ai:test/issue-87-boot-routes-real-subprocess
molecule-ai:fix/extract-message-text-protobuf-iterable
molecule-ai:feat/browser-profile-dir-env
molecule-ai:release/runtime-v0.3.7
molecule-ai:fix/runtime-honors-provider-drop-inherited-oauth
molecule-ai:fix/internal-688-boot-register-retry
molecule-ai:fix/dedupe-set-current-task-extract-text
molecule-ai:agent-dev-b/test-card-helpers-and-redactor
molecule-ai:agent-dev-b/test-not-configured-handler
molecule-ai:agent-dev-b/test-rbac-policy
molecule-ai:agent-dev-b/test-transcript-auth-rca-328
molecule-ai:agent-dev-b/test-platform-comm-contract
molecule-ai:fix/runtime-template-pins-check
molecule-ai:fix/stdio-transport-regression-test-option-b
molecule-ai:agent-dev-b/stdio-transport-revive
molecule-ai:fix/ruff-cleanup-e402-f401-f841-e741
molecule-ai:fix-52-missing-retry-backoff
molecule-ai:agent-dev-b/runtime-stdio-tests
molecule-ai:fix-52-cascade-credential-safety
molecule-ai:agent-dev-b/runtime-type-errors
molecule-ai:agent-dev-b/runtime-small-cleanups
molecule-ai:fix/fullscreen-desktop-browser
molecule-ai:fix/xorg-firefox-display
molecule-ai:fix/xvfb-falkon-window
molecule-ai:release/runtime-0.3.3
molecule-ai:fix/xvfb-falkon-browser
molecule-ai:fix/xvfb-chrome-flags
molecule-ai:feat/desktop-control-tools
molecule-ai:fix/ruff-test-only-e401-multi-imports
molecule-ai:chore/maintained-runtime-cascade
molecule-ai:fix/external-upload-push-attachments
molecule-ai:fix/hermes-user-attachments-runtime
molecule-ai:fix-15-pin-shas-runtime-phase2
molecule-ai:fix-52-hardcoded-network-probe
molecule-ai:fix-49-validate-needs-timeouts
molecule-ai:fix/l4-vlm-image-descriptions
molecule-ai:fix/l4-vision-attachments
molecule-ai:fix/attachment-l4-runtime
molecule-ai:fix/credential-helper-file-leak
molecule-ai:chore/gitea-only-ci
molecule-ai:feat/rfc-upload-resolution-mandatory-contract
molecule-ai:fix/publish-cascade-prs
molecule-ai:ssot/base-mcp-tools-contract
molecule-ai:fix/layer2-peer-info-defensive-read
molecule-ai:test/platform-comm-contract-workflow
molecule-ai:fix/durable-delegation-platform-url-ssot
molecule-ai:fix/rbac-policy-ssot
molecule-ai:fix/standalone-mcp-rbac-config-default
molecule-ai:docs/multi-external-workspace-registration
molecule-ai:chore/consumer-drift-secret-preflight
molecule-ai:chore/consumer-runtime-drift-guard
molecule-ai:chore/ci-full-runtime-test-guard
molecule-ai:fix/multi-workspace-platform-url-runtime
molecule-ai:fix/stop-all-bash-subprocess-cancel-propagation
molecule-ai:fix/heartbeat-notify-success-suppress
molecule-ai:chore/runtime-ssot-gitea-publish
molecule-ai:fix/190-self-delegation-regression-tests
molecule-ai:fix/378-non-blocking-a2a-handler
molecule-ai:feat/296-per-workspace-platform-url
molecule-ai:migration/standalone-ssot
molecule-ai:fix/pin-python-multipart-for-chat-upload
molecule-ai:feat/agent-card-update-and-runtime-identity-tools
molecule-ai:runtime/fix-a2a-mcp-module-invocation
molecule-ai:runtime/idle-loop-skip-pending-delegations
molecule-ai:runtime/idle-loop-check-pending-messages
molecule-ai:runtime/offsec-003-delegation-only
molecule-ai:runtime/platform-url-host-docker-internal
molecule-ai:runtime/fix-offsec-003-read-delegation-results
molecule-ai:sre/OFFSEC-003-mcp-prompt-injection-guard
molecule-ai:fix/a2a-mcp-server-review-fixes
molecule-ai:runtime/http-mcp-review-fixes
molecule-ai:runtime/review-pr5-http-mcp-fixes
molecule-ai:fix/hermes-mcp-platform-tools
molecule-ai:fix/a2a-sdk-constraint-to-1x
molecule-ai:fix/post-suspension-github-urls
molecule-ai:fix/lowercase-org-slug
molecule-ai:docs/readme-pypi-vs-mirror-clarification
Dismiss Review
Are you sure you want to dismiss this review?
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
agent-dev-a
agent-dev-b
agent-pm
agent-researcher
agent-reviewer
agent-reviewer-1
agent-reviewer-cr2
app-fe (Molecule AI · app-fe)
app-lead (Molecule AI · app-lead)
app-qa (Molecule AI · app-qa)
claude-ceo-assistant
claude-ci-reader
core-be (Molecule AI · core-be)
core-devops (Molecule AI · core-devops)
core-fe (Molecule AI · core-fe)
core-lead (Molecule AI · core-lead)
core-offsec (Molecule AI · core-offsec)
core-qa (Molecule AI · core-qa)
core-security (Molecule AI · core-security)
core-uiux (Molecule AI · core-uiux)
cp-be (Molecule AI · cp-be)
cp-lead (Molecule AI · cp-lead)
cp-qa (Molecule AI · cp-qa)
cp-security (Molecule AI · cp-security)
cui (Zhanlin Cui)
dev-lead (Molecule AI · dev-lead)
devops-engineer
documentation-specialist (Molecule AI · documentation-specialist)
fullstack-engineer (Molecule AI · fullstack-engineer)
godwin
hongming
hongming-ceo-delegated
hongming-codex-laptop
hongming-kimi-laptop
hongming-pc2
hongming-personal
infra-lead (Molecule AI · infra-lead)
infra-runtime-be (Molecule AI · infra-runtime-be)
infra-sre (Molecule AI · infra-sre)
integration-tester (Molecule AI · integration-tester)
molecule-code-reviewer
molecule-runtime-release-bot (Molecule Runtime Release Bot)
plugin-dev (Molecule AI · plugin-dev)
pm
publish-runtime-bot
pypi-publisher (Molecule AI PyPI Publisher (RFC#596))
release-manager (Molecule AI · release-manager)
sdk-dev (Molecule AI · sdk-dev)
sdk-lead (Molecule AI · sdk-lead)
sop-tier-bot (SOP Tier-Check Bot)
technical-writer (Molecule AI · technical-writer)
triage-operator (Molecule AI · triage-operator)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: molecule-ai/molecule-ai-workspace-runtime#169
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "fix/131-merge-runtime-version-bumps"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes runtime#131.
REQUEST_CHANGES @1a8b397aff3c
5-axis review, target=main, CI green. The missing-token no-op path is safe when DISPATCH_TOKEN is absent, and the PR is tightly scoped to bot-authored runtime-version bumps with green status gates.
Blocking issue: the workflow and script are wired to DISPATCH_TOKEN (
secrets.DISPATCH_TOKEN, default--token-env DISPATCH_TOKEN), but runtime#131 requires the not-yet-provisioned non-author merge/approval identity (CONSUMER_BUMP_MERGE_TOKEN). If DISPATCH_TOKEN exists as the propagation/release identity, this job will not no-op; it will attempt approve/merge with the wrong identity before the non-author token is wired, likely failing self-approval/permissions and making the automation red or ineffective. Please gate the workflow/script on the explicit non-author merge token (or otherwise prove DISPATCH_TOKEN is that non-author identity), and keep the absent-token path as an exit-0 skip until provisioned.REQUEST_CHANGES @1a8b397aff3ce0d169b82dc761de63a8982a7815
CI is green and the added unit tests pass locally (
python -m unittest scripts/test_merge_runtime_version_bumps.py -v, 17/17), but I found two correctness blockers against runtime#131's required contract.The workflow is wired to the wrong secret/identity.
.gitea/workflows/merge-runtime-version-bumps.ymlpassesDISPATCH_TOKENintoscripts/merge_runtime_version_bumps.py, and the script defaults--token-envtoDISPATCH_TOKEN. runtime#131's dependency was explicitly a non-author approve/merge identity (e.g.CONSUMER_BUMP_MERGE_TOKEN) distinct from the release/propage author. IfDISPATCH_TOKENis the existingmolecule-runtime-release-botopener, the script attempts to approve its own PR and does not satisfy the non-author approval gate. If it is not that bot, the script'sBOT_AUTHOR_USERNAME == molecule-runtime-release-botassumption is inconsistent with the token being used. This only scaffolds the lane; it does not safely fulfill the approve/merge identity requirement.The sweeper does not recognize the actual branch names created by the current propagation script.
scripts/propagate_runtime_version.pysetsbranch = f"bump/runtime-{target}", butmerge_runtime_version_bumps.pyonly extracts versions from prefixesbump-runtime-andbump-runtime-v. Real propagated PRs from the current script will have heads likebump/runtime-0.3.x, fail version extraction, and be skipped rather than approved/merged. The tests usebump-runtime-0.3.23, so they don't catch this integration mismatch.Required fix shape: wire the workflow/script to the provisioned non-author merge token (and fail-soft/no-op when that token is absent), while preserving
DISPATCH_TOKENonly for the opener path; and accept/test the actualbump/runtime-<version>branch grammar produced bypropagate_runtime_version.py. Add regression tests covering absent merge token no-op and current propagate branch names.Security/safety notes: file-scope gating to
.runtime-version/requirements.txtand all-green status gating are good directions, but the current head is not mergeable as runtime#131 because it cannot reliably complete real propagated PRs and may violate the non-author approval model.CR2 caught two real blockers against runtime#131's required contract: 1. Wrong identity for approve+merge. The script was using DISPATCH_TOKEN (the opener/bot identity) for both read AND write operations. Self-approval via the opener token is a no-op (Gitea rejects), so the sweeper would either self-approve- no-op silently or hit permissions errors depending on which identity DISPATCH_TOKEN turned out to be. Fix: split into two tokens — CONSUMER_BUMP_MERGE_TOKEN (the non-author identity, typically devops-engineer) for approve+merge+close; DISPATCH_TOKEN unchanged for the read-only pre-flight (list PRs, fetch files, check status, read the per-repo opt-out file). The absent CONSUMER_BUMP_MERGE_TOKEN path now exits 0 with a loud warning (runtime#83 pattern: config gap, not a runtime regression — must not paint runtime main red). 2. Branch-name grammar mismatch. scripts/propagate_runtime_version.py emits bump/runtime-{target} (with a slash), but my prefix list was bump-runtime- / bump-runtime-v (no slash). Real propagated PRs would have failed version extraction and been silently skipped — the tests used bump-runtime-0.3.23 (the wrong grammar) so they didn't catch the integration mismatch. Fix: extend the prefix list to bump/runtime-v, bump/runtime-, bump-runtime-v, bump-runtime- (most-specific first). Add 4 explicit tests for the real grammar + legacy forms + unrelated branches. Workflow file (.gitea/workflows/merge-runtime-version-bumps.yml): - secrets.CONSUMER_BUMP_MERGE_TOKEN is now wired alongside DISPATCH_TOKEN - Both missing-secret paths exit 0 with ::warning:: (the runtime#83 config-gap pattern, not a runtime regression — must not paint runtime main red on an unprovisioned secret) Tests added in scripts/test_merge_runtime_version_bumps.py: - BranchGrammar: 4 tests pinning the integration with the current propagate script's branch grammar - AbsentMergeToken: 2 tests pinning the runtime#83 absent-token no-op behavior + the present-token gate-passes behavior Total tests: 23 (was 17). All pass.APPROVE @f37cd9212e42
5-axis re-review, target=main, CI green. The prior RC 13415 is addressed: approve/merge/close now use the separate CONSUMER_BUMP_MERGE_TOKEN non-author identity, while DISPATCH_TOKEN is kept to read-only PR/file/status/opt-out calls. The workflow exits 0 with a warning when CONSUMER_BUMP_MERGE_TOKEN is absent, so the current unprovisioned-token state no-ops safely instead of breaking main. The bump filters remain narrow: bot-authored only, .runtime-version/requirements.txt only, required consumer statuses success, and repo opt-out honored.
No blocking issues found.
REQUEST_CHANGES @f37cd9212e4219f8fbcd37aaaa73e07ce101af2b
Re-reviewed current head. CI is green and the added tests pass locally (
python -m unittest scripts/test_merge_runtime_version_bumps.py -v, 23/23). The two blockers from my prior RC 13416 are addressed: the workflow now requiresCONSUMER_BUMP_MERGE_TOKENfor the non-author approve/merge identity, keepsDISPATCH_TOKENfor read/preflight only, and the branch parser now accepts the actualbump/runtime-<version>grammar frompropagate_runtime_version.py.New correctness blocker: the new workflow sets
GITEA_HOST: git.moleculesai.app, butscripts/merge_runtime_version_bumps.pytreatsGITEA_HOSTas the full API base URL (parser.add_argument("--base-url", default=os.environ.get("GITEA_HOST", "https://git.moleculesai.app"))) andGiteaClient._requestconcatenates it directly with/api/v1/.... With the workflow value, the first real API call is built asgit.moleculesai.app/api/v1/...(no scheme), which Python urllib rejects withValueError: unknown url type. I verified this locally withurllib.request.Request("git.moleculesai.app/api/v1/repos").This means the fail-safe absent-token path is fine, but once the CTO provisions
CONSUMER_BUMP_MERGE_TOKEN, the scheduled sweeper will not actually list/approve/merge any consumer bump PRs. It therefore still does not fulfill runtime#131 in production.Required fix shape: set the workflow env to a full URL (
GITEA_HOST: https://git.moleculesai.app) or rename/useGITEA_URLconsistently; alternatively make the script normalize a bare host by prependinghttps://. Add a regression test or workflow-level assertion for a bare-host env value if that is the intended convention.No other blockers found in the identity split, file-scope gate, branch grammar, or absent-token no-op behavior.
New commits pushed, approval review dismissed automatically according to repository settings
APPROVE @5c267ee95bb8
5-axis re-review, target=main, CI green. RC 13418 is resolved: workflow GITEA_HOST is now a full URL (
https://git.moleculesai.app) and the script defensively normalizes scheme-less base URLs before urllib constructs requests. The earlier fixes still hold on this head: approve/merge/close use CONSUMER_BUMP_MERGE_TOKEN, DISPATCH_TOKEN remains read-only, missing CONSUMER_BUMP_MERGE_TOKEN exits 0 before write paths, and the bump branch grammar coversbump/runtime-*. Scope remains narrow to bot-authored .runtime-version/requirements.txt bumps with required consumer statuses green.No blocking issues found.
REQUEST_CHANGES @5c267ee9.
RC 13418 itself is resolved:
.gitea/workflows/merge-runtime-version-bumps.ymlnow setsGITEA_HOST: https://git.moleculesai.app, andscripts/merge_runtime_version_bumps.pydefensively normalizes a scheme-lessGITEA_HOSTby prependinghttps://, so urllib no longer builds a scheme-lessgit.moleculesai.app/api/v1/...URL.Prior blockers also remain addressed: approve/merge uses
CONSUMER_BUMP_MERGE_TOKENwhileDISPATCH_TOKENis read-only; missingCONSUMER_BUMP_MERGE_TOKENexits 0 with a warning; and branch parsing accepts the actualbump/runtime-*grammar as well as legacy forms. Current PR head CI is green and the unit suite reports 25/25 passing locally.New blocker:
all_required_statuses_success()does not match the actual Gitea combined-status payload. The function iterates child statuses withs.get("state") == "success"(scripts/merge_runtime_version_bumps.pyaround the required-status gate), but live Gitea status rows usestatus, notstate(for example this PR head returns rows like{"context":"ci / build (pull_request)", "status":"success", ...}and no childstate). As a result, even a consumer bump PR with realvalidate-runtimeandt4-conformancesuccesses will produce an emptypostedset and be skipped as not all-green. That means the sweeper still does not fulfill runtime#131's intent once the token is provisioned. Please readstatus(or accept bothstatusandstate) and add a regression test using the actual Gitea child-status shape.all_required_statuses_success read combined.statuses[].state, but Gitea's combined-status CHILD rows carry the per-context result in `status` (the top-level combined uses `state`). Against real Gitea payloads every child evaluated false -> the sweeper skipped genuinely-green consumer bump PRs and never merged them (runtime#131 unfulfilled). Accept both shapes: (s.get('status') or s.get('state')). Adds a regression test using a real Gitea-shaped payload (child field `status`=`success`) asserting all_required_statuses_success returns True, plus a Gitea-shaped fail-closed case. 27 tests pass (was 25). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>New commits pushed, approval review dismissed automatically according to repository settings
APPROVE @ef2bc5c557c34571031281beeff88deb0925d014
5-axis re-review, target=main, mergeable=true, required CI green on the current head.
RC 13421 is resolved: all_required_statuses_success now reads child status via s.get("status") or s.get("state"), so Gitea-shaped commit-status children are counted correctly, and the added tests cover both all-green and failing required status cases.
Earlier-reviewed safeguards still hold on this head: approve/merge/close use CONSUMER_BUMP_MERGE_TOKEN rather than DISPATCH_TOKEN, missing merge token exits cleanly without write actions, branch matching covers the bump/runtime-* grammar, and GITEA_HOST is a full URL with defensive scheme normalization in the script.
No blockers found.
APPROVE @ef2bc5c557c34571031281beeff88deb0925d014.
5-axis review: RC 13421 is resolved.
all_required_statuses_success()now accepts Gitea's real child-status field (status) while retaining compatibility withstate, and tests include both the Gitea-shaped success/failure cases. That means real green consumer bump PRs withvalidate-runtimeandt4-conformancesuccesses will no longer be skipped by the sweeper.Prior runtime#131 blockers remain addressed: approve/merge uses the separate non-author
CONSUMER_BUMP_MERGE_TOKEN;DISPATCH_TOKENis read-only; absent merge token exits 0 with a warning;GITEA_HOSTis a fullhttps://URL and scheme-less values are normalized; and branch parsing accepts the actualbump/runtime-*grammar plus legacy forms. Target is main, mergeable=true, live CI is green, and local unit tests pass (27/27).View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.