ORCH-026: task dependencies (B waits for A) + single-repo merge serialization #78

Merged
admin merged 9 commits from feature/ORCH-026-b-a into main 2026-06-08 19:47:58 +03:00
Owner

Summary

Implements ORCH-026 (ADR-001), two conditional levels — both kill-switched, never-raise, no new stage and no change to STAGE_TRANSITIONS / the QG_CHECKS registry.

  • Level A — merge/deploy serialization within one repo. Reuses the existing ORCH-043/065 merge-lease (no new mechanism). The only new logic is an unconditional pre-merge rebase: in check_branch_mergeable, under the held lease, auto_rebase_onto_main is called always when premerge_rebase_always (default True), not only when the branch is behind — a deterministic structural anti-phantom complementing ORCH-073. No-op on an up-to-date branch (rebase keeps HEAD, push --force-with-lease -> "Everything up-to-date", CI not triggered). Kill-switch off -> ORCH-043 behaviour 1:1. Serialization window "merge -> main-updated" stays per-repo (cross-repo parallelism preserved).
  • Level B — declarative task dependencies ("B waits for A"). Additive job_deps(task_id, depends_on_task_id) table (CREATE ... IF NOT EXISTS, safe on the live DB); claim_next_job NOT EXISTS gate defers a job whose depends-on tasks aren't yet done without occupying a max_concurrency slot; inert on empty job_deps -> zero regression. New leaf src/task_deps.py (never-raise): is_task_ready (fail-open), DFS cycle detection + Blocked/alert, declare_dependency, ingest_plane_relations (the db source never hits the network on the hot path), snapshot. Telegram waiting-line, /queue task_deps block, reconciler skip + cycle backstop; reaper untouched. Intra-repo only (v1).

Flags: ORCH_PREMERGE_REBASE_ALWAYS (true), ORCH_TASK_DEPS_ENABLED (true), ORCH_TASK_DEPS_SOURCE (db).

Self-hosting safety

Never pushes to main; the only force op stays --force-with-lease on the task branch. Prod container not restarted. Non-self repos remain a no-op on empty deps/scope.

Docs (golden source, same PR)

docs/architecture/README.md, CLAUDE.md, .env.example, CHANGELOG.md, ADR adr-0015 + work-item ADR-001.

Test plan

  • tests/test_orch026_*.py — 64 tests (TC-A01..A08, TC-B01..B08, TC-G01/G02) green
  • Regression: pinned premerge_rebase_always=False in the ORCH-043 short-circuit tests
  • Full suite: pytest tests/ -q -> 991 passed
  • ruff check clean on all changed/new source + tests (remaining 10 findings pre-exist on main)

🤖 Generated with Claude Code

## Summary Implements ORCH-026 (ADR-001), two conditional levels — both kill-switched, never-raise, **no new stage** and **no change to `STAGE_TRANSITIONS` / the `QG_CHECKS` registry**. - **Level A — merge/deploy serialization within one repo.** Reuses the existing ORCH-043/065 merge-lease (no new mechanism). The only new logic is an **unconditional pre-merge rebase**: in `check_branch_mergeable`, under the held lease, `auto_rebase_onto_main` is called **always** when `premerge_rebase_always` (default `True`), not only when the branch is behind — a deterministic structural anti-phantom complementing ORCH-073. No-op on an up-to-date branch (rebase keeps HEAD, `push --force-with-lease` -> "Everything up-to-date", CI not triggered). Kill-switch off -> ORCH-043 behaviour 1:1. Serialization window "merge -> main-updated" stays per-repo (cross-repo parallelism preserved). - **Level B — declarative task dependencies ("B waits for A").** Additive `job_deps(task_id, depends_on_task_id)` table (`CREATE ... IF NOT EXISTS`, safe on the live DB); `claim_next_job` `NOT EXISTS` gate defers a job whose depends-on tasks aren't yet `done` **without** occupying a `max_concurrency` slot; inert on empty `job_deps` -> zero regression. New leaf `src/task_deps.py` (never-raise): `is_task_ready` (fail-open), DFS cycle detection + `Blocked`/alert, `declare_dependency`, `ingest_plane_relations` (the `db` source never hits the network on the hot path), `snapshot`. Telegram waiting-line, `/queue` `task_deps` block, reconciler skip + cycle backstop; reaper untouched. Intra-repo only (v1). Flags: `ORCH_PREMERGE_REBASE_ALWAYS` (true), `ORCH_TASK_DEPS_ENABLED` (true), `ORCH_TASK_DEPS_SOURCE` (db). ## Self-hosting safety Never pushes to `main`; the only force op stays `--force-with-lease` on the task branch. Prod container not restarted. Non-self repos remain a no-op on empty deps/scope. ## Docs (golden source, same PR) `docs/architecture/README.md`, `CLAUDE.md`, `.env.example`, `CHANGELOG.md`, ADR `adr-0015` + work-item `ADR-001`. ## Test plan - [x] `tests/test_orch026_*.py` — 64 tests (TC-A01..A08, TC-B01..B08, TC-G01/G02) green - [x] Regression: pinned `premerge_rebase_always=False` in the ORCH-043 short-circuit tests - [x] Full suite: `pytest tests/ -q` -> **991 passed** - [x] `ruff check` clean on all changed/new source + tests (remaining 10 findings pre-exist on `main`) 🤖 Generated with Claude Code
admin added 6 commits 2026-06-08 19:17:45 +03:00
Level A — merge/deploy serialization within one repo: reuse the existing
ORCH-043/065 merge-lease (no new mechanism); the only new logic is an
unconditional pre-merge rebase in check_branch_mergeable — under the held
lease, auto_rebase_onto_main is ALWAYS called when premerge_rebase_always
(default True), not just when the branch is behind. No-op on an up-to-date
branch (rebase keeps HEAD, force-with-lease -> "Everything up-to-date", CI
not triggered). Kill-switch off -> ORCH-043 behaviour 1:1.

Level B — declarative task dependencies: additive job_deps table
(CREATE ... IF NOT EXISTS, no live-DB migration); claim_next_job gate
(NOT EXISTS) defers a job whose depends-on tasks are not yet 'done' without
occupying a max_concurrency slot; inert on empty job_deps -> zero regression.
New leaf src/task_deps.py (never-raise): is_task_ready (fail-open), DFS cycle
detection + Blocked/alert, declare/ingest_plane_relations (db source never
hits the network on the hot path), snapshot. Telegram waiting-line, /queue
observability, reconciler skip + cycle backstop, reaper untouched.

Invariants unchanged: STAGE_TRANSITIONS, QG_CHECKS registry (dep gate is a
claim_next_job врезка, not a registered QG), DB schema of existing tables,
HTTP endpoints; non-self repos remain a no-op on empty deps/scope.

Flags: ORCH_PREMERGE_REBASE_ALWAYS, ORCH_TASK_DEPS_ENABLED, ORCH_TASK_DEPS_SOURCE.
Docs: docs/architecture/README.md, CLAUDE.md, .env.example, CHANGELOG.md,
adr-0015. Tests: tests/test_orch026_*.py (64 tests); full suite 991 green.

Refs: ORCH-026

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
tester(ET): auto-commit from tester run_id=390
All checks were successful
CI / test (push) Successful in 27s
CI / test (pull_request) Successful in 27s
9800dc89e3
admin force-pushed feature/ORCH-026-b-a from 30d9f8e5ab to 9800dc89e3 2026-06-08 19:17:45 +03:00 Compare
admin added 1 commit 2026-06-08 19:28:42 +03:00
deploy(ORCH-036): finalize FAILED for ORCH-026
All checks were successful
CI / test (push) Successful in 23s
CI / test (pull_request) Successful in 22s
1d928dab57
admin added 1 commit 2026-06-08 19:33:58 +03:00
deploy(ORCH-036): finalize FAILED for ORCH-026
All checks were successful
CI / test (push) Successful in 23s
CI / test (pull_request) Successful in 23s
90a5cae8e6
admin merged commit b0e517c76a into main 2026-06-08 19:47:58 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/orchestrator#78