fix(consumer-drift): stop runtime main going red on every release (propagate set + token-scope reconcile) #160
Reference in New Issue
Block a user
Delete Branch "fix/propagate-consumers-derive-from-drift-ssot"
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?
Problem
consumer-drift / runtime-ssot-consumers (push)reds runtimemainafter a release for two independent reasons, neither of which is a real runtime regression:Bug 1 — propagate set narrower than the guard set (no automation to converge)
check_consumer_runtime_drift.pyDEFAULT_CONSUMERS(the guard) enforces 10 templates + molecule-core.propagate_runtime_version.pyTEMPLATE_CONSUMERS(the auto-bump bot) was a hand-maintained 4-template subset (claude-code, hermes, openclaw, codex).So
langgraph / autogen / google-adk / crewai / deepagents / gemini-cliall pin.runtime-version, are FAILED by the guard when they drift, but the bot never opened a bump PR for them — main stays red after every release with no path to green but hand-authoring. (Those 6 + an un-merged hermes/openclaw auto-PR stack are exactly what was red at 0.3.44.)Bug 2 — reconcile hard-fails on a token-scope gap (exit 2 = red)
The job log showed the real failure was not drift findings (exit 1) but exit 2:
reconcile_org_consumers→/orgs/molecule-ai/reposneedsread:organization; the CIDISPATCH_TOKENonly haswrite:repository. A token-scope/config gap was being conflated with a runtime regression — the same anti-patternconsumer-drift.ymlalready guards against for an absent token, but not for a present-but-underscoped one.Fix
Bug 1 — derive
TEMPLATE_CONSUMERSfrom the guard'sDEFAULT_CONSUMERS(template subset, minusEXEMPT_CONSUMERS). The two lists now share one SSOT and can never diverge again.molecule-coreexcluded by construction; over-inclusion is safe (plan_consumerskips ano-pinrepo).Bug 2 — raise
ReconcileUnavailableon 401/403 from the org listing;main()warns loudly + skips the (advisory) blind-spot reconcile, falling through to the pin-drift check (which reads each enumerated consumer directly, no org scope needed). SSOT enforcement is unaffected. The durable complement is to grant the CI tokenread:organization(operator/owner action) — see follow-up below.Verification
tests/test_propagate_runtime_version.py,scripts/test_propagate_runtime_version_dual_pin.py,tests/test_consumer_runtime_drift_guard.py— 25 passed locally (incl. 2 new tests for the 403 → warn/skip path).TEMPLATE_CONSUMERSresolves to all 10 templates.read:organization-capable token:Runtime SSOT drift guard passed for 11 consumer repo(s)(all pins now 0.3.44).Out-of-band remediation already done (clears the current red)
All 10 templates merged to runtime
0.3.44(8 bump PRs reviewed + merged; stale superseded auto-PRs closed). This PR prevents recurrence.Follow-up (operator)
Grant
DISPATCH_TOKEN(themolecule-runtime-release-botidentity)read:organizationso the blind-spot reconcile runs for real instead of being skipped. Until then it degrades gracefully (warn, not red).🤖 Generated with Claude Code
fix(propagate): derive TEMPLATE_CONSUMERS from drift guard DEFAULT_CONSUMERS (no more lists diverging -> red main)to fix(consumer-drift): stop runtime main going red on every release (propagate set + token-scope reconcile)Reviewed both root-cause fixes. (1) TEMPLATE_CONSUMERS now derived from the guard's DEFAULT_CONSUMERS so the propagate set can never again be narrower than what the guard enforces (the divergence that left 6 templates un-bumped + main red). Import is robust to both in-repo and spec-loader (test) paths, registers the module in sys.modules before exec so the dataclass resolves. (2) Org-scan 403 (token lacks read:organization) now raises ReconcileUnavailable -> main() warns+skips the advisory blind-spot reconcile instead of exit 2, while the actual pin-drift SSOT check still runs against the enumerated set. New tests cover both. 25 tests green. LGTM.
Security review: changes are CI-tooling only. No new secret handling; the import fallback reads a same-repo sibling file by file-relative path (no traversal/injection). The 403 soft-skip narrows to 401/403 only and degrades the ADVISORY reconcile, not the enforcing pin-drift check, so SSOT enforcement is preserved. Approve.