mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
docs(release): 0.27.0 prep — changelog through Wave C, map + rag + CLAUDE.md current (#697)
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -16,7 +16,9 @@
|
||||
| `_validate_and_set_status` | method | task.py:548 | Single chokepoint: validate transition + git requirements, set status, poke dispatcher, emit audit. |
|
||||
| `_emit_status_transition_audit` | method | task.py:652 | Write `task.<status>` audit row in caller session; bump `revision_count` on entry into `needs_revision`. |
|
||||
| `_alert_auditor_of_rework` | method | task.py:1019 | Best-effort helper that asks `NotificationDeliveryService` to send a HIGH `ALERT` to the auditor when a task enters `needs_revision`. Called from `fail_qa`, `pr_fail`, and `request_changes` immediately after `await self.session.flush()` so the transition row is visible before the alert is dispatched. |
|
||||
| `create` | method | task.py:864 | New task; depth/batch/AC validation; branchless/umbrella flags; baseline constraints attachment; (V2) vault materialize-on-create. |
|
||||
| `create` | method | task.py:864 | New task; depth/batch/AC validation; branchless/umbrella flags; baseline constraints attachment; (V2) vault materialize-on-create; stamps `acceptance_criteria_ids` through `_reconcile_ac_ids` (#682, explicitly supplied ids still win). |
|
||||
| `update` | method | task.py:2928 | Generic PATCH field loop (task route, prompter `update_live_draft`/`_patch_batch_child`/`update_live_batch`) — derives `acceptance_criteria_ids` via `_reconcile_ac_ids` whenever `acceptance_criteria` is rewritten with no explicit id list (#682; previously overwrote the criteria text without touching ids, leaving them mismatched or empty and silently disabling the parent-coverage gate). |
|
||||
| `_reconcile_ac_ids` | function | task.py | Pure helper (#682): one id per new criterion; text-unchanged criteria KEEP their existing id (children/findings reference criteria by id or exact text — a blanket re-mint would orphan every live reference); new/reworded text mints a fresh id; a dropped criterion drops its id. |
|
||||
| `_attach_baseline_constraints` | method | task.py:971 | Append conventions baseline constraints to task prompt (gated `conventions_enabled`). |
|
||||
| `_materialize_vault_note` | method | task.py:910 | V2: best-effort vault seam called from `create` — assembles + writes a deterministic task note (narrative placeholder) so a task is visible in the vault from the moment it exists, not just at Auditor curation/rebuild. Gated `obsidian_vault_enabled`; swallows + logs any failure. |
|
||||
| `list_updated_since` | method | task.py:7101 | V2: tasks touched (`COALESCE(updated_at, created_at)`) since a timestamp, ascending, paged — the vault janitor's changed-task re-projection set. |
|
||||
@@ -31,9 +33,12 @@
|
||||
| `_emit_admin_override_audit` | method | task.py:8555 | Factored out of `_apply_pre_block_restore`: writes `task.admin_override` audit row for admin-triggered blocked restores (`forced=False, restore=True`). |
|
||||
| `claim` | method | task.py:3112 | `FOR UPDATE` lock + `_validate_claim_preconditions` + `_finalize_claim`; calls `_validate_and_set_status(claimed)`. |
|
||||
| `_validate_claim_preconditions` | method | task.py:2883 | Per-claim validator chain: status, `_claim_blocked_by_sequencing` (dependency + sequence), team, pre-assignment theft, self-review. |
|
||||
| `_claim_blocked_by_sequence` | method | task.py:2805 | Strict sibling-sequence gate: a PENDING/`needs_revision` task with parent + effective `sequence` (`COALESCE(sequence, 0)`) N is held while any same-parent sibling with a strictly lower effective sequence is non-terminal — assignee-blind, independent of `dependency_ids`. Ties run parallel; cancelled siblings never block. |
|
||||
| `_claim_blocked_by_sequence` | method | task.py:2805 | Sequence gate for a PENDING/`needs_revision` task with a parent + effective `sequence` (`COALESCE(sequence, 0)`) N — **reachability-aware since #681**: it branches on `is_batch_root_subtask(task.batch_id, task.parent_task_id)`. A MegaTask root-subtask keeps the ORIGINAL strict rule unchanged (held while ANY same-parent sibling with a strictly lower sequence is non-terminal — assignee-blind, edge-agnostic; `sequence` there is a one-shot globally-computed Kahn wave, a deliberate staged-release barrier). Every other same-parent context instead routes through the pure `sequence_blocker_id` (`roboco/services/sequencing.py`), which only lets a lower-sequence sibling block when it is a real transitive predecessor via `dependency_ids` UNIONED with `completed_dependency_ids` — a task with NO dependency edge onto any same-parent sibling still falls back to the raw edge-agnostic bar (preserves the pre-#681 #452 edge-less-PM-delegation scenario). Ties run parallel; cancelled siblings never block. |
|
||||
| `sequence_blocker_id` | function | services/sequencing.py | Pure reachability check backing the non-batch branch of `_claim_blocked_by_sequence` (#681): returns the blocking sibling's id, or `None`, from `dependency_ids ∪ completed_dependency_ids` — the union matters because `_unblock_dependents` prunes a completed dependency's edge into `completed_dependency_ids` the moment it lands, almost always before the dependent is ever claimed. |
|
||||
| `sequence_hold_reason` | method | task.py | Names the blocking sibling for the caller instead of a bare `None`; feeds the gateway's `Envelope.sequence_held` (#681) so a held claim on PENDING or NEEDS_REVISION surfaces cleanly instead of `claim()`'s bare `None` return being misdiagnosed by the verb runner as a concurrent-transition `INVALID_STATE`. |
|
||||
| `_claim_blocked_by_dependencies` | method | task.py:2781 | `unmet_dependency` TIMING gate: refuses claim while any `dependency_ids` entry is non-terminal. |
|
||||
| `is_pending_claim_blocked` | method | task.py:2864 | Read-only wrapper over `_claim_blocked_by_sequencing` (dependency OR sequence) so the orchestrator dispatcher can filter a doomed claim before attempting it (`_pending_claim_blocked` in orchestrator.py). |
|
||||
| `is_pending_claim_blocked` | method | task.py:2864 | Read-only wrapper over `_claim_blocked_by_sequencing` (dependency OR sequence) so the orchestrator dispatcher can filter a doomed claim before attempting it (`_pending_claim_blocked` in orchestrator.py); extended to NEEDS_REVISION so `give_me_work`'s two offer paths (`list_pending_for_agent`, the Choreographer's `_drop_dependency_held`) never offer a task the reachability-aware bar (#681) is about to reject. |
|
||||
| `terminal_children_count` | method | task.py:9711 | Count of a task's terminal (completed/cancelled) direct children; feeds the orchestrator oscillation breaker's progress fingerprint (#685, `roboco/services/gateway/choreographer/_impl.py`) so a coordination root whose children advance between escalate/unblock round-trips resets its strike count instead of accruing toward a false trip. |
|
||||
| `stamp_wave_sequence` | method | task.py:7452 | Stamps a freshly delegated subtask's `sequence` as `1 + max(sequence of each same-parent dependency target)`, or `0` when independent — so independent siblings tie (parallel under the sequence gate) while colliding/ordered work ascends. Runs POST-wiring (after the collision DAG / cross-cell edges land); PM-authored sequences are never rewritten. |
|
||||
| `_apply_dependency_lineage` / `_merge_one_dependency` | method | task.py:2308 / 2337 | Claim-time content assist (not a gate): merges each same-repo dependency's landed work into a freshly cut branch when it lies outside the branch's own ancestor chain (`GitService.merge_dependency_lineage`); a real conflict aborts the merge and stamps a `dependency_lineage_conflict` transition note instead of failing the claim. |
|
||||
| `_finalize_claim` | method | task.py:3265 | Work-session create/inherit, branch cut, proactive-context injection; calls `_inherit_upstream_base` when `_should_inherit_base` says the reclaimed branch may need an upstream merge. |
|
||||
@@ -142,6 +147,8 @@ stateDiagram-v2
|
||||
- `complete()` requires PR merged (`_assert_pr_merged_for_complete`) EXCEPT branchless roots; `ceo_approve` separately checks `work_session.pr_status=="merged"` and refuses otherwise.
|
||||
- Background indexing/learning/cleanup tasks are tracked on `self._background_tasks` and are best-effort — a failure never blocks the transition.
|
||||
- The sequence gate (`_claim_blocked_by_sequence`) is enforced ONLY in `_validate_claim_preconditions`, i.e. inside `claim` itself — both the gateway claim verbs AND the orchestrator's raw dispatch claim cross it because they both funnel through `TaskService.claim`, unlike the pre-#382 dependency gate which briefly lived only on the gateway side. Any future claim path that bypasses `TaskService.claim` (a raw `admin_set_status`, for instance) does NOT get sequence enforcement.
|
||||
- Since #681, the sequence gate is NOT one rule everywhere: `stamp_wave_sequence` stamps a sibling's wave from a partial, per-task view of the graph at delegate time, which is fine within one connected chain but can coincidentally collide two INDEPENDENT same-parent dev-task streams onto the same raw sequence number. The strict edge-agnostic rule survives ONLY for `is_batch_root_subtask` rows (a MegaTask's globally-computed Kahn wave is a deliberate barrier); every other same-parent context resolves via `sequence_blocker_id`'s real-predecessor check. A task with an empty `dependency_ids`/`completed_dependency_ids` union onto its same-parent siblings still falls back to the raw bar unchanged either way.
|
||||
- An `acceptance_criteria` rewrite through `update()` with NO explicit `acceptance_criteria_ids` used to silently desync ids from text (or leave an empty id list, which the parent-coverage gate then reads as "no criteria to cover" — waiving coverage for the whole subtree). `_reconcile_ac_ids` (#682) closes this at the one chokepoint every rewrite path shares; the parent-coverage gate also self-heals an out-of-length/empty id list in place rather than returning early.
|
||||
- `_apply_dependency_lineage` is scoped to SAME-REPO dependencies only (`dep_task.project_id != ctx.project.id` short-circuits) — a cross-repo dependency edge (e.g. a MegaTask root-subtask in another project) has no shared git history to merge and is silently skipped; the dependency TIMING gate still holds the claim regardless of repo.
|
||||
- `TaskTable.orchestration_markers` is generic `JSON`, not `JSONB`. Any SQL predicate on a marker key must use `.as_string()` (or the JSON dialect's generic comparator), not `.astext`, which is JSONB-only and raises `AttributeError` at compile time. `list_open_docs_sync_tasks(version=...)` at task.py:1596 is the current example; the inline comment records the rationale.
|
||||
- Both cancel and terminal-completion now force-delete (`-D`) the task's LOCAL branch ref in the assignee's clone alongside the worktree — a completed task's PR was squash-merged (its local ref is never an ancestor of base, so a "safe" `-d` refuses unconditionally) and a cancelled task's work is discarded by decision, so the ref is spent either way. Skipped when the branch name coincides with an environment-ladder rung (`effective_environments`), which outlives any one task.
|
||||
@@ -164,6 +171,10 @@ stateDiagram-v2
|
||||
> (open PR #548, branch `feature/wave-2-hygiene-charts`, 2026-07-17) Local branch refs stop leaking: `_delete_task_branch_best_effort`/`_remove_task_worktree_on_terminal` now also force-delete the assignee's local branch ref (via new `WorkspaceService.delete_local_branch`) and rmtree the task's `.previews/{task8}` video-preview dir, both skipped for environment-ladder rungs. See `docs/map/worksession-git.md` for the paired `GitService.cleanup_stale_branches` sweep.
|
||||
>
|
||||
> `2e889c70` (#644, "work re-claims inherit an advanced upstream base"): a re-claim (pool release / reaper unclaim / escalation redirect / a dev's own `i_will_work_on` re-entry) reused whatever branch had been cut at the EARLIER claim, so any work that landed on the parent/base branch since then (e.g. a sibling cell merging into root, or UX/UI landing before BE/FE re-claims) never reached the reclaimed branch — silent divergence, avoidable conflicts at PR time. `_finalize_claim` now calls `_inherit_upstream_base` after resolving the work session, gated by the double check above; a conflict never fails the claim, it steers the dev to `sync_branch` via a transition note + `dev_notes`.
|
||||
>
|
||||
> `c4ba351a` (#681, "reachability-aware claim bar + sequence_held surfacing", 2026-07-24) The sequence-drift fix: `_claim_blocked_by_sequence` branches on `is_batch_root_subtask` so an independent same-parent dev-task stream can no longer phantom-hold behind an unconnected sibling that coincidentally shares a lower raw `stamp_wave_sequence` number; non-batch contexts route through the new pure `sequence_blocker_id` (real transitive predecessor via `dependency_ids ∪ completed_dependency_ids`). New `sequence_hold_reason` + a proactive gateway guard return `Envelope.sequence_held` instead of a bare `None` reaching the verb runner as a misdiagnosed `INVALID_STATE`. `is_pending_claim_blocked` extended to NEEDS_REVISION so both `give_me_work` offer paths never dangle a task the claim gate would reject.
|
||||
>
|
||||
> `3516d925` (#682, "reconcile acceptance_criteria_ids at the update chokepoint", same day) `create()` and `update()` both now stamp `acceptance_criteria_ids` through the new pure `_reconcile_ac_ids` (id-preserving for text-unchanged criteria, fresh id for new/reworded text, dropped id for a removed criterion) — every prior post-create rewrite path (task PATCH, prompter `update_live_draft`/`_patch_batch_child`/`update_live_batch`) had silently desynced or emptied the ids, and an empty id list silently waived the whole subtree's parent-coverage gate. The gate itself now self-heals an empty/out-of-length id list in place instead of returning early.
|
||||
|
||||
## Regression Risks
|
||||
|
||||
|
||||
Reference in New Issue
Block a user