Skip to content

Implement Self-Evolving Project Skills v2 run 17 - #895

Draft
adriandemian wants to merge 7 commits into
ralphx/ralphx/agent-88af9c08from
ralphx/ralphx/agent-b73874ac
Draft

Implement Self-Evolving Project Skills v2 run 17#895
adriandemian wants to merge 7 commits into
ralphx/ralphx/agent-88af9c08from
ralphx/ralphx/agent-b73874ac

Conversation

@adriandemian

@adriandemian adriandemian commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Added durable publication_pushed_sha storage to agent workspaces and threaded it through the domain entity, workspace preparation, and both repository implementations.
  • Introduced merged-workspace outcome classification that distinguishes coarse merged, clean merge, and merged-with-followups cases using the recorded pushed SHA and GitHub PR sync state.
  • Added plan-verdict history recording for accepted, declined, and revision-requested plan decisions, including a new plan_mode_revision_requested outcome class.
  • Wired the new history capture into automation plan judging, plan approval handling, question/ideation command flows, and PR merge reconciliation.

User Impact

  • Workspace publication data now retains the commit SHA that was pushed, which gives later reconciliation a stable reference point.
  • Plan decisions can now be persisted as durable history rows instead of only transient approval state.
  • Merged PRs can be classified more precisely when sufficient workspace and GitHub evidence is available; otherwise the existing coarse merged classification is preserved.

Technical Context

  • Added publication_pushed_sha to AgentConversationWorkspace, plus validation and repository support, and introduced a SQLite migration for the new column.
  • Added plan_verdict_history to create idempotent task outcomes from project, conversation, session, artifact version, actor, and verdict identity data.
  • Added agent_workspace_merge_classification and a terminal observation status override so merged PR observations can reflect clean and follow-up distinctions.
  • Updated scheduler and command handlers to record verdict history from the live plan-judging paths with artifact version context.

Risks / Follow-Ups

  • Merge refinement still falls back to the coarse merged status when the pushed SHA, workspace record, or GitHub sync evidence is missing or invalid.
  • The new persistence and verdict-history paths rely on all repository implementations staying aligned with the expanded workspace and task-outcome shapes.
View full plan

Spec §PR D4 — Merged-Clean and Plan-Verdict Capture

Goal

“Implement only Spec §PR D4 — Merged-clean and plan-verdict capture.”

Implement the authoritative D4 slice on the current merged D1–D3 base: retain the exact commit successfully pushed for each publication attempt, use authoritative GitHub evidence to refine an already-observed merge into clean versus follow-up outcomes without false upgrades, and append deterministic User/Judge/PlanImport verdict history while keeping the approved-plan projection approved-only.

Assumptions grounded in the specification and current code:

  • The persisted workspace publication status remains the coarse merged status; workspace_pr_merged_clean and workspace_pr_merged_with_followups are typed ledger refinements.
  • The authoritative comparison anchor is the commit actually pushed to the PR publication branch, compared with current GitHub PR/merge metadata through the production-resolved gh path. Any ambiguity, including squash cases the available metadata cannot prove, stays plain merged.
  • Existing approval transactions retain their current meaning. D4 observes their completed verdicts; it does not create a second approval writer or change approval-table semantics.
  • No C1 spawn-time skill injection work is included.

This is an architectural/stateful backend slice because it crosses persisted workspace state, every publication push seam, merge finalization/recovery, plan projection, and the typed outcome ledger.

Existing-Work Assessment

Evidence at current HEAD:

  • D1 is landed in src-tauri/crates/ralphx-domain/src/repositories/task_outcome_repository.rs: canonical {pr_number}:terminal dedupe, row identity preservation, class ranking, equal-rank evidence replacement, higher-rank upgrade, lower-rank no-op, and status derivation already exist.
  • D3 is landed through v20260723143416_typed_ledger_sources_classes_failure_fingerprints, TaskOutcomeSource, TaskOutcomeClass, and OutcomeLedgerService. The plan_mode source is live and non-terminal, so it is already outside the terminal PR lattice.
  • AgentWorkspaceOutcomeAdapter::record_pr_terminal already understands merged_clean and merged_with_followups, but current terminal observations and reconciliation emit only plain merged. D4 should supply evidence-backed classification, not recreate the adapter or lattice.
  • Plan verdict capture is partially present in src-tauri/src/commands/question_commands.rs: accepted user verdicts can reach the outcome ledger, and PlanApprovalActor::{User, Judge, PlanImport} already exists. Missing pieces are decline/revise/import coverage, actor/version-aware idempotency, a shared post-transaction helper, and projection-preservation proofs.
  • publication_pushed_sha and a dedicated repository setter do not exist. This is the one schema gap requiring an additive migration.
  • The PlanImport approval propagation owner at verified HEAD is src-tauri/src/http_server/handlers/external/ideation_start/start.rs; re-derive it plus the exhaustive push-call inventory with rg at implementation HEAD and record both in the tracker before production edits. Do not infer either from stale spec line anchors.

The PR description must include this assessment, the final callsite inventory, any anchor drift, requirements confirmed already landed, D4 gaps implemented, and explicit non-applicability of C1/UI/MCP work.

Traceability Note

Before production edits, create/update the ignored implementation tracker at .artifacts/specs/spec-pr-d4/tracker.md with the current HEAD/base, exact push and verdict producer inventory, and this mapping:

Controlling obligation Planned change Planned proof
Spec §PR D4: add publication_pushed_sha with a dedicated setter One additive workspace migration; domain entity; repository trait; SQLite and memory implementations Migration round-trip/backfill-null test; both concrete repo setter/read tests
D4: update every workspace push seam; clear on restart; handle integration/plan fenced pushes explicitly Centralize “successful publication push → exact branch OID → workspace setter”; wire each production push path only after success/fence; clear during canonical restart Table-driven push-path tests, failed-push/write absence assertions, restart stale-SHA test, integration/plan branch-role tests
D4: compare before branch deletion through resolved gh One shared classifier called by poller, external reconciliation, and terminal/recovery entry paths before cleanup Equal/different/null/stale/squash/gh-failure tests through production terminalization/reconciliation
D4: clean versus follow-ups without false upgrades Emit fine status only when GitHub evidence proves it; otherwise retain plain merged Clean, proven follow-up, ambiguity fallback, retry/re-entry, upgrade/no-downgrade tests
Adopted D1 dependency Reuse record_pr_terminal, {pr}:terminal, and resolve_task_outcome_upsert; do not add a second terminal dedupe mechanism Existing lattice tests plus focused merged→fine, fine→plain no-downgrade, equal-rank re-entry
Adopted D2/D3 dependency and canonical vocabulary Reuse typed source/class/evidence/link fields and existing cleanup/finalizer writers; add only missing plan_mode/revision_requested typed vocabulary if HEAD confirms absent Serialization/round-trip and production ledger tests; no outcome-class schema CHECK migration
D4: post-transaction plan ledger helper keyed by session+artifact+version+actor+verdict Introduce one deterministic helper over OutcomeLedgerService; encode the full stable identity in ledger linkage/evidence; exact duplicate delivery is idempotent while distinct actors/versions/verdicts append Duplicate delivery, two verdicts/session, actor separation, version separation, failed-write/retry tests
D4: User approve/decline, Judge approve/revise, propagated PlanImport Call the helper only after each owning transaction/propagation succeeds One production-entry test per actor/source/verdict, stale attempt and event-order tests
Adopted approved-only decision and convergence/changelog invariant Leave approval repository/schema/writer intact; revise/decline append history but never replace the last approved artifact or trigger judge auto-reapproval Approve projection test; revise/decline non-overwrite tests; judge revise no-auto-reapproval; absence assertions
Cross-cutting provider-neutral/legacy compatibility Nullable additive field; no harness-specific state; retain legacy workspace reads and existing ledger links Legacy row/read test and memory/SQLite parity
Cross-cutting backend-owned identity/MCP alignment Derive workspace/session/artifact/version/actor from trusted backend context; expose no run/orchestration identifiers or new MCP payload fields Command/service tests prove linkage without caller-supplied orchestration IDs; MCP dist unchanged unless inspection proves an existing source must change
Cross-cutting stateful false-success Fail closed on missing/stale reads; persist only after successful pushes/transactions; keep cleanup and projections safe under partial failure Failed reads/writes, stale attempt, race/re-entry, and suppressed-side-effect assertions
Origin-item and changelog adjudication D-lane origin item D4 after D1→D2→D3; approvals-approved-only reviewer correction; serialized canonical vocabulary PR traceability section cites Spec §PR D4, the D-lane dependency, and the approvals-approved-only adjudication; no C1 changes

Affected Files

Exact files are revalidated at implementation HEAD; bounded ownership follows current repository seams.

Migration and workspace persistence

  • Add src-tauri/src/infrastructure/sqlite/migrations/v<UTC>_agent_workspace_publication_pushed_sha.rs and sibling test: add nullable publication_pushed_sha TEXT without rewriting unrelated tables.
  • Update src-tauri/src/infrastructure/sqlite/migrations/mod.rs and the schema-version constant using the repository migration workflow.
  • Modify src-tauri/crates/ralphx-domain/src/entities/agent_conversation_workspace.rs: add the nullable field and preserve legacy/default construction.
  • Modify src-tauri/crates/ralphx-domain/src/repositories/agent_conversation_workspace_repository.rs: add a dedicated setter/clear contract rather than overloading unrelated publication updates.
  • Modify src-tauri/src/infrastructure/sqlite/sqlite_agent_conversation_workspace_repo.rs and src-tauri/src/infrastructure/memory/memory_agent_conversation_workspace_repo.rs: row mapping and parity implementation.
  • Extend the existing sibling repository/migration tests; do not add inline production-file tests.

Push capture and restart

  • Modify src-tauri/src/application/publish_resilience.rs: capture the exact local source-branch OID only after each successful push and persist it for the owning publication attempt.
  • Modify the owning restart module, currently src-tauri/src/application/agent_conversation_workspace_restart.rs: clear the SHA in the same canonical restart flow that resets publication state.
  • Inspect and wire all production callers of GitHubService::push_branch/push retry/fenced helpers under src-tauri/src/application/, including push_publish_branch, ensure_publish_base_pushed, ensure_plan_publish_branch_fresh, integration publication, plan publication, recovery/resume, and any handler-owned publish path. Record why each call does or does not own publication_pushed_sha; unrelated base-branch pushes must not overwrite the PR publication SHA.
  • Change src-tauri/src/domain/services/github_service.rs only if the established push abstraction must return the pushed OID. Prefer resolving the exact branch OID at the owning git seam over introducing harness-specific state.

Merge classification and terminalization

  • Add or extend one application helper beside the existing terminalization modules to classify merged as clean/follow-ups/plain from persisted pushed SHA plus authoritative GitHub metadata.
  • Modify src-tauri/src/application/agent_workspace_terminal_observation.rs, agent_workspace_terminalization.rs, agent_workspace_external_pr_reconciliation.rs, and pr_merge_poller.rs as current call graphs require so poller, recovery, reconciliation, ReviewPr/automation finalization, and re-entry use the same classifier before branch deletion.
  • Reuse src-tauri/src/domain/services/agent_workspace_outcomes.rs and src-tauri/crates/ralphx-domain/src/repositories/task_outcome_repository.rs; edit them only for a proven missing typed mapping/test, not to replace landed D1 behavior.
  • Use the existing production CLI resolver for gh; do not construct an ad hoc PATH lookup or turn SHA/branch input into a filesystem path.

Plan verdict history

  • Add a shared application/domain service helper over OutcomeLedgerService for deterministic post-transaction plan verdict capture.
  • Modify src-tauri/src/commands/question_commands.rs: route existing user acceptance and user decline through the helper after the owning transaction.
  • Modify src-tauri/src/application/automation/scheduler.rs: record Judge approve/revise verdict rows after transition_plan_judge_state, approve_current_plan_artifact, or set_plan_pending_instructions accepts the current artifact/version, including stored-verdict replay.
  • Keep src-tauri/src/application/automation/plan_judge.rs limited to parsing/typed-vocabulary support if plan_mode_revision_requested remains absent at implementation HEAD.
  • Modify src-tauri/src/http_server/handlers/external/ideation_start/start.rs for PlanImport approval propagation; record PlanImport verdict rows only after the approval clone/upsert succeeds. Re-check src-tauri/src/application/plan_reference_import.rs and related tests for additional import paths before editing.
  • Modify TaskOutcomeClass parsing/serialization only if plan_mode_revision_requested remains absent at implementation HEAD. D3 intentionally has no outcome-class DDL CHECK, so this should not require a ledger-table migration.
  • Leave plan_artifact_approval_repository.rs, its table schema, and its existing approved projection writer semantically unchanged; only pass committed identity to the ledger helper.

Tests and handoff artifacts

  • Extend focused sibling tests such as agent_workspace_outcomes_tests.rs, question_commands_tests.rs, SQLite/memory workspace repository tests, pr_merge_poller_tests.rs, and the relevant suite_agent_workspace/automation plan tests.
  • Update .artifacts/specs/spec-pr-d4/tracker.md throughout implementation; it remains ignored local state.
  • Update no frontend, plugin/MCP source, or user documentation unless current HEAD inspection proves D4 already exposes a directly affected surface. If MCP src/ is unexpectedly touched, rebuild and commit its distribution.

Data / State

Workspace publication SHA

  • Store a nullable 40-character commit OID as data, validating canonical hex shape at the setter boundary where the existing domain pattern permits.
  • The writer sequence is: successful push/fence → resolve exact pushed source ref OID → persist via dedicated setter. Never persist before push success.
  • A repeated successful push replaces the SHA for the same current publication attempt.
  • A restart clears it before a new publication attempt can reuse old metadata.
  • Integration/base-only pushes must not overwrite publication evidence for the PR head. Plan/integration fenced publication pushes must explicitly record the publication branch OID only after their fence succeeds.
  • Setter failure must not report publication success with stale evidence; preserve the existing typed failure policy and assert no incorrect fine terminal outcome.

Merge refinement

After an authoritative merged observation and before branch deletion:

  1. Read the current workspace’s persisted publication SHA.
  2. Query current PR head/merge metadata via resolved gh.
  3. If the evidence unambiguously proves the merged PR head equals the recorded pushed SHA, propose workspace_pr_merged_clean.
  4. If it unambiguously proves later head commits and the merge metadata is not squash-ambiguous, propose workspace_pr_merged_with_followups.
  5. If the SHA is absent/stale, metadata is missing, the actual merge is squash-ambiguous, or gh fails, retain workspace_pr_merged.
  6. Submit the proposed outcome through the existing terminal helper. D1 decides equal replacement, higher upgrade, and lower no-op; D4 must not special-case around it.
  7. Branch cleanup uses the existing proven terminal authority. A classification-read failure may reduce precision to plain merged but must not fabricate merge authority or reorder cleanup ahead of terminal recording.

Plan verdict rows

Each row uses:

  • source = plan_mode;
  • canonical outcome class plan_mode_accepted, plan_mode_declined, or plan_mode_revision_requested; add the revision-requested variant if it remains absent at implementation HEAD;
  • backend-derived project/task/session/artifact/version linkage;
  • actor user, judge, or plan_import;
  • a deterministic dedupe identity over session + artifact + version + actor + verdict;
  • evidence containing actor, artifact/version, verdict, and originating flow without caller-owned orchestration bookkeeping.

Exact duplicate delivery is a no-op/equal replacement according to the existing non-terminal outcome repository semantics; a different actor, artifact version, or verdict is a distinct historical row. The helper runs after the authoritative transaction. If ledger delivery fails after commit, preserve the committed projection/verdict, surface/log the failure according to the owning flow, and make retry safe through the same key.

The approved projection changes only through the existing approved writer. Decline/revise rows never clear, replace, or masquerade as the last approved artifact. Judge revise cannot recursively trigger or later be mistaken for judge approval.

Agent And MCP Surface

  • No new model-facing tool, schema, run ID, orchestration ID, or harness-specific field is needed.
  • All ledger identity is injected from backend-owned session/artifact/task context.
  • Claude/Codex and legacy persisted workspaces continue to use the same nullable domain field and repository contracts.
  • If inspection finds an existing MCP source callsite involved in PlanImport, retain its current surface and derive actor/version server-side; do not widen the payload.
  • Do not begin C1 or alter agent skill injection/grants.

UI / UX

No direct UI work is planned. Fine merge classifications and verdict rows are backend ledger data in D4; the existing approved projection remains the UI source for the approved plan. This prevents revise/decline history from presenting as an approved plan and avoids introducing a second visible approval state.

Progression Scenarios

  1. Clean publication: push succeeds, exact PR-branch SHA persists, GitHub later reports merged with matching authoritative head, terminal row upgrades from plain merged to merged-clean, retry remains one terminal row.
  2. Human/automation follow-up: later commit changes the PR head; non-squash GitHub metadata proves the difference, terminal row upgrades to merged-with-followups; a later coarse observation cannot downgrade it.
  3. Ambiguous merge: missing SHA, stale attempt, squash ambiguity, or GitHub lookup failure leaves plain merged. Cleanup follows existing merge authority; no fine class is fabricated.
  4. Restart/republication: restart clears the prior SHA; failed or unrelated fenced/base pushes cannot seed the next attempt; the next successful publication records its own OID.
  5. User approve then decline/revise history: approval projection remains the approved artifact; later decline/revision appends history only.
  6. Judge revise: one revision-requested row is written; duplicate delivery is idempotent, actor-separated user/import rows remain distinct, and no judge auto-approval is triggered.
  7. Plan import: propagated accepted plan retains its existing projection semantics and appends a PlanImport-attributed row with the imported artifact/version linkage.
  8. Partial failure: push/ledger/read failures do not create clean outcomes, stale metadata, duplicate rows, or projection rollback; safe retries converge.

Constraints

  • Follow CLAUDE.md, src-tauri/CLAUDE.md, and the stateful-workflow, task-state-machine, merge-recovery-consistency, Rust-test, CodeQL path-safety, multi-harness, production CLI, stable Rust, and PR-description rules.
  • Rebase the implementation branch on the latest configured automation base before edits/handoff and again before requesting review; preserve the exact configured base chain.
  • TDD first: add focused failing behavioral tests through production entry paths before production fixes.
  • One forward-only additive migration, using the project migration generator/validator and a timestamp later than D3.
  • Keep task status writes outside D4; if any status transition becomes necessary, use TaskTransitionService.
  • Use one terminal classifier and one plan-verdict capture helper; no repeated production wiring/branch logic.
  • New/modified Rust tests belong in sibling test files. Format/check each touched Rust leaf; do not broadly format mod.rs or run cargo fmt.
  • Run only focused tests/checks. After the final or aborted Rust test attempt, run cd src-tauri && cargo clean separately before handoff.
  • Preserve unrelated work and review the full diff against HEAD.
  • PR and commit subjects have no [codex] prefix. The PR body leads with context, user impact, decisions, and risks, then D4 traceability/existing-work/changelog assessment and concise validation.
  • Publish the branch, open the focused PR against the current automation base, enable automatic merge, and do not start C1.

Avoid

  • Reimplementing D1’s terminal dedupe/rank/status derivation or D3’s typed ledger.
  • Treating missing/read-failed/squash-ambiguous evidence as clean or follow-ups.
  • Recording the local working tree SHA before push success, or letting an unrelated base/integration push overwrite publication-branch evidence.
  • Deleting branches before the existing authoritative terminal/cleanup gate.
  • Adding a second approval table, changing approval semantics, clearing the approved projection on revise/decline, or allowing judge revise to become approval.
  • Session-only verdict dedupe that overwrites distinct versions, actors, or verdicts.
  • Caller-supplied orchestration identity, harness-specific branches, new MCP schema, UI scope, or C1 work.
  • Broad Rust/workspace validation, formatter churn, unstable std APIs, or filesystem sinks built from unchecked external state.

Decisions

  • Use one nullable workspace column plus a dedicated repository setter; no plan-ledger schema migration is expected.
  • Fine merge status is ledger-only; coarse workspace publication status remains compatible.
  • Classification is monotonic and evidence-based: precise only when proven, coarse on ambiguity.
  • Reuse the resolved production gh seam and D1 terminal adapter/lattice.
  • Use a deterministic composite verdict identity, with actor/version/verdict also stored as typed/evidence fields for auditability.
  • Keep approvals approved-only; verdict history is append-oriented and post-transaction.
  • No user-owned design decision remains: the authoritative spec resolves comparison authority, projection ownership, scope, and failure posture. Any newly discovered repository ambiguity is resolved by current owning patterns and recorded in the tracker/PR.

Proof Obligations

  • Every production publication push callsite is inventoried and either records the exact publication-branch OID after success or is explicitly proven unrelated.
  • SQLite and memory repos have parity; legacy rows deserialize with None; restart clears stale evidence.
  • Equal, later-head, absent, stale, squash-ambiguous, and GitHub-failure cases produce exactly the specified terminal class.
  • Re-entry preserves one canonical terminal row; merged-clean/followups never downgrade to plain merged or each other incorrectly.
  • Classification failure cannot cause premature deletion or a false success.
  • User approve/decline, Judge approve/revise, and PlanImport each write correctly attributed/versioned/linkable history.
  • Same five-part verdict identity is idempotent; two verdicts in one session and the same verdict by distinct actors remain distinct.
  • Approve can update the existing approved projection; decline/revise cannot overwrite it. Judge revise cannot auto-reapprove.
  • Post-transaction ledger write/read failures and stale deliveries preserve authoritative state and converge on retry without duplicate effects.
  • No task transition bypass, CodeQL-unsafe path sink, harness regression, MCP surface drift, plugin dist drift, UI change, or C1 change is introduced.
  • The PR body includes exact Spec §PR D4 traceability, D1–D3 dependency reuse, origin-item mapping, adopted approved-only decision, convergence/changelog adjudication, current-base assessment, risks, and validation.

Testing Strategy

Write focused failures first, then implement:

  1. Migration/repositories
    • Migration upgrades a legacy workspace row with NULL SHA and preserves all existing fields/indexes.
    • Dedicated setter round-trips and overwrites in SQLite and memory; clear returns None; invalid/stale target does not mutate.
  2. Push/restart
    • Each inventoried publication push persists the exact pushed branch OID only after success.
    • Failed push, failed fence, OID-read failure, or setter failure has explicit error/absence behavior.
    • Integration/base-only push cannot overwrite the PR publication SHA; plan/integration publication fence records the correct owning branch.
    • Restart clears the SHA before reuse.
  3. Merge terminalization
    • Matching authoritative evidence → merged-clean.
    • Proven later non-squash head → merged-with-followups.
    • NULL/stale SHA, squash ambiguity, missing metadata, and resolved-gh failure → plain merged.
    • Poller, reconciliation, recovery/finalization, and retry entry paths converge through the same helper.
    • Plain merged upgrades to a proven fine class; fine classes do not downgrade on coarse/stale re-entry; equal delivery is idempotent.
    • Failed classification/ledger write asserts absent fine outcome and preserves cleanup safety.
  4. Plan verdicts/projection
    • User approve and decline; Judge approve and revise through live scheduler handling and stored-verdict replay; PlanImport propagation through the external ideation import handler.
    • Exact duplicate delivery; two verdicts/session; same verdict across actors; new artifact version.
    • Revision/decline preserve last approved projection and do not write an approval; judge revise cannot auto-reapprove.
    • Approval/verdict transaction failure writes no ledger row; post-commit ledger failure preserves authoritative projection and retries once.
    • Stale artifact/version and reordered delivery cannot overwrite the current approved projection.
  5. Focused validation
    • Run exact lib filters for touched domain/application modules with --features test-utils.
    • Run only the affected suite_agent_workspace and suite_pr_github nextest expressions.
    • Run the relevant automation/plan command test target for verdict paths.
    • Run python3 scripts/validate_sqlite_migrations.py.
    • Run rustfmt --edition 2021 --check <each touched leaf.rs>.
    • Run python3 scripts/check-layering.py only if module/import boundaries change.
    • If any Rust test starts, finish with a separate cd src-tauri && cargo clean.
    • Review git diff --check, the complete diff against HEAD, branch freshness, PR base/head, and auto-merge state.

Exact cargo filters are selected from the final test symbols after TDD files are added; do not fall back to broad lib/workspace suites.


Generated by RalphX


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…to ralphx/ralphx/agent-b73874ac

# Conflicts:
#	src-tauri/src/application/publish_resilience_tests.rs
#	src-tauri/src/application/services/pr_merge_poller.rs
#	src-tauri/src/commands/ideation_commands/ideation_commands_restart.rs
#	src-tauri/src/commands/question_commands.rs
#	src-tauri/src/http_server/handlers/agent_workspaces/mod.rs
#	src-tauri/src/infrastructure/sqlite/migrations/mod.rs
A stored or fresh judge Approve for plan artifact version N could be applied
to a later version of the same artifact because the guards compared only
evaluated_artifact_id. The backend now stamps evaluatedArtifactVersion into
the normalized verdict at invocation time and both the fresh and stored
apply paths discard verdicts whose version does not match the current
artifact; legacy stored verdicts without a version fail closed.
Workspace Review blocker B1: the plan-mode decline capture reused the accept
path's ledger identity (source_ref_kind="planning_session" /
source_ref_id=planning_session_id). PlanMode rows are outside the terminal-PR
rank lattice, so resolve_task_outcome_upsert overwrote the earlier verdict in
place and a decline followed by an accept in one planning session destroyed the
decline.

- Extract the length-prefixed component encoder out of plan_verdict_ledger and
  key plan-mode proposal rows on session + verdict class through it, so the two
  writers cannot drift apart. Repeat delivery of one verdict stays idempotent.
- Cover the decline path: detector unit tests, mutual exclusivity with accept,
  and a production-entry regression proving accept and decline both survive
  (falsified: it fails with the old session-only key).
- Remove the duplicated publication_pushed_sha = NULL merge residue from the
  restart SQL and align restore_after_restart (SQLite + memory + trait docs)
  with the production column set, with a production-path restart assertion.
- Decline path: log repository read failures instead of silently returning,
  derive project_id the same way the accept path does, and document the reason
  source difference.
- Note the retired "accepted"/"declined"/"revision_requested" outcome-class
  strings intentionally fall through to Other(...) and are not backfilled.

Migration edge: rows already written under the bare planning_session_id key are
unreachable by the new key. The next verdict for such a session inserts a new
row, leaving one orphaned legacy row per affected session; not backfilled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant