Skip to content

fix(docs): anchor release dates to git tags and replace the release guards - #183

Open
flyingrobots wants to merge 4 commits into
mainfrom
docs/release-date-guards
Open

fix(docs): anchor release dates to git tags and replace the release guards#183
flyingrobots wants to merge 4 commits into
mainfrom
docs/release-date-guards

Conversation

@flyingrobots

Copy link
Copy Markdown
Owner

Plain-English Walkthrough

TL;DR

Every release date recorded in this repository described a plan rather than what
shipped: the changelog headings ran to 2026-11-04 while every tag was cut
between 2026-06-21 and 2026-06-30. The test meant to prevent exactly that could
not have caught it, because it compared two generated copies of one field
against each other and never consulted the tags.

This corrects all eleven dates across four surfaces, and replaces the guards
with cargo xtask release-dates, which reconciles the recorded dates against
git for-each-ref refs/tags. Net −587 / +525 across 19 files: eleven
near-duplicate tests plus a tautological guard become four real ones and a gate
step.

No library, schema, or golden artifact behavior changes. No issues are closed by
this PR.

Walkthrough

The dates described a schedule, not a history

Every release heading in CHANGELOG.md was months later than the tag that
published it [claim:date-drift, confidence:1.00]:

Version Before Tag (actual)
v0.9.0-alpha.1 2026-10-07 2026-06-28
v0.10.0-alpha.1 2026-10-21 2026-06-29
v0.11.0-alpha.1 2026-11-04 2026-06-30

These are not typos. release-prep writes the heading from a target_date
field at scaffold time, and nothing back-fills the real date after tagging. The
recorded dates were a planned biweekly cadence; the releases shipped roughly
four months early. Keep a Changelog, which CHANGELOG.md claims to follow,
defines that heading as the release date.

All eleven now match their tags across four surfaces: the changelog headings,
the target_date fields in policy.toml, the Target date: lines in
docs/releases/*.md, and the xtask guards that pinned them. target_date
keeps its field name but now holds the real publication date, so
RELEASE-REQ-008 is restated to say so.

Why the existing guard could not have caught it

alpha_changelog_dates_match_release_policy asserted that changelog dates
equalled policy.toml target dates. Both are generated from the same field, so
the assertion compared a copy against its own source
[claim:guard-tautology, confidence:0.95].

The diagram below shows why that arrangement is unfalsifiable: every value the
guard compared flows out of a single origin, and the only independent record of
when a release happened was never an input.

flowchart LR
    TD["policy.toml<br/>target_date"] -->|release-prep writes| CL["CHANGELOG.md<br/>heading date"]
    TD -->|release-prep writes| RN["docs/releases/*.md<br/>Target date:"]
    TD -.->|"old guard compared<br/>source against copy"| CL
    GIT["git tags<br/>actual publication date"] -.-> NEVER["not an input to<br/>any assertion"]
Loading
Caption: One source, two copies, and an unconsulted authority
  1. target_date is written once at scaffold time by release-prep.
  2. The changelog heading and the release-notes line are both generated from it.
  3. The old guard compared one of those generated copies against that source.
  4. The git tag, the only record of when publication actually occurred, was never
    an input to any assertion.

Two values written from one source always agree, including when that source is
wrong. The guard stayed green through four months of drift across all eleven
releases and only failed once a human corrected one side by hand. It detected
intervention, not incorrectness.

The nine release_policy_tracks_v0_N_boundary tests (plus v0_2) had a
separate defect: they matched substrings against the whole policy file rather
than the release's own block. Setting v0.3's target_date to 1999-01-01
leaves release_policy_tracks_v0_3_boundary passing, because v0.4 carries the
same date string [claim:substring-false-pass, confidence:1.00]. Releases tagged
on the same day legitimately share dates, so that is the normal case rather than
a corner case. They were also roughly 250 lines of frozen-history boilerplate,
auto-written by a generator, asserting that a static file still contained
strings someone had typed.

The replacement

The new check compares recorded dates against the tags, so the reference lives
outside the system that writes the dates.

flowchart LR
    GIT["git for-each-ref<br/>refs/tags"] --> R{{"reconcile_release_dates<br/>(pure)"}}
    POL["policy.toml<br/>target_date"] --> R
    CL["CHANGELOG.md"] --> R
    RN["docs/releases/*.md"] --> R
    R -->|date contradicts tag| D["drift → fails gate"]
    R -->|surface absent| G["gap → reported, passes"]
Loading
Caption: Reconciliation inputs and the two outcome classes
  1. Tag dates enter as the reference, not as one more comparable copy.
  2. All three recorded surfaces are compared against that reference.
  3. A recorded date that contradicts its tag is drift and fails the gate.
  4. An absent surface is a gap: reported on stdout, does not fail.

The drift / gap split is not cosmetic. Running the check for the first time
flagged that v0.1.0-alpha.1 has no policy block, which is true, and is
history, because that release predates the structured policy. A check that fails
on correct history gets switched off, so absence is reported without blocking
while contradictions still fail.

Splitting the pure reconcile_release_dates from the I/O in release_dates
matters for CI. ci.yml runs cargo test --workspace behind an
actions/checkout with no fetch-depth, which is a shallow clone without tags
[claim:ci-shallow, confidence:0.95]. The unit tests therefore take already-read
inputs and need no git, while the git-dependent reconciliation runs in
cargo xtask verify and in the release workflows, which do set
fetch-depth: 0.

Before After
alpha_changelog_dates_match_release_policy, hardcoded 10-row date table cargo xtask release-dates, zero hardcoded dates
10 × release_policy_tracks_v0_N_boundary, file-global contains() 1 × release_policy_blocks_are_structurally_complete, block-scoped
release_policy_block_parsing_scopes_fields_to_their_own_release
reconcile_release_dates + 2 hermetic tests

release-prep no longer scaffolds Rust test stubs or changelog date guard
entries, and policy.toml's scaffold_outputs drops the two removed entries.
Per-release scope and non-goal content is now reviewed rather than
string-tested, matching the repo's own rule in
docs/topics/documentation/test-plan.md that policy detail is not encoded as a
Rust test; the ten affected requirement and test-case rows move to policy
status accordingly. That is a reduction in claimed coverage matching a
reduction in actual coverage that was always there.

Verification and known gaps

Both failure modes were negative-tested before the check was wired in.
Corrupting only the changelog date, which is the exact drift the old guard slept
through, and corrupting a single block's target_date each fail with a message
naming the tag and both dates [claim:new-check-catches, confidence:1.00]. The
full local gate passes on this branch against current main
[claim:gate-green, confidence:1.00].

Two gaps are recorded in the release-process test plan rather than left implicit:

  1. next_release_target_date still seeds the next value as last entry + 14
    days
    , which from the realigned history computes 2026-07-14, already past
    [claim:stale-seed, confidence:0.95]. release-prep needs an explicit or
    clock-derived date. This now fails loudly at release time via
    release-dates instead of silently baking in another wrong date. Choosing
    the replacement seeding is follow-up work, not part of this PR.
  2. Nothing mechanically checks that a block's declared scope matches what the
    release actually shipped. That was equally true before; the removed tests
    only checked that the strings were present.
Appendix: Citations
Claim Evidence Confidence Notes
claim:date-drift git for-each-ref --format='%(refname:short) %(creatordate:short)' refs/tags → v0.9.0-alpha.1 2026-06-28, v0.10.0-alpha.1 2026-06-29, v0.11.0-alpha.1 2026-06-30, against the pre-change headings 2026-10-07 / 2026-10-21 / 2026-11-04 1.00 Annotated tag creation dates versus the recorded headings.
claim:guard-tautology xtask/src/release_prep.rs#199@89ca929a writes ## [{tag}] - {target_date}; xtask/src/release_prep.rs#251@89ca929a writes Target date: {target_date}; the removed guard compared the first against its own source field 0.95 Source inspection of the generator; no independent executable witness of the historical false negative.
claim:substring-false-pass Reproduced against docs/topics/release-process/policy.toml before this change: rewriting only v0.3's target_date to 1999-01-01 left every assertion of release_policy_tracks_v0_3_boundary satisfied, because v0.4 supplies the expected target_date = "2026-06-24" string 1.00 Executed reproduction against the committed policy file.
claim:new-check-catches release_date_reconciliation_reports_drift_and_gaps at xtask/src/tests.rs#2863@89ca929a; release_date_reconciliation_accepts_dates_matching_their_tags at #2916@89ca929a; release_policy_block_parsing_scopes_fields_to_their_own_release at #2825@89ca929a; release_policy_blocks_are_structurally_complete at #2760@89ca929a 1.00 Hermetic tests over reconcile_release_dates, plus the pinned false-pass regression.
claim:gate-green cargo xtask verify → all stages pass in 47s, ending contract-check: 25 topic shelf(s) validated and release-dates: 11 tag(s) reconciled against git, 1 uncovered surface(s); cargo test -p xtask → 71 passed, 0 failed 1.00 Full local gate including cargo clippy --workspace --all-targets --all-features -- -D warnings under pedantic.
claim:ci-shallow .github/workflows/ci.yml#28@89ca929a uses actions/checkout with only persist-credentials: false; release.yml and auto-release-tag.yml both set fetch-depth: 0 0.95 Inferred from actions/checkout defaulting to depth 1 without tags; not independently executed in CI.
claim:stale-seed xtask/src/release_prep.rs#383@89ca929a (add_days_to_iso_date(&latest, 14)); the latest target_date after realignment is 2026-06-30, giving 2026-07-14 0.95 Arithmetic from source; not executed, since running release-prep would scaffold a release.

CHANGELOG release headings recorded a planned biweekly schedule running
2026-06-24 through 2026-11-04, while every tag was actually cut between
2026-06-21 and 2026-06-30. The dates were never a typo: release-prep
writes "## [{tag}] - {target_date}" at scaffold time from
next_release_target_date(), and nothing back-filled the real date after
tagging. Keep a Changelog, which this file claims to follow, defines that
heading as the release date.

Realigns all four surfaces that carry the dates:

- CHANGELOG.md: 11 release headings
- docs/topics/release-process/policy.toml: 10 target_date fields
- docs/releases/*.md: 11 "Target date" lines
- xtask/src/tests.rs: the alpha_changelog_dates_match_release_policy
  table and the nine release_policy_tracks_v0_N_boundary guards

The synthetic temp-repo fixtures in xtask/src/tests.rs keep their
original dates; their values are load-bearing for the +14 scaffolding
arithmetic and describe no real release.

target_date keeps its field name but now holds the actual publication
date, so RELEASE-REQ-008, its fixture oracle, and RELEASE-TP-004 are
restated to say so rather than describing a planned date.

Known gap, recorded in the release-process test plan:
next_release_target_date still adds 14 days to the last entry, which now
seeds 2026-07-14, already past. release-prep needs an explicit or
clock-derived date before the next release.

docs-impact: documentation and release-guard fixtures only; no library,
schema, or golden artifact change. Verified with cargo xtask verify
(full gate, 52s), 76 xtask tests, contract-check 23 shelves, and
markdownlint 0 errors.
…pies

The release date guards were fragile and largely tautological.

alpha_changelog_dates_match_release_policy asserted that CHANGELOG.md
dates equalled policy.toml target_date values, but release-prep generates
both from that one field. Two copies written from a single source always
agree, including when the source is wrong, so the guard stayed green
through four months of drift across all eleven releases and only failed
once a human corrected one side by hand. It detected intervention, not
incorrectness.

The nine release_policy_tracks_v0_N_boundary tests (plus v0_2) matched
substrings against the whole policy file rather than the release's own
block. Verified: setting v0.3's target_date to 1999-01-01 left
release_policy_tracks_v0_3_boundary passing, because v0.4 carried the same
date string. Releases tagged on the same day share dates, so that is the
normal case. They were also ~250 lines of frozen-history boilerplate,
auto-written by a generator, asserting that a static file still contained
strings someone typed.

Replaces them with:

- `cargo xtask release-dates`, which reconciles policy.toml, CHANGELOG.md,
  and docs/releases/*.md against `git for-each-ref refs/tags` -- the
  independent authority for when a release happened. Wired into
  `xtask verify`. Date contradictions fail; absent surfaces are reported
  as uncovered rather than failing an otherwise-correct history, since the
  earliest releases predate these surfaces. A clone without tags says it
  skipped instead of passing vacuously.
- release_policy_blocks_are_structurally_complete, one data-driven test
  over parsed blocks, replacing eleven near-duplicates.
- release_policy_block_parsing_scopes_fields_to_their_own_release, a
  regression guard pinning the 1999-01-01 false-pass.
- reconcile_release_dates, a pure function over already-read inputs, with
  hermetic tests. cargo test needs no git tags, so CI's shallow checkout
  is unaffected.

release-prep no longer scaffolds Rust test stubs or changelog date guard
entries. Per-release scope and non-goal content is now reviewed rather
than string-tested, matching the repo's own rule in
docs/topics/documentation/test-plan.md that policy detail is not encoded
as a Rust test; the ten affected requirement and test-case rows move to
`policy` status accordingly.

docs-impact: release-process README, test plan, and policy.toml updated
with the new design and two recorded open gaps. Verified with cargo xtask
verify (full gate, 9s), 69 xtask tests, and markdownlint 0 errors.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • Documentation

    • Updated release dates across the changelog, release notes, and release policy to match publication dates.
    • Clarified release-preparation guidance, date reconciliation, verification behavior, and known limitations.
  • New Features

    • Added release-date validation comparing policy, changelog, release notes, and Git tag dates.
    • Integrated release-date checks into continuous verification.
  • Improvements

    • Simplified release preparation with explicit date support.
    • Removed obsolete boundary-test stub generation and validation.

Walkthrough

The release process now synchronizes published dates across policy, changelog, and release notes. A new release-dates xtask reconciles these dates with Git tags. Release preparation no longer generates boundary-test stubs, and CI, tests, and documentation reflect the updated workflow.

Changes

Release process synchronization

Layer / File(s) Summary
Synchronize published release metadata
CHANGELOG.md, docs/releases/*, docs/topics/release-process/policy.toml
Published alpha release dates now use UTC tag dates from June 21–30, 2026. Obsolete scaffold outputs were removed from the policy.
Implement release-date reconciliation
xtask/src/release_dates.rs, xtask/src/main.rs
The new command parses release surfaces, reads annotated Git tag dates, reports gaps and drift, and runs through verify.
Remove boundary-test generation
xtask/src/release_prep.rs
Release preparation accepts an explicit or current UTC date and no longer generates per-release Rust boundary-test stubs.
Update release validation and documentation
xtask/src/tests.rs, docs/topics/release-process/README.md, docs/topics/release-process/test-plan.md
Tests validate structured policy blocks, tag-date reconciliation, and updated scaffolding. Documentation describes the commands and date semantics.
Run release-date checks in CI
.github/workflows/ci.yml
CI runs cargo xtask release-dates --check with a full Git checkout.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Poem

Tags set the date,
Policy and notes agree,
Drift meets a hard check.
Stubs leave the release path,
CI guards every tag.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main changes: anchoring release dates to Git tags and replacing obsolete release guards.
Description check ✅ Passed The description directly explains the release-date reconciliation, guard replacement, CI integration, and release-preparation changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
xtask/src/release_prep.rs (1)

74-74: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

next_release_target_date now feeds a field whose meaning changed under it, and the next release-prep run will produce a self-contradicting artifact.

This PR redefines target_date from a planned date to the recorded tag date. Every value in policy.toml, CHANGELOG.md, and the release notes now records when a release actually happened. next_release_target_date still computes a plan by adding 14 days to the last entry.

The consequence is deterministic, not speculative:

  1. The last realigned entry is 2026-06-30.
  2. next_release_target_date returns 2026-07-14.
  3. release_prep writes 2026-07-14 into the policy block, the changelog section, and the release-notes stub.
  4. The next tag is created on its real date, which is not 2026-07-14.
  5. The release_dates gate added in this PR reports three drift lines and fails cargo xtask verify.

The PR objectives record this and choose not to resolve it, and docs/topics/release-process/test-plan.md lines 131-137 describe it as failing loudly. That reasoning holds for detection. It does not hold for generation: release_prep now emits a value that is known in advance to be wrong, and the operator must edit three generated surfaces by hand on every release.

Since the field now records a date rather than planning one, the scaffold should write the current UTC date and let the reconciliation confirm it, or require the date as an explicit argument.

Do you want me to open an issue that tracks replacing the 14-day increment with an explicit or clock-derived date, and to draft the RED test for it?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/release_prep.rs` at line 74, The release_prep flow currently uses
next_release_target_date to generate a planned date for a field that now
represents the actual release date. Update the release preparation logic around
release_prep and next_release_target_date to use the current UTC date or require
an explicit date argument, removing the unconditional 14-day projection so
generated policy, changelog, and release-note values reflect the recorded
release date.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 243-249: Update the changelog wording describing target_date to
say it records the actual Git tag date, not the real publication date. Preserve
the distinction between Git tag dates and GitHub Release publication dates,
consistent with release-date validation in release_dates.rs and the
v0.4.0-alpha.1 release documentation.

In `@docs/topics/release-process/README.md`:
- Around line 63-70: Update the release-process README paragraph describing
`cargo xtask release-dates` to explicitly define `policy.toml`’s `target_date`
and each release note’s `Target date:` as the release publication date, not a
planned date. Keep the existing explanation of git tags as the independent
authority and verification behavior, and do not rename the field or modify
parser and release-note files.

In `@docs/topics/release-process/test-plan.md`:
- Line 104: Rename the test at xtask/src/tests.rs around
release_prep_scaffolds_version_policy_changelog_and_test_stub to reflect that
release-prep does not write a Rust test stub, and update RELEASE-TP-019’s
evidence name to match exactly. Preserve the test behavior and all other row
content.
- Line 77: Update the CHANGELOG.md oracle description in the release test plan
to identify the corresponding git tag date as the authority for published alpha
release sections, replacing the reference to the release policy. Keep the
existing release-history scope and align this wording with the rule already
stated on line 89.

In `@xtask/src/release_dates.rs`:
- Around line 98-109: Update the unsuccessful-command branch after
Command::new("git") in the release-date logic to include the captured
output.stderr in the returned error message. Preserve the existing success path
and command-execution error handling while making the failure message retain
git’s diagnostic text.
- Around line 100-102: Update the git ref scan in the release-date collection
logic to restrict tags to the release naming contract: tags beginning with “v”
and matching the version format accepted by ReleasePrepVersion::parse, rather
than enumerating all refs/tags. Preserve the existing creator-date formatting
and downstream verification behavior.
- Around line 167-172: Update the release_dates validation around block.status
so a known pre-publication status such as “prep” with an existing tag is
reported as a gap, not drift; retain drift for statuses outside the known set.
First add a RED test covering this existing-tag/prep case and asserting no
drift, then implement the classification change and update RELEASE-TP-004 in the
release process test plan.
- Around line 209-214: Update release_dates() so the tags.is_empty() branch
treats missing git tags as a failed reconciliation rather than returning Ok(()).
Preserve the diagnostic message or make it clearly indicate failure, and return
the established error type used by release_dates() so release gating fails
closed.
- Around line 99-103: Update the git tag date retrieval in the release-dates
command around the for-each-ref invocation to force UTC and emit raw UTC date
fields with a stable YYYY-MM-DD formatter, replacing the timezone-dependent
creatordate:short format. Keep the existing Published-versus-tag comparison
behavior unchanged.

In `@xtask/src/tests.rs`:
- Around line 2780-2789: The release-notes policy validation does not verify
that each section key matches its tag. In the test block around seen_tags and
target_date, derive the expected section key from tag using the same
transformation as ReleasePrepVersion::parse, assert it equals section, and first
add a mismatched fixture to confirm the test fails before implementing the
assertion.
- Around line 1772-1779: Replace the ineffective absent-substring check in the
release-prep test with an exact artifact comparison: extract the seeded xtask
test file contents into a shared RELEASE_PREP_FIXTURE_XTASK_TESTS constant, use
it when creating the fixture, then assert the file remains byte-for-byte
identical after release_prep. This must detect any modification or deletion of
the seeded file while preserving the existing fixture behavior.
- Around line 2766-2770: Update the block-count assertion in the relevant test
to require exactly 11 entries instead of allowing any count greater than or
equal to 10, preserving the existing assertion message and using the release
fixture count as the expected value.

---

Outside diff comments:
In `@xtask/src/release_prep.rs`:
- Line 74: The release_prep flow currently uses next_release_target_date to
generate a planned date for a field that now represents the actual release date.
Update the release preparation logic around release_prep and
next_release_target_date to use the current UTC date or require an explicit date
argument, removing the unconditional 14-day projection so generated policy,
changelog, and release-note values reflect the recorded release date.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 61910f40-5043-44ed-8a09-665102a850bd

📥 Commits

Reviewing files that changed from the base of the PR and between df80f92 and 89ca929.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • docs/releases/v0.1.0-alpha.1.md
  • docs/releases/v0.10.0-alpha.1.md
  • docs/releases/v0.11.0-alpha.1.md
  • docs/releases/v0.2.0-alpha.1.md
  • docs/releases/v0.3.0-alpha.1.md
  • docs/releases/v0.4.0-alpha.1.md
  • docs/releases/v0.5.0-alpha.1.md
  • docs/releases/v0.6.0-alpha.1.md
  • docs/releases/v0.7.0-alpha.1.md
  • docs/releases/v0.8.0-alpha.1.md
  • docs/releases/v0.9.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/topics/release-process/policy.toml
  • docs/topics/release-process/test-plan.md
  • xtask/src/main.rs
  • xtask/src/release_dates.rs
  • xtask/src/release_prep.rs
  • xtask/src/tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: supply-chain (cargo-deny)
  • GitHub Check: rust stable (fmt · clippy · test)
  • GitHub Check: rust msrv 1.94.0 (fmt · clippy · test)
🧰 Additional context used
📓 Path-based instructions (6)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Never amend Git commits, use git rebase without explicit user approval, or force any Git operation; use new commits and regular merge commits instead.
Do not create draft pull requests, and never use a codex prefix in branch names, pull request titles, or commit messages.
Pull requests for issue work must include GitHub auto-close text such as Closes #123`` for every issue they intend to close.
Use codex-think --remember --json when starting a session, entering the repository, or regaining context, and record significant durable events with `codex-think "..." --json`. Treat Think as memory rather than repository truth.
Every pull request body must contain `## Plain-English Walkthrough` with `### TL;DR` and `### Walkthrough`, explaining the prior behavior, new model and dataflow, invariants, failures, compatibility, and verification as applicable.
Use Mermaid diagrams for nontrivial flow, lifecycle, ownership, or component interaction when clearer than prose; every diagram requires an introductory paragraph, the diagram, the exact collapsed caption structure, and a concluding interpretation.
Tag each material technical claim at first occurrence as `[claim:, confidence:]`, cite evidence using repository-relative paths, line numbers, and Git SHAs, and end the explanatory body with a collapsed citations appendix.
If CodeRabbit is actively reviewing, obtain its approval before merge; if unavailable due to limits or credits, request `@codex review please` and wait for the alternate response. Do not treat unavailability as approval unless a maintainer explicitly overrides the gate.
For release preparation, write the release thesis first, reconcile changes from the previous tag, update release policy and tests, verify the milestone has no open issues and no unauthorized crates.io publication occurred, and record a durable release report.
Run `cargo xtask verify` before claiming a branch is ready.

Files:

  • docs/releases/v0.2.0-alpha.1.md
  • docs/releases/v0.11.0-alpha.1.md
  • docs/releases/v0.10.0-alpha.1.md
  • docs/releases/v0.1.0-alpha.1.md
  • docs/releases/v0.6.0-alpha.1.md
  • docs/releases/v0.8.0-alpha.1.md
  • docs/releases/v0.4.0-alpha.1.md
  • xtask/src/main.rs
  • CHANGELOG.md
  • docs/releases/v0.5.0-alpha.1.md
  • docs/releases/v0.9.0-alpha.1.md
  • docs/releases/v0.3.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/releases/v0.7.0-alpha.1.md
  • xtask/src/tests.rs
  • xtask/src/release_prep.rs
  • docs/topics/release-process/test-plan.md
  • docs/topics/release-process/policy.toml
  • xtask/src/release_dates.rs
**/*.{rs,md}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,md}: Tests must assert software behavior and stable error kinds or structured artifacts, not implementation details, prose, paths, or merely is_err(); documentation-tool tests may test validator behavior.
For nontrivial behavior, contract, workflow, release, schema, validation, or public-surface changes, follow RED/GREEN TDD: update the owning test-plan.md, write the deterministic test first, observe the RED failure, implement the smallest coherent fix, then mark the case implemented only after executable evidence exists.

Files:

  • docs/releases/v0.2.0-alpha.1.md
  • docs/releases/v0.11.0-alpha.1.md
  • docs/releases/v0.10.0-alpha.1.md
  • docs/releases/v0.1.0-alpha.1.md
  • docs/releases/v0.6.0-alpha.1.md
  • docs/releases/v0.8.0-alpha.1.md
  • docs/releases/v0.4.0-alpha.1.md
  • xtask/src/main.rs
  • CHANGELOG.md
  • docs/releases/v0.5.0-alpha.1.md
  • docs/releases/v0.9.0-alpha.1.md
  • docs/releases/v0.3.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/releases/v0.7.0-alpha.1.md
  • xtask/src/tests.rs
  • xtask/src/release_prep.rs
  • docs/topics/release-process/test-plan.md
  • xtask/src/release_dates.rs
**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{md,mdx}: Documentation pages must have one primary reader job, separate user task help from contributor architecture and evidence maps, use concrete valid examples with expected results when relevant, and keep exact public facts in validated or generated reference material.
Update affected documentation in the same change as behavior, schema, release, workflow, or public-surface changes, or state docs-impact: none with a concise rationale.

Files:

  • docs/releases/v0.2.0-alpha.1.md
  • docs/releases/v0.11.0-alpha.1.md
  • docs/releases/v0.10.0-alpha.1.md
  • docs/releases/v0.1.0-alpha.1.md
  • docs/releases/v0.6.0-alpha.1.md
  • docs/releases/v0.8.0-alpha.1.md
  • docs/releases/v0.4.0-alpha.1.md
  • CHANGELOG.md
  • docs/releases/v0.5.0-alpha.1.md
  • docs/releases/v0.9.0-alpha.1.md
  • docs/releases/v0.3.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/releases/v0.7.0-alpha.1.md
  • docs/topics/release-process/test-plan.md
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Use tables for consistent-shape comparisons and evidence, bullets for unordered sets, numbered lists for ordered procedures or states, and focused branch-accurate snippets for exact syntax.

Files:

  • docs/releases/v0.2.0-alpha.1.md
  • docs/releases/v0.11.0-alpha.1.md
  • docs/releases/v0.10.0-alpha.1.md
  • docs/releases/v0.1.0-alpha.1.md
  • docs/releases/v0.6.0-alpha.1.md
  • docs/releases/v0.8.0-alpha.1.md
  • docs/releases/v0.4.0-alpha.1.md
  • CHANGELOG.md
  • docs/releases/v0.5.0-alpha.1.md
  • docs/releases/v0.9.0-alpha.1.md
  • docs/releases/v0.3.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/releases/v0.7.0-alpha.1.md
  • docs/topics/release-process/test-plan.md
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: For Rust changes, preserve claim integrity by providing executable evidence, keep compiler and validation paths deterministic and free of hidden I/O, and prefer structured public failures with stable error kinds over prose-only diagnostics.
Do not add Rust dependencies without pull-request rationale and contract-impact notes; treat planned lint, dependency, and fuzzing ratchets as planned until executable checks land.

Files:

  • xtask/src/main.rs
  • xtask/src/tests.rs
  • xtask/src/release_prep.rs
  • xtask/src/release_dates.rs
docs/topics/**

📄 CodeRabbit inference engine (AGENTS.md)

docs/topics/**: Topic shelves document landed behavior: README.md describes current HEAD truth, test-plan.md records verification and known gaps, and optional architecture or rationale pages contain durable supporting information.
For every nontrivial behavior, contract, workflow, release, schema, validation, or public-surface change, identify or create the owning topic shelf, update test-plan.md, add executable evidence, update README.md only after behavior exists, and run cargo xtask verify.
Do not update topic shelves for purely mechanical edits that do not change a contract; explain the omission in the pull request or final report.

Files:

  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • docs/topics/release-process/policy.toml
🪛 LanguageTool
docs/topics/release-process/test-plan.md

[uncategorized] ~46-~46: The official name of this software platform is spelled with a capital “H”.
Context: ... and dispatches release publication. | .github/workflows/auto-release-tag.yml, docs/to...

(GITHUB)


[uncategorized] ~47-~47: The official name of this software platform is spelled with a capital “H”.
Context: ... the milestone has zero open issues. | .github/workflows/release.yml, docs/topics/rele...

(GITHUB)


[uncategorized] ~49-~49: The official name of this software platform is spelled with a capital “H”.
Context: ...uest, and derives the requested tag. | .github/workflows/auto-release-tag.yml, docs/to...

(GITHUB)


[grammar] ~59-~59: Ensure spelling is correct
Context: ...ocs/topics/release-process/policy.toml, xtask/src/release_dates.rs | ## Fixtures | Fixture | Purpose | Oracle |...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[uncategorized] ~93-~93: The official name of this software platform is spelled with a capital “H”.
Context: ...ports_dispatch_and_milestone_closure | .github/workflows/auto-release-tag.yml, .github...

(GITHUB)


[uncategorized] ~93-~93: The official name of this software platform is spelled with a capital “H”.
Context: ...github/workflows/auto-release-tag.yml, .github/workflows/release.yml, docs/topics/rele...

(GITHUB)


[uncategorized] ~95-~95: The official name of this software platform is spelled with a capital “H”.
Context: ...auto_release_tag_workflow_is_guarded | .github/workflows/auto-release-tag.yml, docs/to...

(GITHUB)

🔇 Additional comments (23)
docs/releases/v0.10.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.8.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.9.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.11.0-alpha.1.md (1)

3-3: LGTM!

xtask/src/release_dates.rs (2)

31-78: LGTM!


216-244: LGTM!

xtask/src/main.rs (1)

133-152: LGTM!

Also applies to: 227-227

xtask/src/release_prep.rs (1)

31-35: LGTM!

Also applies to: 92-100, 289-289, 319-321

xtask/src/tests.rs (3)

2818-2856: LGTM!


2858-2936: LGTM!


1704-1704: 🗄️ Data Integrity & Integration

No change needed.

policy.toml, runbook.md, and the repository have no remaining references to the removed boundary-test surface.

docs/topics/release-process/README.md (1)

58-61: LGTM!

docs/topics/release-process/test-plan.md (2)

41-59: LGTM!

Also applies to: 88-103, 105-106


131-141: LGTM!

CHANGELOG.md (1)

362-362: LGTM!

Also applies to: 416-416, 456-456, 487-487, 505-505, 528-528, 552-552, 569-569, 606-606, 655-655, 674-674

docs/releases/v0.1.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.2.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.3.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.4.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.5.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.6.0-alpha.1.md (1)

3-3: LGTM!

docs/releases/v0.7.0-alpha.1.md (1)

3-3: LGTM!

docs/topics/release-process/policy.toml (1)

47-47: LGTM!

Also applies to: 147-147, 167-167, 192-192, 214-214, 241-241, 272-272, 317-317, 366-366, 408-408, 447-447

Comment thread CHANGELOG.md Outdated
Comment thread docs/topics/release-process/README.md Outdated
Comment thread docs/topics/release-process/test-plan.md Outdated
Comment thread docs/topics/release-process/test-plan.md Outdated
Comment thread xtask/src/release_dates.rs
Comment thread xtask/src/release_dates.rs Outdated
Comment thread xtask/src/release_dates.rs
Comment thread xtask/src/tests.rs
Comment thread xtask/src/tests.rs Outdated
Comment on lines +2766 to +2770
assert!(
blocks.len() >= 10,
"release policy should retain a block per published release, found {}",
blocks.len()
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Replace the >= 10 lower bound with the exact count.

This PR realigns eleven releases, and docs/topics/release-process/test-plan.md lists eleven release-notes fixtures, v0.1.0-alpha.1 through v0.11.0-alpha.1. A lower bound of 10 lets one historical block be deleted without any test failing. Silent loss of a historical policy block is the precise failure class this PR sets out to eliminate.

The assertion message already claims "a block per published release". Make the assertion say it.

🐛 Proposed fix
+    // One block per published release. Update deliberately when a release
+    // lands, so a deleted historical block fails instead of passing a bound.
     assert!(
-        blocks.len() >= 10,
-        "release policy should retain a block per published release, found {}",
+        blocks.len() >= 11,
+        "release policy must retain a block per published release, found {}",
         blocks.len()
     );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/tests.rs` around lines 2766 - 2770, Update the block-count
assertion in the relevant test to require exactly 11 entries instead of allowing
any count greater than or equal to 10, preserving the existing assertion message
and using the release fixture count as the expected value.

Comment thread xtask/src/tests.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89ca929a48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

[release_notes.v0_11_0_alpha_1]
tag = "v0.11.0-alpha.1"
target_date = "2026-11-04"
target_date = "2026-06-30"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop seeding the next release from the last tag date

Changing the final policy date to 2026-06-30 makes the unchanged next_release_target_date calculation scaffold 2026-07-14 for v0.12, which is already in the past as of 2026-08-04. That stale value is copied into the changelog, policy, and release notes, while release-dates cannot detect it until the tag exists, so the next release-prep branch passes pre-tag verification with a knowingly incorrect date. Release prep should accept or derive a current release date instead of adding 14 days to historical publication data.

Useful? React with 👍 / 👎.

for gap in &report.gaps {
println!("release-dates: uncovered - {gap}");
}
if report.drift.is_empty() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail verification for unexpected coverage gaps

When an existing tagged release loses its changelog heading, policy block, release-notes file, or Target date: line, reconciliation records only a gap; this branch nevertheless returns success whenever no contradictory date remains. Consequently, deleting the date-bearing surface can make cargo xtask verify pass instead of detecting the regression. Legacy omissions should be explicitly allowlisted, while new gaps in currently covered releases should fail the gate.

AGENTS.md reference: AGENTS.md:L82-L83

Useful? React with 👍 / 👎.

Comment thread xtask/src/main.rs
provider_contract_pack(root, ProviderContractPackMode::Check)?;
provider_runtime_dependencies(root)?;
contract_check(root)?;
release_dates(root)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run the real date reconciliation in required CI

Checked .github/workflows/ci.yml: pull-request jobs run format, clippy, workspace tests, and the provider fixture check, but never cargo xtask verify or cargo xtask release-dates, and their checkout does not fetch tags. The removed alpha_changelog_dates_match_release_policy guard ran under the workspace tests, whereas the replacement tests use only synthetic maps, so a PR can now change policy, changelog, and notes to the same wrong date and pass every required CI job. Add a tag-aware reconciliation step to CI rather than wiring it only into the optional local gate.

AGENTS.md reference: AGENTS.md:L49-L57

Useful? React with 👍 / 👎.

Comment thread xtask/src/tests.rs Outdated
Comment on lines +2807 to +2808
if status == "published" {
for placeholder in ["TODO_release_scope", "TODO_release_non_goal"] {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject scaffold placeholders before release-prep can merge

For the normal next-release flow, release-prep creates a block with status = "prep" and TODO_release_scope/TODO_release_non_goal, but this replacement guard rejects placeholders only after status becomes published. The removed generated boundary test rejected those placeholders while the block was still prep; without it, normal CI can pass and the auto-release workflow can tag and publish a release-prep merge whose structured scope remains TODO. Apply the placeholder check to release-prep blocks as well, rather than relying only on the new policy review row.

AGENTS.md reference: AGENTS.md:L77-L83

Useful? React with 👍 / 👎.

Comment thread xtask/src/release_dates.rs Outdated
Comment on lines +101 to +102
"--format=%(refname:short)\t%(creatordate:short)",
"refs/tags",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not use commit dates for lightweight release tags

Git defines creatordate as the committer or tagger date depending on the referenced object type, as documented in git-for-each-ref. For a lightweight v* tag—which .github/workflows/release.yml currently accepts—this therefore reports the tagged commit's committer date, not when the tag was pushed or the release published. Tagging an older main commit makes the checker reject every correct recorded release date; either require annotated release tags or obtain publication time from an authority that exists for both tag types.

AGENTS.md reference: AGENTS.md:L82-L83

Useful? React with 👍 / 👎.

Seventeen review findings on #183, all addressed.

Correctness of the check itself:

- Tag dates are read in UTC. `%(taggerdate)` renders in the reader's
  timezone, so a tag made near midnight resolves to different days for
  different operators. This was not theoretical: v0.4.0-alpha.1 is
  2026-06-24 in PDT and 2026-06-25 in UTC, so the earlier realignment
  recorded a local date that CI, which runs UTC, would have rejected.
  That release is corrected to 2026-06-25 across all three surfaces.
- Release tags must be annotated. `creatordate` falls back to the tagged
  commit's committer date for a lightweight tag, so a tag placed on an
  older commit could report a date that never corresponded to a release.
- The scan is scoped to `refs/tags/v*`, so scratch tags no longer emit
  permanent uncovered lines that train operators to ignore the output.
- `git` stderr is preserved in the failure message.
- No tags now fails closed. A missing independent authority is not
  approval.
- An absent date-bearing surface is drift, not an advisory gap, so
  deleting the evidence cannot make the gate pass. Only the pre-policy
  v0.1.0-alpha.1 omission is allowlisted.
- A tag whose block still reads `prep` reports a gap rather than failing.
  The tag is created before the post-publication change flips the status,
  and failing there would leave `verify` red on `main` for every
  unrelated branch until that second change landed.

Coverage:

- CI gains a `release-dates` job with `fetch-depth: 0`. The reconciliation
  previously ran only in the local gate, which CI never invokes, so a pull
  request could still set policy, changelog, and notes to one wrong date
  and pass every required check.
- Scaffold placeholders are rejected for `prep` blocks, not only
  `published` ones. auto-release-tag publishes from a merged release-prep
  branch, so a surviving TODO would ship.
- The policy block count is exact rather than a lower bound, and each
  block's tag must agree with its section key.
- The release-prep negative assertion compares the whole file against the
  seeded fixture. It previously searched for a stub name the fixture never
  contained, so it could not fail.

Release prep:

- `release-prep` takes `--date YYYY-MM-DD` and otherwise uses today's UTC
  date. Adding fourteen days to the last recorded release assumed
  `target_date` held a planned date; now that it records when a release
  was tagged, that extrapolation produced 2026-07-14, already past.
- The scaffolding test is renamed to match what it proves.

Documentation: the changelog and README now say tag date rather than
publication date and note that the two differ, the README documents the
UTC and annotated-tag rules, and the CHANGELOG oracle names the git tag
rather than policy.toml as the authority.

docs-impact: release-process README and test plan updated; four new
test-case rows and one restated requirement.

Verified with cargo xtask verify (full gate, 25 shelves, 11 tags
reconciled), 75 xtask tests, and markdownlint.
`[Unreleased]` carried two `### Changed` headings with `### Added` between
them, which markdownlint reports as MD024/no-duplicate-heading. The
condition predates this branch: it reproduces against
`origin/main:CHANGELOG.md`.

Entries are merged into the first `### Changed` in their existing order
and `### Added` follows it. No entry text is altered and no release
section moves; all eleven `## [v...]` headings are unchanged.

Kept as a separate commit because it touches a large span of CHANGELOG.md
and will conflict with any concurrent branch adding entries, so it can be
dropped independently of the review fixes.

docs-impact: none; formatting only.
@flyingrobots

Copy link
Copy Markdown
Owner Author

All 17 findings addressed in 035d60b4, plus one pre-existing lint error in 528dc312.

One finding turned out to be a live bug rather than a hardening suggestion, so it is worth leading with.

The timezone finding was real, and it had already bitten

%(taggerdate) renders in the reading machine's timezone. Comparing the eleven tags both ways:

PDT UTC
v0.4.0-alpha.1 2026-06-24 2026-06-25
other ten tags identical

The earlier realignment in this PR was computed on a machine in PDT, so it recorded 2026-06-24 for that release. The new CI job runs in UTC and would have failed on it. v0.4.0-alpha.1 is now 2026-06-25 across the changelog, policy.toml, and its release notes, and the command forces TZ=UTC so a local run and a CI run agree. Independent corroboration: that release's notes already recorded Published as a prerelease on 2026-06-25.

Correctness of the check

# Finding Resolution
6 Force UTC before parsing TZ=UTC + taggerdate:format-local:%Y-%m-%d; the one affected release corrected as above
17 Lightweight tags report commit dates Reads objecttype; lightweight v* tags now fail with an explicit message. Guard: release_date_reconciliation_rejects_lightweight_release_tags
7 Scan scoped to release tags refs/tags/v*
5 Preserve git stderr Included in the failure message
9 Missing tags must fail closed No v* tags is now an error naming git fetch --tags, not a skip
14 Unexpected gaps must fail Absent surfaces are drift. Only v0.1.0-alpha.1's missing policy block is allowlisted, via a typed Surface list rather than a string match. Guards: ..._fails_when_a_covered_surface_disappears, ..._allowlists_the_prepolicy_release
8 Fresh tag reddens main Took your proposed shape: prep is a lagging surface reported as a gap; any other non-published status is still drift. Guard: ..._tolerates_prep_status_for_a_fresh_tag

Coverage

# Finding Resolution
15 Reconciliation never ran in required CI New release-dates job in ci.yml with fetch-depth: 0. This was the finding that most undercut the PR: the check verified against reality but was wired only into a gate CI does not invoke
16 Placeholders rejected only when published Now rejected for every block regardless of status, since auto-release-tag publishes from a merged release-prep branch
11 >= 10 lower bound assert_eq!(blocks.len(), 10)
12 Section key and tag never compared New policy_section_key; asserted in the structural test and in reconciliation
10 Negative assertion could not fail Now compares the whole file against the seeded fixture, so it fails if release-prep writes anything

Release prep

# Finding Resolution
13 Stop seeding from the last tag date release-prep takes --date YYYY-MM-DD and otherwise uses today's UTC date. next_release_target_date and add_days_to_iso_date are deleted
4 Test name contradicts its purpose Renamed to release_prep_scaffolds_version_policy_changelog_and_notes; RELEASE-TP-019 evidence updated

Documentation

# Finding Resolution
1 "publication date" is wrong Now says the release was tagged, and states that the tag date and the GitHub Release publication timestamp differ
2 README must define the field Added, with the UTC rule and the annotated-tag requirement
3 Oracle still named policy.toml as authority Now names the annotated git tag

RELEASE-REQ-008 is restated to cover fail-closed, annotated-tag, and CI semantics; RELEASE-TP-022 through TP-024 are added.

One thing I did not treat as fixed

The stale-seed open gap is narrowed, not closed. The scaffolded date is still a prediction: a release-prep branch that sits unmerged past its scaffold date records a date earlier than its eventual tag, and reconciliation only catches that once the tag exists. Flipping the block to published is what binds the recorded date to the tag. That is recorded in the release-process test plan rather than claimed as solved.

Out of scope, fixed separately

528dc312 merges the two ### Changed headings inside [Unreleased] (MD024). The condition predates this branch and reproduces against origin/main:CHANGELOG.md. It is a separate commit because it touches a large span of the file and will conflict with any concurrent branch adding entries, so it can be dropped independently.

Verified: cargo xtask verify full gate green (25 shelves, 11 tags reconciled), 75 xtask tests, markdownlint 0 errors.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/topics/release-process/test-plan.md`:
- Around line 134-138: Update the release-date documentation around the
scaffolded release date and status transition to state that
reconcile_release_dates validates prep target_date and binds the recorded date
when the release tag appears, not when status changes to published. Keep
test-plan.md focused on verification and known gaps, and remove the incorrect
claim that flipping to published binds the date.
- Line 105: Update the RELEASE-TP-020 test-plan row’s requirement text to state
that every release_notes.* policy block—published, planned, and prep—rejects
scaffold placeholders, matching the coverage of
release_policy_blocks_are_structurally_complete.

In `@xtask/src/release_dates.rs`:
- Around line 210-220: Update ReleaseDateReport to return structured
reconciliation findings with a stable finding-kind enum and fields such as tag,
surface, expected_date, and actual_date, instead of prose-only strings. Adjust
the reconciliation logic to populate these findings, and move all human-readable
rendering into release_dates(); update tests to assert finding kinds and
structured fields rather than contains(...) checks on rendered text.
- Around line 10-13: Update the release-date documentation to use
timezone-qualified wording: in xtask/src/release_dates.rs lines 10-13, state
that v0.4.0-alpha.1 was tagged on 2026-06-24 in PDT and 2026-06-25 in UTC; apply
the same wording in docs/topics/release-process/README.md lines 72-83 instead of
presenting 2026-06-24 as the unqualified tag date.

In `@xtask/src/release_prep.rs`:
- Line 75: Update the release-preparation command boundary around target_date
and scaffold_release_date so the current SystemTime or UTC-date provider is read
once and injected into a pure default-date helper instead of calling today_utc
internally. Preserve explicitly supplied dates, return the existing error for
pre-epoch clocks, and add deterministic tests covering 1970-01-01 and a leap day
alongside the pre-epoch error path.
- Line 75: Update the release-preparation entry point around
scaffold_release_date to enforce canonical ISO date grammar before proceeding:
validate fixed separators and four-, two-, and two-digit component widths at the
required byte positions. Convert all malformed-input cases, including
parse_date_part errors, into the single stable InvalidIsoDate error without
exposing parser-specific messages.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: eae09197-600f-4243-83b5-be91e079c0d4

📥 Commits

Reviewing files that changed from the base of the PR and between 89ca929 and 528dc31.

📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • docs/releases/v0.4.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/topics/release-process/policy.toml
  • docs/topics/release-process/test-plan.md
  • xtask/src/main.rs
  • xtask/src/release_dates.rs
  • xtask/src/release_prep.rs
  • xtask/src/tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: rust msrv 1.94.0 (fmt · clippy · test)
  • GitHub Check: supply-chain (cargo-deny)
  • GitHub Check: rust stable (fmt · clippy · test)
🧰 Additional context used
📓 Path-based instructions (6)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Never amend Git commits, use git rebase without explicit user approval, or force any Git operation; use new commits and regular merge commits instead.
Do not create draft pull requests, and never use a codex prefix in branch names, pull request titles, or commit messages.
Pull requests for issue work must include GitHub auto-close text such as Closes #123`` for every issue they intend to close.
Use codex-think --remember --json when starting a session, entering the repository, or regaining context, and record significant durable events with `codex-think "..." --json`. Treat Think as memory rather than repository truth.
Every pull request body must contain `## Plain-English Walkthrough` with `### TL;DR` and `### Walkthrough`, explaining the prior behavior, new model and dataflow, invariants, failures, compatibility, and verification as applicable.
Use Mermaid diagrams for nontrivial flow, lifecycle, ownership, or component interaction when clearer than prose; every diagram requires an introductory paragraph, the diagram, the exact collapsed caption structure, and a concluding interpretation.
Tag each material technical claim at first occurrence as `[claim:, confidence:]`, cite evidence using repository-relative paths, line numbers, and Git SHAs, and end the explanatory body with a collapsed citations appendix.
If CodeRabbit is actively reviewing, obtain its approval before merge; if unavailable due to limits or credits, request `@codex review please` and wait for the alternate response. Do not treat unavailability as approval unless a maintainer explicitly overrides the gate.
For release preparation, write the release thesis first, reconcile changes from the previous tag, update release policy and tests, verify the milestone has no open issues and no unauthorized crates.io publication occurred, and record a durable release report.
Run `cargo xtask verify` before claiming a branch is ready.

Files:

  • docs/releases/v0.4.0-alpha.1.md
  • xtask/src/main.rs
  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • xtask/src/release_prep.rs
  • CHANGELOG.md
  • xtask/src/tests.rs
  • xtask/src/release_dates.rs
  • docs/topics/release-process/policy.toml
**/*.{rs,md}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,md}: Tests must assert software behavior and stable error kinds or structured artifacts, not implementation details, prose, paths, or merely is_err(); documentation-tool tests may test validator behavior.
For nontrivial behavior, contract, workflow, release, schema, validation, or public-surface changes, follow RED/GREEN TDD: update the owning test-plan.md, write the deterministic test first, observe the RED failure, implement the smallest coherent fix, then mark the case implemented only after executable evidence exists.

Files:

  • docs/releases/v0.4.0-alpha.1.md
  • xtask/src/main.rs
  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • xtask/src/release_prep.rs
  • CHANGELOG.md
  • xtask/src/tests.rs
  • xtask/src/release_dates.rs
**/*.{md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{md,mdx}: Documentation pages must have one primary reader job, separate user task help from contributor architecture and evidence maps, use concrete valid examples with expected results when relevant, and keep exact public facts in validated or generated reference material.
Update affected documentation in the same change as behavior, schema, release, workflow, or public-surface changes, or state docs-impact: none with a concise rationale.

Files:

  • docs/releases/v0.4.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • CHANGELOG.md
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Use tables for consistent-shape comparisons and evidence, bullets for unordered sets, numbered lists for ordered procedures or states, and focused branch-accurate snippets for exact syntax.

Files:

  • docs/releases/v0.4.0-alpha.1.md
  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • CHANGELOG.md
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: For Rust changes, preserve claim integrity by providing executable evidence, keep compiler and validation paths deterministic and free of hidden I/O, and prefer structured public failures with stable error kinds over prose-only diagnostics.
Do not add Rust dependencies without pull-request rationale and contract-impact notes; treat planned lint, dependency, and fuzzing ratchets as planned until executable checks land.

Files:

  • xtask/src/main.rs
  • xtask/src/release_prep.rs
  • xtask/src/tests.rs
  • xtask/src/release_dates.rs
docs/topics/**

📄 CodeRabbit inference engine (AGENTS.md)

docs/topics/**: Topic shelves document landed behavior: README.md describes current HEAD truth, test-plan.md records verification and known gaps, and optional architecture or rationale pages contain durable supporting information.
For every nontrivial behavior, contract, workflow, release, schema, validation, or public-surface change, identify or create the owning topic shelf, update test-plan.md, add executable evidence, update README.md only after behavior exists, and run cargo xtask verify.
Do not update topic shelves for purely mechanical edits that do not change a contract; explain the omission in the pull request or final report.

Files:

  • docs/topics/release-process/README.md
  • docs/topics/release-process/test-plan.md
  • docs/topics/release-process/policy.toml
🪛 LanguageTool
docs/topics/release-process/test-plan.md

[uncategorized] ~42-~42: The official name of this software platform is spelled with a capital “H”.
Context: ...licy.toml, xtask/src/release_dates.rs, .github/workflows/ci.yml | | RELEASE-REQ-009 | ...

(GITHUB)

🔇 Additional comments (9)
CHANGELOG.md (1)

31-48: LGTM!

Also applies to: 367-367, 421-421, 461-461, 492-492, 510-510, 533-533, 557-557, 574-574, 611-611, 660-660, 679-679

docs/releases/v0.4.0-alpha.1.md (1)

3-3: LGTM!

docs/topics/release-process/policy.toml (1)

47-47: LGTM!

Also applies to: 147-147, 167-167, 192-192, 214-214, 241-241, 272-272, 317-317, 366-366, 408-408, 447-447

xtask/src/release_dates.rs (1)

21-208: LGTM!

Also applies to: 223-408

xtask/src/main.rs (1)

10-10: LGTM!

Also applies to: 31-31, 98-98, 125-162, 236-236

xtask/src/tests.rs (1)

1714-1880: LGTM!

Also applies to: 2766-2870

docs/topics/release-process/test-plan.md (1)

41-104: LGTM!

Also applies to: 106-109, 139-142

docs/topics/release-process/README.md (1)

55-74: LGTM!

Also applies to: 76-88

.github/workflows/ci.yml (1)

46-62: LGTM!

| RELEASE-TP-017 | policy | Boundary guard | RELEASE-REQ-022 | Review confirms structured policy captures the v0.10 first public CLI scope, JSONL check workflow, deterministic input expansion, stream record schemas, stable diagnostic kind codes, golden fixture corpus, and explicit non-goals for compile/lower/explain/bundle/admission commands, human-pretty output, embedded schema validation, language server, marketplace packaging, participant policy, and crates.io publication. | - | docs/topics/release-process/policy.toml | Prevents the release metadata from overclaiming the first public CLI milestone. Frozen historical record; reviewed, not string-tested. Block structure is covered by `release_policy_blocks_are_structurally_complete`. |
| RELEASE-TP-018 | policy | Boundary guard | RELEASE-REQ-023 | Review confirms structured policy captures the v0.11 contract-bundle assembly and canonical Target IR artifact freeze scope, including semantic/release bundle digest goldens, Target IR byte/digest goldens, computed bundle integration, and explicit non-goals for runtime execution, admission execution, participant policy logic, Echo verifier completeness, git-warp commit creation, git-warp CRDT reducer verification, general target plugin dispatch, additional target profiles, extra source-to-target fixtures, canonical bundle-manifest bytes, and crates.io publication. | - | docs/topics/release-process/policy.toml | Prevents the release metadata from overclaiming the v0.11 cryptographic freeze. Frozen historical record; reviewed, not string-tested. Block structure is covered by `release_policy_blocks_are_structurally_complete`. |
| RELEASE-TP-019 | implemented | Scaffolding guard | RELEASE-REQ-024 | Given a temp repo skeleton with the current release-process surfaces, `cargo xtask release-prep <version>` writes the version bump, lockfile package versions, dated changelog section, release policy boundary block, release notes stub, and paired planned release-process rows deterministically, and writes no Rust test stub. | release_prep_scaffolds_version_policy_changelog_and_notes | xtask/src/release_prep.rs, xtask/src/tests.rs | Keeps release-prep setup mechanical so review focuses on release thesis, scope, non-goals, and evidence rather than missed boilerplate. |
| RELEASE-TP-020 | implemented | Consistency guard | RELEASE-REQ-025 | Every `[release_notes.*]` block parses with a unique section and tag, an ISO `target_date`, a known status, and `scope`/`non_goals` lists, and published blocks retain no scaffold placeholders. | release_policy_blocks_are_structurally_complete | docs/topics/release-process/policy.toml | Replaces eleven near-duplicate per-release guards with one data-driven check. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

State that every policy block rejects placeholders.

release_policy_blocks_are_structurally_complete checks placeholders for published, planned, and prep blocks. The test-plan row incorrectly limits this guarantee to published blocks.

Proposed fix
-| RELEASE-TP-020 | implemented | Consistency guard | RELEASE-REQ-025 | Every `[release_notes.*]` block parses with a unique section and tag, an ISO `target_date`, a known status, and `scope`/`non_goals` lists, and published blocks retain no scaffold placeholders.
+| RELEASE-TP-020 | implemented | Consistency guard | RELEASE-REQ-025 | Every `[release_notes.*]` block parses with a unique section and tag, an ISO `target_date`, a known status, `scope`/`non_goals` lists, and no scaffold placeholders.

As per coding guidelines: “test-plan.md records verification and known gaps.” <coding_guidelines>

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| RELEASE-TP-020 | implemented | Consistency guard | RELEASE-REQ-025 | Every `[release_notes.*]` block parses with a unique section and tag, an ISO `target_date`, a known status, and `scope`/`non_goals` lists, and published blocks retain no scaffold placeholders. | release_policy_blocks_are_structurally_complete | docs/topics/release-process/policy.toml | Replaces eleven near-duplicate per-release guards with one data-driven check. |
| RELEASE-TP-020 | implemented | Consistency guard | RELEASE-REQ-025 | Every `[release_notes.*]` block parses with a unique section and tag, an ISO `target_date`, a known status, `scope`/`non_goals` lists, and no scaffold placeholders. | release_policy_blocks_are_structurally_complete | docs/topics/release-process/policy.toml | Replaces eleven near-duplicate per-release guards with one data-driven check. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/topics/release-process/test-plan.md` at line 105, Update the
RELEASE-TP-020 test-plan row’s requirement text to state that every
release_notes.* policy block—published, planned, and prep—rejects scaffold
placeholders, matching the coverage of
release_policy_blocks_are_structurally_complete.

Source: Coding guidelines

Comment on lines +134 to +138
- The scaffolded release date is `--date` or today's UTC date. It is still a
prediction: a release-prep branch that sits unmerged past its scaffold date
records a date earlier than its eventual tag, and `release-dates` only detects
that once the tag exists. Flipping the block to `published` is what binds the
recorded date to the tag.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Bind the date when the tag appears, not when status changes.

reconcile_release_dates validates target_date for a prep block. Changing the status to published does not bind the date.

Proposed fix
-  that once the tag exists. Flipping the block to `published` is what binds the
-  recorded date to the tag.
+  that once the tag exists. Tag creation binds the recorded date to the tag;
+  `prep` status remains advisory only when the dates already match.

As per coding guidelines: “test-plan.md records verification and known gaps.” <coding_guidelines>

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- The scaffolded release date is `--date` or today's UTC date. It is still a
prediction: a release-prep branch that sits unmerged past its scaffold date
records a date earlier than its eventual tag, and `release-dates` only detects
that once the tag exists. Flipping the block to `published` is what binds the
recorded date to the tag.
- The scaffolded release date is `--date` or today's UTC date. It is still a
prediction: a release-prep branch that sits unmerged past its scaffold date
records a date earlier than its eventual tag, and `release-dates` only detects
that once the tag exists. Tag creation binds the recorded date to the tag;
`prep` status remains advisory only when the dates already match.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/topics/release-process/test-plan.md` around lines 134 - 138, Update the
release-date documentation around the scaffolded release date and status
transition to state that reconcile_release_dates validates prep target_date and
binds the recorded date when the release tag appears, not when status changes to
published. Keep test-plan.md focused on verification and known gaps, and remove
the incorrect claim that flipping to published binds the date.

Source: Coding guidelines

Comment on lines +10 to +13
//! The recorded date is the tag date, not the GitHub Release publication
//! timestamp. Those can differ: `v0.4.0-alpha.1` was tagged 2026-06-24 while the
//! prerelease was published 2026-06-25. Release notes record the publication
//! timestamp separately.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the UTC tag date consistently.

The release-date contract defines the authoritative tag date in UTC. Both sites still say that v0.4.0-alpha.1 was tagged on 2026-06-24, while the reconciled UTC date is 2026-06-25.

  • xtask/src/release_dates.rs#L10-L13: State that the tag timestamp falls on 2026-06-24 in PDT and 2026-06-25 in UTC.
  • docs/topics/release-process/README.md#L72-L83: Apply the same timezone-qualified wording instead of calling 2026-06-24 the unqualified tag date.
📍 Affects 2 files
  • xtask/src/release_dates.rs#L10-L13 (this comment)
  • docs/topics/release-process/README.md#L72-L83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/release_dates.rs` around lines 10 - 13, Update the release-date
documentation to use timezone-qualified wording: in xtask/src/release_dates.rs
lines 10-13, state that v0.4.0-alpha.1 was tagged on 2026-06-24 in PDT and
2026-06-25 in UTC; apply the same wording in
docs/topics/release-process/README.md lines 72-83 instead of presenting
2026-06-24 as the unqualified tag date.

Comment on lines +210 to +220
/// Outcome of comparing recorded dates against tag dates.
///
/// `drift` fails the gate: a recorded date contradicts its tag, or a surface
/// that should exist is absent. `gaps` are advisory and cover only the two cases
/// that are not contradictions: surfaces that predate a release, and the window
/// between tag creation and the post-publication change that flips a block from
/// `prep` to `published`.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub(crate) struct ReleaseDateReport {
pub(crate) drift: Vec<String>,
pub(crate) gaps: Vec<String>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Return structured reconciliation findings.

ReleaseDateReport exposes only rendered prose. The new tests must use contains(...) to identify missing surfaces, lightweight tags, and prep status.

Add a stable finding kind and structured fields such as tag, surface, expected_date, and actual_date. Render CLI text only in release_dates().

As per coding guidelines: “prefer structured public failures with stable error kinds over prose-only diagnostics” and “Tests must assert software behavior and stable error kinds or structured artifacts, not implementation details [or] prose.” <coding_guidelines>

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/release_dates.rs` around lines 210 - 220, Update ReleaseDateReport
to return structured reconciliation findings with a stable finding-kind enum and
fields such as tag, surface, expected_date, and actual_date, instead of
prose-only strings. Adjust the reconciliation logic to populate these findings,
and move all human-readable rendering into release_dates(); update tests to
assert finding kinds and structured fields rather than contains(...) checks on
rendered text.

Source: Coding guidelines

Comment thread xtask/src/release_prep.rs

let policy = read_to_string(&policy_path)?;
let target_date = next_release_target_date(&policy)?;
let target_date = scaffold_release_date(date)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Inject the clock into the default-date path.

scaffold_release_date(None) reads SystemTime::now() through today_utc. A release_prep caller cannot provide a fixed time. The supplied test passes Some("2026-08-04"), so it bypasses the new default branch and its clock-error path.

Read the clock at the command boundary. Pass SystemTime or a UTC-date provider into a pure helper. Add fixed tests for 1970-01-01, a leap day, and a pre-epoch clock error.

As per coding guidelines: **/*.rs says to “keep compiler and validation paths deterministic and free of hidden I/O,” and **/*.{rs,md} requires deterministic executable evidence for nontrivial behavior changes.

Also applies to: 382-389, 406-414

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/release_prep.rs` at line 75, Update the release-preparation command
boundary around target_date and scaffold_release_date so the current SystemTime
or UTC-date provider is read once and injected into a pure default-date helper
instead of calling today_utc internally. Preserve explicitly supplied dates,
return the existing error for pre-epoch clocks, and add deterministic tests
covering 1970-01-01 and a leap day alongside the pre-epoch error path.

Source: Coding guidelines


🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map helper definitions before inspecting their implementations.
ast-grep outline xtask/src/release_prep.rs --items all --type function

# Verify whether target-date generators normalize or reject noncanonical input.
rg -n -C 12 \
  'fn (insert_release_changelog_section|append_release_policy_block|render_release_notes_stub|validate_iso_date)\b|target_date' \
  xtask/src/release_prep.rs

# Locate CLI and test coverage for date syntax failures.
rg -n -C 8 \
  'release-prep|release_prep\(|validate_iso_date|2026-1-001|invalid ISO date|YYYY-MM-DD' \
  xtask/src/main.rs xtask/src/tests.rs

Repository: flyingrobots/edict

Length of output: 20711


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the date parser used by validate_iso_date.
sed -n '437,463p' xtask/src/release_prep.rs | cat -n

# Deterministically simulate the existing parser for canonical and noncanonical inputs.
python3 - <<'PY'
def parse_date_part(part, name):
    if part is None:
        raise ValueError(name)
    if not part.isdigit():
        raise ValueError(name)
    value = int(part)
    if name == "month" and not 1 <= value <= 12:
        raise ValueError(name)
    return value

def validate_iso_date_like_parser(date):
    class Parts:
        def __init__(self, seq):
            self.seq = list(seq)
            self.idx = 0
        def next(self):
            if self.idx >= len(self.seq):
                return None
            item = self.seq[self.idx]
            self.idx += 1
            return item
    parts = Parts(date.split('-'))
    year = parse_date_part(parts.next(), "year")
    month = parse_date_part(parts.next(), "month")
    day = parse_date_part(parts.next(), "day")
    if parts.next() is not None or len(date) != 10 or month == 0 or month > 12 or day == 0:
        return f"invalid ISO date `{date}`"
    return "ok"

cases = ["2026-08-04", "2026-1-001", "2026-1-01", "2026-01-1", "206-08-04", "2026-01-004", "2026-08-04-99"]
for c in cases:
    print(f"{c!r}: {validate_iso_date_like_parser(c)!r}")
PY

# Check whether any release output assertions verify target_date format in xtask/src/tests.rs.
rg -n 'target date|target_date|YYYY[-_]MM[-_]DD|invalid ISO date|noncanonical|2026-[0-9]|release_prep' xtask/src/tests.rs

Repository: flyingrobots/edict

Length of output: 6550


Reject noncanonical ISO dates before release preparation begins.

validate_iso_date accepts 2026-1-001, passes it to the changelog, policy, and release-notes scaffolds, and only checks total length plus range. Add the missing grammar checks at the entry point: fixed byte positions and fixed digit widths for each component. Use one stable InvalidIsoDate error for malformed dates, including parser errors from parse_date_part, without exposing parser-specific prose.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xtask/src/release_prep.rs` at line 75, Update the release-preparation entry
point around scaffold_release_date to enforce canonical ISO date grammar before
proceeding: validate fixed separators and four-, two-, and two-digit component
widths at the required byte positions. Convert all malformed-input cases,
including parse_date_part errors, into the single stable InvalidIsoDate error
without exposing parser-specific messages.

Source: Coding guidelines

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