fix: lifecycle state machine hardening (closes #411, closes #412, closes #424, closes #426, closes #434, closes #443, closes #445, closes #432, closes #433, closes #423)#462
Draft
0xLeif wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
❌ Corvin says...
_
<(;\ .oO(oh no...)
|/(\
\(\\
" "\\
"Even the dumpster of code seems empty today."
CI Summary
| Check | Status |
|---|---|
| Validate action.yml | ✅ Passed |
| Packaged Action Consumer | ❌ failure |
| Dependency Audit | ✅ Passed |
| Code Coverage | ❌ failure |
| Format Check | ❌ failure |
| Docs Site | ✅ Passed |
| Spec Validation | ❌ failure |
| Tests (build, test, clippy) | ❌ failure |
| VS Code Extension | ✅ Passed |
Powered by corvid-pet
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.
This PR currently contains 11 of 12 changed files.
src/change.rs(860KB) could not be uploaded through the automation channel and must be added to this branch (expected git blob SHA7252c4190a306683e3fdbba4116ae4f1312a652b; full file and a 71KB patch vs main are attached to the task report / available from the author). The branch will not compile until it lands. Everything else is byte-verified against the validated local commit.Summary
Consolidated PR for the W3 lifecycle workstream — the fixes interleave inside the same lifecycle files (src/change.rs, src/commands/change.rs), so they land together. Validation at the full local HEAD: 1734 unit + 228 integration tests pass,
cargo clippy -- -D warningsclean, only failure is the pre-existing root-onlychange::tests::non_git_walk_skips_volatile_trees_but_fails_on_relevant_walk_errors(fails on main too when run as root).Issue → fix → tests
uncovered_meaningful_pathsno longer flattens git stderr — newgit_output_allow_empty_resultpreserves it; error names cause + remediation ("SDD coverage needs a comparison base: no remote default ref found and no recorded base commit; add a remote … or runspecsync change adopt"). Tests:missing_comparison_base_error_names_cause_and_remediation,unreachable_recorded_base_error_names_the_base.stray_archive_directory_without_state_is_skipped_with_warning.reapproval_discards_verification_warningnaming the discarded evidence + re-verify remediation (refusal impossible: 12 existing tests assert the transition itself). Test:reapproving_verifying_change_warns_that_verification_is_discarded.answerrejects unknown keys (names the advertised set) and empty answers; actors trimmed/single-line vianormalize_identity;validate_module_namerejects surrounding whitespace;create_changerejects nonexistent--spec(registry-aware). Tests:answer_rejects_unknown_question_keys_with_advertised_set,answer_rejects_empty_answers,approval_actor_is_trimmed_and_must_be_single_line,create_change_rejects_nonexistent_spec_reference.extra: BTreeMap<String, Value>flatten-passthrough on ChangeRecord/ApprovalLedger/VerificationRecord/VerificationAttemptLedger (unknown fields survive rewrites); uniformschema_version != 1gating with remediation; serde errors name the file path. Tests:unknown_state_fields_are_preserved_on_rewrite,load_change_rejects_unsupported_schema_version_with_remediation,invalid_ledgers_name_their_file_path.ChangeListing/list_changes_with_errors— healthy records still listed, one error row per malformed workspace, non-zero exit; status printsDependencies:; corrupt archived evidence → non-zero. Tests:list_changes_with_errors_keeps_healthy_records_and_reports_malformed_workspaces,change_list_surfaces_malformed_workspaces_and_exits_nonzero,change_status_prints_dependencies,change_status_fails_on_corrupt_archived_evidence. (Item 2, stuck "next: verify" label: not reproducible — label is state-machine driven; deferred with justification.)--enforcement warnexits 0 on stale findings;--threshold 0off-by-one fixed (behind > 0 && behind >= threshold); add-then-revert commit pairs no longer count as drift (byte-identical short-circuit); stale-input errors name the offending inputs. Tests:stale_threshold_zero_passes_when_in_sync_and_fails_on_real_drift,stale_warn_enforcement_exits_zero_despite_drift,stale_ignores_add_then_revert_commit_pairs,stale_definition_approval_error_names_the_restore_escape,stale_project_input_digest_names_the_offending_input.--enforcement warn;adopt --dry-runvalidates--source. Tests:adoption_base_commit_is_the_coverage_diff_base_on_local_only_repos,adopt_dry_run_validates_the_source,sdd_errors_honor_enforcement_warn_exit_semantics.project_input_digestexcludes the change-sequence ledger (bookkeeping, not a delivery input) sochange newno longer stales every in-flight change; reopen remediation strings print the mandatory--actor/--reasonflags; corrupt transaction journal error names the file + recovery. Tests:creating_another_change_does_not_self_stale_in_flight_verification,corrupt_transaction_journal_names_the_file_and_recovery.--digestnow optional (resolved from the predecessor's signed acceptance manifest); unmerged predecessor → "not merged into this branch's history" with remediation; rejected covering successors surface in the diagnostic with the exact failing predicate. Tests:change_supersede_resolves_the_entry_digest_automatically,supersede_names_an_unmerged_predecessor,rejected_covering_successor_diagnostic_names_the_failing_predicate.Deferred
Closes #411, closes #412, closes #424, closes #426, closes #434, closes #443, closes #445, closes #432, closes #433, closes #423