Repository navigation
chore(fidelity): single upstream pin, SHA check, it.each extraction, two-tier mapping (#185) - #249
Conversation
…two-tier mapping (#185) - scripts/upstream_pin.json is the single pin source (pin chat@4.31.0 and target chat@4.41.1, with full commit SHAs); the script, lint.yml (jq) and the CLAUDE.md clone snippet read it. - CI and the script fail when the checkout HEAD differs from the pinned SHA (closes #79); the script only warns for a plain export. - --check-docs guards CLAUDE.md / docs/UPSTREAM_SYNC.md against stale pin literals; pin major.minor must match UPSTREAM_PARITY. - it.each / test.each templates count as one logical test (placeholders stripped); test() counts; describe.each titles are used for reporting. Strict fidelity at the pin is now 733/733. - Two tiers: MAPPING (strict) + TARGET_MAPPING (--report-target only) + UNMAPPED (reasons), with a completeness check over core *.test.ts(x). - --report-target writes scripts/fidelity_target.json (committed for chat@4.41.1: 282 missing of 1036, incl. 16 .each templates). - Fuzzy-match ties now break deterministically (sorted candidates). Tooling only; no consumer-visible behavior change. Part of #184.
|
Warning Review limit reachedNext included review available in 28 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (10)
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. Comment |
…uzzy order, checkout/doc guards (#185) - Fuzzy pass matches plain tests before .each templates; regenerated fidelity_target.json (chat.test.ts GitHub-login test now credited, the isMention template reported missing; total stays 282). - Extractor reads modifier chains, .for, <T> type args, skipIf/runIf, single-quoted and wrapped titles; unknown call forms warn. - --strict / --report-target fail on any extraction warning. - SHA check fails when TS_ROOT/.git exists but git cannot read it, and on local edits under packages/chat/src; mismatch hint clones into a fresh directory. - --check-docs: case-insensitive, --branch=, -b, continuations, markdown. - --report-target prints plain MISSING (no baseline marker). - UPSTREAM_SYNC.md: full clone at /tmp/vercel-chat-full, pinned checkout at /tmp/vercel-chat. - CLI-level tests for --check-docs, --report-target SHA/overlap/delta and the parity check.
# Conflicts: # CHANGELOG.md
…eep scanning after describe modifiers
…-report snapshot test
# Conflicts: # CHANGELOG.md
…sed on unterminated literals, reject computed titles
…eckouts and unverifiable absences
|
Merge gate: CI green (Lint & Type Check, test (3.12), test (3.13), CodeQL, Analyze (actions), Analyze (python)); local Codex review (gpt-6-astra, xhigh, --base origin/main) on 209230e: "No actionable regressions found. All 116 tooling tests passed, strict fidelity verified 733/733 tests against the pinned upstream commit, and regenerating the target report reproduced the committed report exactly."; 2 astra rounds after merging main (#205, #231, #243): round 1 found a P2 ( |
Summary
This PR adds the fidelity tooling for the 4.41 wave. The tool can now report what is missing against
chat@4.41.1while CI stays strict atchat@4.31.0. It is tooling only: no runtime changes, no test ports, and the pin does not move (that is #203).Target report (committed as
scripts/fidelity_target.json,chat@4.41.1@f690af3c):MAPPING, 13 files)TARGET_MAPPING, 11 files).eachtemplates)The strict-tier missing count by file: chat 33, ai/index 26, thread 18, serialization 17, ai/messages 10, from-full-stream 9, markdown 7, callback-url 5, transcripts-wiring 4, transcripts 1.
The issue estimated about 132; the report says 130. The fuzzy matcher claims one
.eachtemplate,thread.test.ts's$labeltemplate, as the issue predicted. The fuzzy claims are listed per file infuzzy_matches. The fuzzy pass now matches plain tests before.eachtemplates (see Review), sochat.test.ts'sshould not treat %s as a mention (%s)template is correctly reported missing, and the plainshould not match GitHub-style logins as Slack ids (case sensitivity)test is credited to its existing translation.Strict at the pin: 733/733. It was 732:
thread.test.ts:622'sit.eachis now counted, and it matchestests/test_thread_faithful.py:953.What changed
scripts/upstream_pin.json. It holdspin(chat@4.31.0@2a553aa9…) andtarget(chat@4.41.1@f690af3c…) with full SHAs.write_baselinefallback and in the clone hint are gone.lint.ymlreads it viajq.CLAUDE.md,docs/UPSTREAM_SYNC.mdandCONTRIBUTING.mdclone snippets use$(jq -r .pin.tag scripts/upstream_pin.json).pin.sha, and writes the SHA to$GITHUB_STEP_SUMMARY.TS_ROOTis the top level of a git checkout;--report-targetchecks againsttarget.sha.--check-docsmode, run as a new CI step. It fails if a--branch chat@Xorpinned to [vercel/]chat@Xphrase inCLAUDE.mdordocs/UPSTREAM_SYNC.mddiffers frompin.tag; the phrase may wrap across lines. This fixed the stale4.30.0line. Thelint.ymlpathsfilters now includeCLAUDE.md,docs/UPSTREAM_SYNC.mdand the pin file.pin.tagmust equal that ofUPSTREAM_PARITY. It runs in every mode, reads__init__.pyby regex, and never importschat_sdk.it.each/test.eachtemplate counts as one logical test. The placeholders%s %d %i %f %j %o %O %c %p %# %$ %%,$nameand$a.bare stripped only in.eachtitles, thents_name_to_pythonruns.])("…",] as const)("…", computed)("…"and tagged-template tables. It skips strings, template literals and comments. A dynamic title or a placeholder-only title produces a warning.test("…")now counts;regex.test("…")does not.describe.eachtitles are used only for reporting.MAPPINGis unchanged and stays strict.TARGET_MAPPING:history/user→test_transcripts.py;history/{thread,channel,to-prompt}→test_history_*.py([4.41/C8] Unified History API (bot.history.user/thread/channel), to_prompt_entries, transcripts deprecation #197);agent-session→test_agent_session.py([4.41/C7] Turn cancellation: abort_turn, thread.signal, typing options, agent-session events #201);app-contextandinstallation-events→ [4.41/C4] Core lifecycle events: message updated/deleted, installed/uninstalled, app context changed #196 files;cards,modals,emoji→ existing files;message→test_types.py(provisional).UNMAPPED, with reasons:ai/tanstack/*,workflow/approval, the threejsx-*files andadapters/index, plus "Extend verify_test_fidelity.py MAPPING to cover all packages/chat/src/*.test.ts #78 pending" forerrors,loggerandchat-singleton.packages/chat/src/**/*.test.ts(x)must be classified. An unclassified file warns at the pin and errors in--report-target.--report-targetchecksMAPPING ∪ TARGET_MAPPINGand never fails on missing tests.[describe, it]pairs, the extra count, exact/fuzzy counts and the fuzzy pairs.fuzzy_matchiterated aset, so score ties were broken by the per-process string hash seed. The target total flipped between 282 and 283 missing across runs. Candidates are now scanned in sorted order. Strict at the pin is 733/733 under 8 differentPYTHONHASHSEEDs, and the report is byte-identical across seeds.docs/UPSTREAM_SYNC.md§ Test fidelity was rewritten to cover the pin file, the two tiers, theUNMAPPEDreasons table, the target report and the guardrails.CLAUDE.md§ Test Quality andCONTRIBUTING.mdwere updated.CHANGELOG.mdgets a new "Unreleased (4.41 wave)" section, marked tooling-only.scripts/fidelity_baseline.json: thetotal_ts_testscount is 733, and the_commentno longer names the tag.Upstream mapping
636da193(#972, chat@4.41.1) pruned and merged tests. The resulting Python "Extra" counts are only reported; each owning wave issue decides what to delete.169788b6(history/*),2ce2be00(agent-session),1721fa01(app-context),2e2426d1(installation-events),2d0d3bf3(ai/tanstack) and4cb7e5d5(workflow/approval). The new.eachtemplates in mapped files come fromb547f458,5b538f6f,93a58af5,6f17495band056d8830.Tests
There are no upstream tests to port. New
tests/test_verify_test_fidelity.pyhas 112 tests (44 originally, 44 more from the first review round, 24 more from the gpt-6-astra rounds; see Merge gate) and loads the script viaimportlib.util.spec_from_file_location. It covers:chat@4.41.1template shapes:should not treat %s as a mention (%s)…via $labelretains $expected entries with maxPerUser=$maxPerUsermerges legacy maxPerUser=%s under history.user$access/$singletontemplatedescribe.each(...)("on%s")it("100% done")staying unchanged, andregex.testnot counting;%%s, and the scanner ignoring brackets inside strings and comments;--branch chat@4.30.0and on a wrappedpinned\nto;*.test.ts;UPSTREAM_PARITYmajor.minor check;I mutation-checked the tests against 11 injected faults and 10 were caught. The one survivor is an equivalent mutant: reordering the
%%alternative, where%is not in the character class. That first round did not cover the CLI wiring. In the review round I ran a second check of 17 faults, covering the reviewer's 7 survivors plus faults in each new guard, and all 17 were caught.Divergences
None. This is tooling only and adds no non-parity rows.
Consumer impact
None; this is tooling only.
Validation
ruff check,ruff format --check,audit_test_quality.py(0 hard failures),--check-docs, strict fidelity atchat@4.31.0(733/733),pytest(5451 passed, 13 skipped, after mergingmain) andpyrefly(0 errors) all pass.One note on the environment(resolved:mainnow caps the Teams SDK below 2.1, #251, and this branch has merged it):uv.lockis gitignored. A freshuv syncresolvesmicrosoft-teams-apps2.1.0, and with it 3 existing Teams tests fail with'App' object has no attribute 'activity_sender'. They pass with 2.0.13.4, which is what the main checkout's venv uses. This is unrelated to this PR and does not touchsrc/or the Teams tests. CI resolves fresh, so it may hit the same failure.Follow-ups
scripts/fidelity_target.jsonwithTS_ROOT=<chat@4.41.1 checkout> uv run python scripts/verify_test_fidelity.py --report-targetand quotes the printed delta.Review
Two reviewers sent 11 findings. I checked each one myself: 10 are fixed in
958c8f2and 1 is declined. Every fix has a test that fails without it.Fixed
(major) An
.eachtemplate could steal a plain test's fuzzy match.check_fidelitypass 2 now fuzzy-matches plain tests first, then.eachtemplates; the report stays in file order.fidelity_target.json.chat.test.ts"should not match GitHub-style logins as Slack ids (case sensitivity)" is now matched, andshould not treat %s as a mention (%s)is reported missing. Thethread$labeltemplate still matches, and the total stays at 282.test_fuzzy_pass_matches_plain_tests_before_each_templatesandtest_committed_target_report_credits_the_plain_github_login_test.(minor) Vitest
.eachvariants were dropped with no warning.skip,only,concurrent,sequential,fails,shuffle) before.each/.for;<T>type arguments, including nested generics and=>;.skipIf(c)/.runIf(c);it.skip("…");it/test/describecall form (it.todo,it.extend, a non-literal title) produces a warning.test_vitest_call_variants_are_extracted,test_unknown_test_call_forms_warn_instead_of_vanishingandtest_prose_and_strings_are_not_test_calls.(minor)
--report-targetlabelled every miss "MISSING (baselined)". It now prints plainMISSING:. Test:test_report_target_lists_missing_without_a_baseline_marker.(minor) The SHA-mismatch hint re-cloned into the existing
TS_ROOT.test_sha_mismatch_hint_clones_into_a_fresh_directory.(minor) The Extend verify_test_fidelity.py MAPPING to cover all packages/chat/src/*.test.ts #78 progress comment had not been posted. It is posted now; see Follow-ups.
(major) The CI-facing wiring was untested. New CLI-level tests cover:
--check-docsreturns 0 for the pin, and 1 for a stale tag or the target tag;--report-targetpasses with the target SHA, and fails with the pin SHA or any other SHA, without writing the report;--report-targetfails on a MAPPING/TARGET_MAPPING overlap;--strictfails on a pin/UPSTREAM_PARITYmismatch.All 7 of the reviewer's surviving mutants are now caught (17 of 17 in my re-run).
(major)
--strictpassed when a.eachtemplate could not be extracted.--strictand--report-targetnow treat every extraction warning as an error: they listfile:line, exit 1, and--report-targetdoes not write the report. Baseline mode still only warns.${}title, a placeholder-only title):test_strict_fails_closed_on_unextractable_upstream_tests,test_report_target_fails_closed_…andtest_baseline_mode_only_warns_….(minor) The SHA check passed when git failed on a real checkout.
TS_ROOT/.gitexists but git cannot read HEAD, the check now fails with git's stderr. The warning is kept only for true plain exports.test_sha_check_fails_closed_when_git_cannot_read_an_existing_dot_git.(minor) A checkout with a pruned working tree passed as "verified".
git status --porcelain --untracked-files=no -- packages/chat/srcmust be empty.test_sha_check_rejects_local_edits_to_upstream_test_files.(minor) The
--check-docsregex missed common variants.--branch=,-b, a\line continuation,pinned to the …, and**/_/ backtick /[decoration.test_doc_drift_catches_stale_pin_variants). The real docs still pass.(minor) The docs contradicted the SHA check.
docs/UPSTREAM_SYNC.md, the full clone for reading diffs (step 1 and "How to Diff Upstream Changes") now lives at/tmp/vercel-chat-full./tmp/vercel-chatis always the pinned shallow checkout, as in step 5, the "Final parity check" row,CLAUDE.mdand CI.Declined: none. Finding 5 is a process item rather than code; I resolved it by posting the comment.
CI note, outside this PR (resolved by #251, merged into this branch; CI is now green):
test (3.12)/test (3.13)fail on 3 Teams tests ('App' object has no attribute 'activity_sender', andfake_update() got an unexpected keyword argument 'service_url'). CI resolvesmicrosoft-teams-apps2.1.0 fresh, becauseuv.lockis gitignored. The same tests fail onmain's code, since this PR touches nosrc/or Teams tests. With the SDK overlaid at 2.0.13.4 the whole suite passes: 5235 passed, 13 skipped.Lint & Type Checkis skipped because the PR is a draft (if: !github.event.pull_request.draft). I ran every lint step locally, and all pass: ruff, format, audit (0 hard failures),--check-docs, strict 733/733 atchat@4.31.0, and pyrefly (0 errors).Closes #185
Closes #79
Part of #184
Merge gate
Final HEAD:
691d815(includesmain@c77730b).gpt-6-astra: 6 runs. Final verdict on
691d815: "No actionable regressions found. All 112 focused tests passed, as did lint, formatting, doc-pin validation, and strict fidelity verification at 733/733. Regenerating the target report reproduced the committed report exactly."50be6a2(after mergingmain/ #251)89fb863)89fb863ea94072)ea94072d1e500c(after mergingmainagain)5e528c0)5e528c0691d815(after mergingmainagain)Fixed. Each fix has a test that fails on the previous commit. After every fix, extraction over every upstream
packages/**/*.test.ts(x)at bothchat@4.31.0andchat@4.41.1(9,516 lines of output) was byte-identical to before the fix. Strict stays 733/733, and the target report stays 282 missing.describemodifier used up the line's test slot.describe.only("s", () => { it("t") })droppedit("t"). Scanning now continues after adescribecall. Test:test_describe_call_does_not_consume_the_line_test(describe.only,.skip,.each).'test("x")'fixture string counted as a test, and a commented-out// it.each(cases)(name, fn)was reported as unextractable, which aborted--strict. A newcode_masklexer marks comments and string, template and regex literals, and calls are only discovered in code. Tests:test_calls_inside_strings_comments_and_regexes_are_ignored(8 shapes) andtest_real_tests_around_literals_are_still_extracted.test_committed_target_report_credits_the_plain_github_login_testasserted that the committedfidelity_target.jsonstill lists a missing test, so a wave PR that ports it would have failed. It is removed. The matcher regression stays covered by the synthetictest_fuzzy_pass_matches_plain_tests_before_each_templates.--report-targetdelta compared against the working copy. A second run before committing compared against the first run's output and printed+0. The delta now reads the report committed atHEADviagit show. Tests:test_report_target_prints_delta_against_the_report_committed_at_head(two runs, both-1) andtest_report_target_ignores_an_uncommitted_working_copy_for_the_delta.if (…)was lexed as division. Inif (x) //.test(v), the regex's backtick opened a template that hid the following tests. The lexer now tracks which(followsif/while/for/with. As defense in depth, a template literal,${…}or block comment still open at end of file is an extraction error, so it fails--strict; the file then falls back to scanning everything as code. Tests:test_regex_after_control_flow_parens_does_not_mask_later_testsandtest_unterminated_literal_fails_closed_instead_of_masking_the_rest`.it.each(…)("rejects " + kind + " %s")was read as"rejects ". A title literal must now be followed by,or), and otherwise it is an extraction error. This applies to plain,.eachand.skipIfcalls. Tests:test_computed_title_is_unextractable_not_its_literal_prefixandtest_literal_title_followed_by_whitespace_or_paren_still_extracted.Rebutted: none.
Bot comments: CodeRabbit only posted its rate-limit notice ("Review limit reached") and never reviewed. gemini-code-assist did not post. No inline comments or reviews exist, so there was nothing to address.
CI on
691d815: all green.Lint & Type Check(every step, including the pin SHA check,--check-docs, strict fidelity and pyrefly),test (3.12),test (3.13), CodeQL (Analyze (actions),Analyze (python)).Local validation on
691d815:ruff check,ruff format --check,audit_test_quality.py(0 hard failures),--check-docs, strict fidelity atchat@4.31.0(733/733),pytest(5451 passed, 13 skipped),pyrefly(0 errors).--report-targetatchat@4.41.1reproduces the committed report (282 → 282).