fix(gst): record a period the portal declined to generate - #354
fix(gst): record a period the portal declined to generate#354lamemustafa wants to merge 8 commits into
Conversation
The portal drafts the GSTR-2B statement rather than the taxpayer filing it, and for a period with no inward supplies it drafts nothing. Recording that as not-filed would print a claim about the taxpayer the portal never made, so it becomes its own resolved status. Twelve hand-kept copies of the target-status lists decided what a run may persist, and none of them learned about the new status. A saved plan therefore failed to parse the moment a period used it, which threw out of the background handler and took the whole run's details with it. A Set<Union> literal is not exhaustiveness-checked, so nothing failed to compile. All twelve now derive from the one list that defines them. Nine of them were the same fact under nine names and are gone entirely: every consumer asked .has(status), which the shared predicate answers. The recoverable set turned out to be the exact complement of resolved, so it derives too rather than being restated and drifting. Both fiscal-year ZIP planners asked the same four-branch question about what a period earns in the summary; a period the portal declined defaulted to staged, becoming a file the run then reported itself as having failed to produce and blocking the ZIP for a whole year on it. One named rule now answers it for both.
…rate The suite was green while a saved plan could not be read back, so the missing test is the round trip itself: persist a ledger holding the new status, then read it. A guard that only checked a return value would have passed.
The set of reasons and the map from flow signal to reason were two more copies of the pair the diagnostics module now owns. Both derive from it, so a third portal refusal is one line rather than five edits across three modules.
The guard deciding whether a cancelled run may be replaced without asking listed downloaded, manually-observed and not-filed. A declined period is the portal answering that there is nothing to download, exactly as an unfiled one is, so a run holding one was protected and a run holding the other was not. Two more copies of the resolved split turned up written as || chains rather than sets, which is why the earlier sweep missed them: one was the exact complement of resolved, the other that minus the two states a run reaches by itself. Both derive now, and the second is shared with the all-returns path that asked the same question.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba244317f3
ℹ️ 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".
`detectPostClickBlockedState` resolved the GSTR-2B refusal from the target's return type plus whatever text was on the body. No route, year, period or action identity took part, and the signal it emits is terminal. The summary route does not change per period, and the panel outlives the period it was loaded for, so one period's refusal would answer for every later period a run asks about -- which is exactly how the observation path next door recorded eleven months a live run never navigated to. A target is a scope with an action id, so the guard that path already uses applies here unchanged: no new recogniser, no second notion of what counts as the visible period. Removing a duplicate on the way: `normalisedPageText` was a second copy of `normaliseText` that skipped the lower-casing, so the label patterns could not have matched against it. Both readers now take the same reading of the page.
The two existing fixtures carried no header block, which the captured live panel does -- being the reason the panel can outlive its period at all. Bringing them to the captured shape is what makes the binding testable. Both new cases fail with the guard removed.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84f91b2ccc
ℹ️ 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".
…aces' into tapish-codex/gstr2b-not-generated-outcome # Conflicts: # src/connectors/gst/filed-returns-post-click-blocked-state.ts
|
The corrected consolidated candidate is #359, based directly on master. This PR is retained as draft with its commits and review history intact; its unchanged head is not independently merge-ready. The #359 body maps every original automated ask to specific source/test evidence or an explicit held follow-up. Authenticated runtime qualification remains required before merging the replacement. |
|
Superseded by #359. Its disposition register records the final status of this draft’s review asks. This draft is being closed; resolving its remaining threads marks them superseded, not fixed on this unchanged branch. |
Summary
A period the GST Portal declined to generate becomes a first-class resolved outcome, and the twelve
hand-kept copies of the target-status list that made it unrepresentable collapse to one.
GSTR-2B is auto-drafted by the portal rather than filed by the taxpayer, and for a period with no inward
supplies the portal drafts nothing and says so. Recording that as not filed would print a claim about the
taxpayer the portal never made, so it is its own status.
Root Cause / Decision Record
What failed. Adding one status to a union caused a live run to throw out of the background message
handler and take the run's details with it. A saved plan failed to parse the moment a period used the new
status, because a runtime allowlist had never been told about it.
new Set<SomeUnion>([...])is not exhaustiveness-checked, so this compiled cleanly. Twelve copies ofthe status lists existed; nine were the same fact under nine names.
Why this is the smallest safe fix. Deriving is smaller than patching: every consumer was already asking
.has(status), so nineSetdeclarations became one shared predicate and two derived lists disappeared(the recoverable set is the exact complement of resolved, so it is computed rather than restated). The one
path that was already correct used an exhaustive
Record<Union, Outcome>and needed no change — evidencethat the compiler, not more code, is the fix.
Also here. Both fiscal-year ZIP planners asked the same four-branch question about what a period earns
in the summary; a declined period defaulted to staged, becoming a file the run then reported itself as
having failed to produce, blocking a whole year's export. One named rule now answers it for both. And the
status had no durable message, so it fell through to copy telling the user to check browser Downloads for a
file the portal had just said it never produced.
Scope
Pack Workflow Preflight
pnpm workflow:preflightwas run before editing/push, or the skip reason is documented.Sanchika Adoption Gate
@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
Target binding unchanged. Completion still requires correlated
chrome.downloadsevidence: the new status means the portal produced nothing, and is never derived from a click. Durable state is affected by design -- a status the parser previously rejected is now accepted -- so a persist-then-read round trip is pinned.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
No release artifact in this PR; it ships no ZIP and changes no release metadata.
Verification above was run on this branch in an isolated worktree, so the result is the branch's own and not
the stack tip's.
PR Review Follow-Up
Screenshots
Use synthetic data only.
Stacking
Stacked on #353 (
tapish-codex/gstr1-artifact-surfaces). Review that first; this PR's diff is onlymeaningful on top of it.