Repository navigation
Record thirdshift version and failure attribution, with a Where runs failed drilldown (#2067) - #2083
Merged
Merged
Conversation
…drilldown (#2067) Command records keep thirdshift_version at start and stopped_at with a failure_category (held, waiting, crashed, stage_failed) at a failure ending. Older records recover their version from Session traces through the retained Session-signals cache and fall back to their last stage and died or failed. metrics and /metrics filter by --version / version=, break outcomes down by version, mark version (and, when narrowed, Harness and Model) transitions on the timeline, and group Failed Commands as Where runs failed, linking each cluster and Failed bucket to History filtered to those Commands and each name to its details.
…he view, failed_commands in JSON, Ending type (#2067)
This was referenced Nov 12, 2026
Closed
Merged
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.
Summary
Command records now say which
thirdshiftversion ran them and, when they fail, where and how they stopped. Metrics can be sliced by version, and every failure cluster links through to its Commands.The drilldown link names the cluster and the page's own filters, not the Commands in it. So it stays short however many Commands failed: a 120-Command cluster used to need a 13.8 kB URL.
New modules:
src/logs/metrics/failures.rs(Where runs failed) andsrc/logs/metrics/versions.rs(version breakdown and transitions).failed_run::categoryclassifies the typed error;recovery::Stage::recordedmaps a Recovery stage to Command record stage words.Closes #2067
Evidence
Execution evidence
tests/metrics.rstests, run against the base branch's code (origin/issue-2036worktree with this PR'stests/metrics.rs). Command:cargo test --test metrics -- historical_versions a_narrowed where_runs_failedcargo test --test console failure_drilldown_links_stay_within_a_proxy_request_linewhere_runs_failed_and_failed_buckets_open_the_matching_commands_in_history:cargo test --bin thirdshiftcoversa_command_records_its_version_at_start_and_where_a_failure_stopped_at_its_end(RecoverySelf-merge+MergeHold→held; no Recovery → last stage +stage_failed; plan limit → nothing) andthe_failure_category_comes_from_the_typed_error_not_its_words. Both pass.cargo test --no-fail-faston this branch: every target passes excepttests/process/findings.rs::merged_fix_is_rechecked_after_a_later_fix_fails. That test fails the same way on the base branch: I rancargo test --test process merged_fix_is_recheckedin a detachedorigin/issue-2036worktree and gottest result: FAILED. 0 passed; 1 failed.npm test --prefix console: 201 pass, 0 fail.npm test --prefix site: pass.npm run docs:check --prefix site: clean.Visual evidence
/metrics?window=7dwith a fixture of 21 Ticket runs across twothirdshiftversions, some recording failure attribution and some falling back.Desktop 1440×900:
Mobile 390×844 (the new tables scroll inside their own regions; the page does not overflow, as checked by
console/tests/metrics.test.cjsin every Theme):Review
The
thirdshift-code-reviewreviewers worked againstrefs/remotes/origin/issue-2036at ee55846: Standards raised 8 findings, Spec raised 4. Both axes read every changed file; the Spec axis needed one follow-up for two files.site/docs/index.htmlwas excluded as generated output:npm run docs:check --prefix siteis clean, and both reviewers revieweddocs/guide.mdinstead. The fixes in 69ab184 came after the review and touch only files the reviewers had already read.Addressed:
outcomes[].failed_commandsis now in the JSON, so the CLI and API can name what the page links.failed_commands.Stopped.recordedis nowEnding::recorded().Ending { Recorded(FailureCategory), Died, Failed }replaces the tuple and strings.CommandRecord::last_stage.query_valuesis gone. Abarmacro is shared by both tables.Class::Failed.Dimension::label.href="/metrics?version={{ version|urlencode }}", which drops them. P2's assertion now passes, with&in place of&because that is how Askama escapes&.Unaddressed findings
Standards
outcome=andrepository=filters are already page-only (src/console.rs:1409, read withquery_value;thirdshift status --local --all --jsontakes neither). The drilldown also has a CLI path:metrics --jsonnow lists every cluster's and bucket's selectors (where_runs_failed.rows[].commands[].selector,outcomes[].failed_commands) forthirdshift show <selector>. Whether History's filters need a CLI twin is a call for the Day shift, so I filed it as History filters (outcome, repository, Metrics failure drilldown) have no CLI twin #2084.CommandRecord.stopped_atis aString, notStageName. Declined. Persisted stage names are deliberately strings so they stay tolerant of new stages (src/logs/command_record.rs:246, "persisted names stay tolerant of new stages").stages[].nameis stored the same way, and the fallback compares against those strings.FILTERSconstant (src/console/metrics.rs).version_recoveredfield sits on the persisted record. Declined. It follows the existing precedent in the same struct,#[serde(skip)] pub end_time_estimated: bool("Reader-only provenance",src/logs/command_record.rs:112).Spec
interruptedending that nobody asked to stop counts as Failed (src/logs/metrics/outcomes.rs:84-87), so it needsstopped_atandfailure_categoryto be attributed.CommandRecord::finishcannot tell the two apart: a Stop request is a separate file, read bylogs::stop::requested. A stopped Command's attribution never reaches Where runs failed, which reads Failed Commands only.docs/guide.mddocuments that interrupted endings record it.Note from the Spec review:
stopped_atuses the Recovery stage in Command record stage words, which is coarser than the recorded stages (Implementation and Resume both becomeimplement; Push becomespull request). A new record and an older fallback record can therefore name the same failure differently.Security review outcome
No unaddressed introduced findings.
Merge Danger
Door: two-way
The new record fields are optional and additive (
skip_serializing_if = "Option::is_none"). Older binaries ignore them, and older records stay unchanged on disk.Blast Radius: contained
service.versionfield invalidates nothing: the retained Session-signals cache is already keyed by executable identity.thirdshift_version, including kinds without Run metrics. That happens once per trace per binary, and reads after that use the cache./metricsJSON gainswhere_runs_failed,versionsandoutcomes[].failed_commands.Built with claude 2.1.314 · opus · default effort