fix(capture): stop waiting when the portal shows the GSTR-1 no-details dialog - #390
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s dialog A GSTR-1 period without e-invoice details spent the full 20 s generation timeout waiting for a file the portal never creates. The capture now stops as soon as the no-details text newly appears after its click, with the same reason, so the bound post-click inspection decides as before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review round 1 (local Sonnet): held as draftConfirmed safe: serialisation (self-contained; only Medium, accepted as the reason to hold: the early stop matches the two patterns against the whole page's Correction to part of the review's reasoning: the download safety net would not have caught that on today's path either. Next: scope the match to the portal's dialog element rather than page text. Per AGENTS (capture before spec), that needs a live structural capture of the dialog: element chain, roles and visibility only, no text or portal HTML pasted anywhere. Until then this stays draft. |
…rap modal Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… dialog Review of the first version found it matched page-wide text, so wording elsewhere could stop a capture early. A live capture shows the answer is an open Bootstrap modal; the early stop now reads only visible [role=dialog].modal.in elements. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Summary
Part of #386 (approved by the owner). A live timing probe on 2026-09-17 showed every GSTR-1 Excel capture in a full-year run ended in
generation-timeoutat 20003–20006 ms, 5 of 5, while GSTR-1 PDFs took 40–160 ms. The portal shows a no e-invoice details dialog instead of creating a file, and the capture waited out the full 20 s before the post-click inspection recognised the dialog. One run spent 100 s of pure waiting on GSTR-1 alone.The capture now stops waiting as soon as the portal's no-details dialog opens after its click, finishing with the same
generation-timeoutreason. Everything downstream is unchanged: checkpoint retention, the post-click inspection, and the refusal binding to the exact target (bindGstr1DetailRefusal), which is what actually decides the period has no Excel.Root Cause / Decision Record
detectGstr1ExcelNoDetailsmatched two text patterns and bound the refusal. Those two patterns move to a leaf,src/connectors/gst/gstr1-excel-no-details-text.ts, read by both the inspection and the capture, so there is one definition.capturePortalPdfBlobis serialised into the page byscripting.executeScript, so it can import nothing; the existingrebuildInMainWorldtest exercises the early stop through that serialisation.div.modal.fade.fade-scale.in[role="dialog"]>.modal-dialog.sweet>.modal-content>.modal-body>p. The early stop now reads only visible elements matching[role="dialog"].modal.in(GSTR1_EXCEL_NO_DETAILS_DIALOG_SELECTOR, beside the text patterns). Text outside such a dialog, a closed modal, a hidden one, or one carrying only one phrase does not stop it.Scope
portal-blob-shim.ts(optionalstopWhenDialogShows: { selector, textPatterns }, pre-click guard, poll);filed-returns-post-click-blocked-state.ts(reads the shared patterns); new leafgstr1-excel-no-details-text.ts;gstr2b-artifact-acquisition.ts(passes the patterns for GSTR-1 Excel only).docs/PORTAL_INTEGRATION_FINDINGS.mdfix(release): make release PRs pass Pack gates #36, the captured dialog structure and the measured timings (no page text, identifiers or HTML).Live verification
Needed. On the qualification build, run a GSTR-1 full year: periods without e-invoice details should settle in about a second instead of 20 s, still reading Saved · some formats not on portal, and the probe's GSTR-1 Excel rows should show short elapsed times.
Pack Workflow Preflight
pnpm workflow:preflightwas run before editing/push, or the skip reason is documented.Sanchika Adoption Gate
Not applicable: no Sanchika adoption.
@sanchika/*packages or copied Sanchika guidance, Iread
sanchika/docs/adoption-pack.mdin the coordinated parent worktree.and records the Sanchika commit or copied guidance used.
../sanchika,sanchika/packages/*/src, or parentsource paths.
Privacy And Data-Flow Impact
Sensitive Surface Review
Chrome Web Store Impact
docs/PUBLICATION_READINESS.mdis checked.Verification
pnpm install --frozen-lockfilepnpm audit --audit-level highpnpm exec wxt preparepnpm exec prettier --check .pnpm exec eslint . --max-warnings 0pnpm exec tsc --noEmitpnpm exec vitest runpnpm exec wxt buildnode scripts/verify-extension-package.mjs .output/chrome-mv3pnpm exec wxt zipnode scripts/verify-extension-zip.mjsnode scripts/write-release-provenance.mjsnode scripts/verify-github-release-assets.mjs --tag <tag> --zip <zip> --checksum <sha256> --provenance <json>when release assets existnode scripts/publish-chrome-web-store.mjs --zip .output/<zip> --provenance .output/pack-release-provenance.v1.json --publisher-id <id> --dry-run truegit diff --checkpnpm review:gate -- --strict-head-review --wait-head-review-ms 180000before merge/readiness claim; a missing Codex review blocks readiness:Artifact Evidence
PR Review Follow-Up
.inas Bootstrap 3's open marker (removed at hide-start), serialisation via the main-world rebuild test, docs entry #36 carries no sensitive data, one test per guard[role="dialog"].modal.in; commits dc0c9fa, 8fbb597, 000c5ecScreenshots
Use synthetic data only.
Verification detail
Exit codes captured directly: prettier
0· eslint0· tsc0· build0· package verification0·git diff --check0· workflow preflight passed.All tests related to the four changed modules:
Test Files 25 passed (25),Tests 1014 passed (1014).Driven to failure, each on its own: matching the whole page instead of the dialog selector fails the text-outside-a-dialog test; removing the pre-click guard fails the already-open test;
every→somefails the one-phrase test; removing the visibility check fails the hidden-dialog test; watching for every GSTR-1 artifact fails the wiring test for GSTR-1 PDF.One test fixture note: jsdom has no
innerText, and itstextContentjoins the button's text to the dialog's ("DownloadNo details"), which defeats the word boundary; the fixtures separate them with a newline, as a browser'sinnerTextdoes.🤖 Generated with Claude Code