make-hera-plan-living: status-trust + plan-mutation verbs + DAG-authoritative docs (BREAKING hera_send)#795
Merged
Merged
Conversation
Living plan-DAG: required synchronous send-status (+failed role-status), gater re-arm + recovery notice, plan-mutation verbs (update/unblock/cancel), DAG-authoritative skill. Adopt + observed-reopen + wedge-notice cut per devil's-advocate. 3 phases, each its own PR.
…se, rail red ✕) - schema.go: widen hera_role_status.status CHECK to include 'failed' - db/hera.go: add HeraStatusFailed constant; refactor shared rollHeraWorkerToReviewInner (bool stampReadyToClose param); new RollHeraWorkerFailed (in_review, no ready_to_close stamp) - mcp/hera.go: toolHeraStatus accepts 'failed' (error names all 5 values); HeraStore interface adds RollHeraWorkerFailed; worker reporting 'failed' routes to RollHeraWorkerFailed (D2) - widget/rolestatusicon.go: RoleStatusInputs.Failed field + '✕' red case in RoleStatusIcon, precedence below NeedsInput above Done - tui/hera/rail.go: roleStatusInputs sets Failed from HeraStatusFailed - Tests: hera_failed_test.go (db + mcp), widget + rail tests updated/extended 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Extract applyRoleStatus helper (DRY): hera_send and hera_status now share one path for status validation, upsert, meta mirror, and worker task roll (done→in_review+ready_to_close, failed→in_review/no-ready_to_close) - hera_send gains optional status param; REQUIRED for worker/freelance senders: missing status returns a hard error naming all five valid values and sends nothing; status is applied synchronously before message send (D1); soft-fail on apply error never blocks the send; coordinator status remains optional - Update hera_send tool description and schema to document the requirement - Update all existing worker hera_send call sites in tests to include status - New hera_send_status_test.go: 7 tests covering worker-no-status rejection, freelance rejection, status=working applied synchronously, status=done rolls task to in_review+ready_to_close, status=failed rolls to in_review without ready_to_close, coordinator no-status succeeds, delivery-independent apply 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…notice 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…gater cancelled-is-non-gating - schema.go: add cancelled_at TEXT + idx_hera_roles_cancelled to hera_roles; add idempotent ALTER TABLE hera_roles ADD COLUMN cancelled_at TEXT migration (same pattern as nuked_at/base_branch) so pre-existing DBs migrate automatically - hera.go: add CancelledAt *time.Time to HeraRole struct; update scanHeraRole to scan 11 columns (cancelled_at last); update all five SELECT column lists on hera_roles to include cancelled_at (ListHeraRoles, ListHeraRolesByKind, heraRoleByID, heraRoleByActiveName) - hera_plan.go: ListHeraPlannedNodes adds AND cancelled_at IS NULL; add RemoveHeraBlock (idempotent DELETE), UpdateHeraPlannedNode (prompt + optional project, preserves project on empty string), CancelHeraPlannedNode (COALESCE idempotent cancelled_at stamp); uxlog via slog on each mutation - heragater.go: blockerOutcome checks CancelledAt != nil FIRST, returning blockerDone — a cancelled planned blocker is treated as satisfied so its dependents can materialize; placed before the never-bound/working inference to prevent a cancelled never-bound node from blocking dependents forever Tests: 11 new db tests (RemoveHeraBlock x3, UpdateHeraPlannedNode x2, CancelHeraPlannedNode x4, migration round-trip); 3 new gater tests (CancelledNodeNeverMaterializes, DependentOfCancelledBlockerBecomesReady, CancelledBlockerAmongMultiple); migration test extended with cancelled_at column 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
… MCP verbs Three coordinator-only plan-mutation verbs (D5, make-hera-plan-living): - hera_plan_node_update: edits prompt/project on a planned node; rejects materialized nodes (HeraRoleHasBinding guard); requires at least one of prompt or project. - hera_unblock: drops a hera_blocks edge; idempotent on missing edges. - hera_plan_node_cancel: stamps cancelled_at; excludes from gater; keeps role visible for plan rendering; rejects materialized nodes. All three are guarded by heroPlanCoordinatorGuard (non-coordinator rejected). Adds HeraRoleHasBinding, UpdateHeraPlannedNode, CancelHeraPlannedNode, and RemoveHeraBlock to the HeraStore interface. Updates heraToolDefs (12→15) and the tools/list assertion. 11 new tests cover all scenarios from the spec. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
UpdateHeraPlannedNode built a static SET clause for the project!='' branch that always included prompt=?, overwriting the stored prompt with empty when the caller only supplied a project. Now the SET clause is built dynamically: prompt=? and argus_project=? are appended only when the respective input is non-empty, so each field is preserved independently. New db-level tests assert: - project-only update preserves existing prompt (regression case) - both-fields update sets both Strengthened MCP-level TestHeraPlanNodeUpdate_EditsProject to assert the prompt survived the project-only edit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add StateCancelled to planview.State enum with grey ✕ glyph (ColorDimmed) and distinct style from StateFailed (red ✕, bold). Updates all three switch statements (Glyph/Label/style) and the groupCounts legend list. - Add Cancelled bool to RoleView; set from role.CancelledAt != nil in buildRoleView alongside the existing Planned discriminator. - planNodeState: check Cancelled before Planned so cancelled nodes render StateCancelled (grey ✕) even when they were never materialized. - planNodeIcon: return nil for StateCancelled (State overlay handles rendering). - README: document hera_plan, hera_plan_node, hera_block, hera_plan_node_update, hera_unblock, hera_plan_node_cancel in the Reference MCP tools table. - Tests: render_test.go covers glyph/label/style distinctness + chip draw + groupCounts inclusion. plan_test.go covers cancelled projection to StateCancelled, node list retention (not dropped), Cancelled-wins-Planned priority, and nil Icon for cancelled nodes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
… plan-DAG 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…sting DBs
Rebuilds hera_role_status with the widened CHECK ('failed' added), preserving rows. Fresh DBs are already correct via schema.go CREATE; this is only for in-place upgrades of an existing ~/.argus/data.sql (SQLite can't ALTER a CHECK).
…#795 rebase) DRN's archive pass rewrote the Status-icon precedence requirement (4-tier -> 6-tier + BUG-003 spinner-from-real-activity + new scenarios). Re-layer the failed red ✕ addition onto DRN's version instead of clobbering it with the stale 4-tier text.
beefdaf to
91026d2
Compare
Merging this branch changes the coverage (3 decrease, 3 increase)
Coverage by fileChanged files (no unit tests)
Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code. Changed unit test files
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes the hera role-status + plan-DAG a continuously-reconciled, living source of truth — the fix for why the plan-DAG goes stale in practice (dogfooding feedback). Built in 3 phases on one branch.
hera_sendnow requires astatusarg. Existing coordination flows must pass status. (Repo policy: breaking changes are fine, single user.)~/.argus/data.sqlonly): the newfailedstatus widens a SQLite CHECK that can't beALTERed. Before deploy, daemon stopped, runscript/migrate-hera-failed-status.sh(backs updata.sql, rebuildshera_role_statuspreserving rows). Fresh DBs need nothing.Phase A — status trust (the "dead DAG" fix)
Worker
hera_sendapplies a required status synchronously, so a finishing worker actually advances the gater (previously the done-signal lived in prose). Newfailedrole-status (rail red ✕). Gater re-arms on blocker recovery + one-time "unblocked" notice.Phase B — create-only → living
New coordinator verbs
hera_plan_node_update/hera_unblock/hera_plan_node_cancel(MCP surface 12→15). Cancelled nodes render grey ✕ and stop gating; dependents proceed.Phase C — docs/authority
hera SKILL states the plan-DAG is the source of truth with a live coordinator binding (harness TaskCreate defers). README/gotchas updated; required
hera_sendstatus + verbs + failed status documented.Quality
.claude/reviews/2026-06-21/).--new-from-rev→ 0 issues; build + full test surface green;openspec validate make-hera-plan-living --strictvalid. Rebased clean onto current master (feature-only, 39 files).Parked follow-ups (non-blocking)
hera_role_status.statusCHECK (Go already validates the enum) so future fresh DBs never hit the migration trap — left for author sign-off, not applied.ready_to_close(rail can briefly show review-✓ over a reopened worker) — ~5-line follow-up.🤖 Generated with Claude Code