Skip to content

fix(gst): record a period the portal declined to generate - #354

Closed
lamemustafa wants to merge 8 commits into
tapish-codex/gstr1-artifact-surfacesfrom
tapish-codex/gstr2b-not-generated-outcome
Closed

fix(gst): record a period the portal declined to generate#354
lamemustafa wants to merge 8 commits into
tapish-codex/gstr1-artifact-surfacesfrom
tapish-codex/gstr2b-not-generated-outcome

Conversation

@lamemustafa

Copy link
Copy Markdown
Owner

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 of
the 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 nine Set declarations 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 — evidence
that 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

  • Runtime: Filed-returns contracts (one list, two predicates), nine fiscal-year and all-supported modules now deriving from it, durable status message, portal refusal detection, summary outcome vocabulary, both ZIP planners, popup outcome label.
  • Tests: Persist-then-read round trip for the new status, ZIP planning for a declined period, portal refusal detection, single-period bundle ledger. The refusal-detection tests move into a file named for the module they exercise, rather than sitting inside a GSTR-1 acquisition file that happened to import it first.
  • Docs/governance: None in this PR.
  • Explicitly out of scope: How the flow recognises the refusal on the page — that is the PR stacked on this one.

Pack Workflow Preflight

  • pnpm workflow:preflight was run before editing/push, or the skip reason is documented.
  • This PR was opened from a Pack branch, not master.
  • I checked latest master Pack AGENTS guidance or recorded the stale-guidance warning.
  • PR body keeps the required Pack privacy/review/verification checklist visible.

Sanchika Adoption Gate

  • If this PR consumes @sanchika/* packages or copied Sanchika guidance, I
    read sanchika/docs/adoption-pack.md in the coordinated parent worktree.
  • If this PR consumes Sanchika, it links ComplyEaze and Axal completion evidence
    and records the Sanchika commit or copied guidance used.
  • This PR does not import ../sanchika, sanchika/packages/*/src, or parent
    source paths.

Privacy And Data-Flow Impact

  • No new browser permissions.
  • No new host permissions.
  • No new network calls.
  • No analytics, telemetry, ads, or session replay.
  • No credential, OTP, CAPTCHA, cookie, token, GST file, or taxpayer-data capture.
  • Public copy and privacy declarations are updated if behaviour changed.

Sensitive Surface Review

Target binding unchanged. Completion still requires correlated chrome.downloads evidence: 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.

  • Current tab / portal target binding is preserved or intentionally changed.
  • Download completion remains evidence-backed and fail-closed.
  • Ambiguous side-effect delivery cannot be reported as confirmed success.
  • Service-worker durability impact is understood and documented.
  • Real taxpayer data, local paths, raw URLs/referrers, and portal HTML are absent from the diff.

Chrome Web Store Impact

  • This PR does not expand beyond the existing Chrome Web Store V0 listing unless every gate in docs/PUBLICATION_READINESS.md is checked.
  • Full fiscal year remains source-only and excluded from the next packaged Store build until its evidence gates are recorded.
  • Store copy, README status, Privacy QA, and reviewer instructions were reviewed if user-facing behavior changed.
  • CI ZIP creation, provenance, and protected publishing are treated as release evidence, not manual store-submission sign-off.
  • PR title uses Conventional Commits so Release Please can bump Pack after merge.

Verification

  • pnpm install --frozen-lockfile
  • pnpm audit --audit-level high
  • pnpm exec wxt prepare
  • pnpm exec prettier --check .
  • pnpm exec eslint . --max-warnings 0
  • pnpm exec tsc --noEmit
  • pnpm exec vitest run
  • pnpm exec wxt build
  • node scripts/verify-extension-package.mjs .output/chrome-mv3
  • pnpm exec wxt zip
  • node scripts/verify-extension-zip.mjs
  • node scripts/write-release-provenance.mjs
  • node scripts/verify-github-release-assets.mjs --tag <tag> --zip <zip> --checksum <sha256> --provenance <json> when release assets exist
  • node scripts/publish-chrome-web-store.mjs --zip .output/<zip> --provenance .output/pack-release-provenance.v1.json --publisher-id <id> --dry-run true
  • git diff --check
  • pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000 before 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

  • GitHub Actions completed.
  • Autogenerated Codex/bot review comments inspected after checks completed for the latest head SHA.
  • Inline review threads are resolved, outdated, or answered with evidence.
  • No commits were pushed after the last required human/bot review without re-review.
  • Any follow-up PRs or issues are listed here instead of being left implicit.
Thread/comment Disposition Commit or evidence
accepted / fixed / outdated / follow-up

Screenshots

Use synthetic data only.

Stacking

Stacked on #353 (tapish-codex/gstr1-artifact-surfaces). Review that first; this PR's diff is only
meaningful on top of it.

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.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T00:07:46.214359Z ac4c050 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 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".

Comment thread src/connectors/gst/filed-returns-post-click-blocked-state.ts Outdated
Comment thread src/background/filed-returns-full-fiscal-year-validation.ts
Comment thread src/background/filed-returns-single-period-bundle-ledger.ts
Comment thread src/connectors/gst/filed-returns-post-click-blocked-state.ts
Comment thread src/connectors/gst/filed-returns-contracts.ts
Comment thread src/background/filed-returns-full-fiscal-year-summary.ts
Comment thread src/background/filed-returns-single-period-bundle-ledger.ts
Comment thread src/background/filed-returns-full-fiscal-year-summary.ts
Comment thread src/connectors/gst/filed-returns-contracts.ts
`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.

@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: 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".

Comment thread tests/connectors/filed-returns-post-click-blocked-state.test.ts
Comment thread src/background/filed-returns-full-fiscal-year-summary.ts
Comment thread src/connectors/gst/filed-returns-post-click-blocked-state.ts
…aces' into tapish-codex/gstr2b-not-generated-outcome

# Conflicts:
#	src/connectors/gst/filed-returns-post-click-blocked-state.ts
@lamemustafa

Copy link
Copy Markdown
Owner Author

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.

@lamemustafa
lamemustafa marked this pull request as draft September 12, 2026 11:12
@lamemustafa

Copy link
Copy Markdown
Owner Author

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.

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