fix(packs): repair the four broken system templates the validator found (#1388)

Phase 2a quarantined four defects rather than guessing at Swedish accounting.
Each is now resolved against a domain source. KNOWN_BROKEN is empty.

Löneutbetalning could never post. It debited 2710 @0.3 + 2920 @0.12 + 7010 @1.0
against a single 1.0 credit, totalling 1.42x the amount, so the balance trigger
would reject every entry built from it. Rebuilt per the swedish-payroll skill:
Debit 7010 gross, Credit 2710 tax, Credit 1930 net. The 2920 semesterlöneskuld
line is gone because vacation accrual is its own verifikat (7290/2920), and a
legal_note now says the 30% split is schablon and must be adjusted to the actual
skatteavdrag.

Periodiseringsfond avsättning/återföring referenced account 2113. Per
swedish-year-end-closing the year-tagged block is 2120-2129 (2126 = tax year
2026), so 2113 was the fund for tax year 2013: long since reversed and absent
from BAS 2026. Both now use 2110 Periodiseringsfonder, which does not rot
annually, with a legal_note pointing at the year-tagged accounts for a company
that tracks funds per year.

Preliminär F-skatt (EF) turned out to be RIGHT, and the reference was wrong.
Account 2012 "Avräkning för skatter och avgifter" was simply missing from
lib/bookkeeping/bas-data (the file jumps 2011 -> 2013), while the
swedish-year-end-closing skill uses it in two places as an enskild firma equity
sub-account. That is not cosmetic: account-backfill.ts only seeds accounts
present in BAS_REFERENCE, so any entry touching 2012 failed with
AccountsNotInChartError. Added it with the equity SRU code its siblings share,
and a description separating it from 1630, which carries a confusingly similar
name on the asset side.

The port test now distinguishes deliberate divergence from accidental drift:
a pack not listed in INTENTIONAL_DIVERGENCES must still match the seeded JSONB
exactly, and a listed pack must actually differ, so neither an unnoticed edit
nor a stale entry can survive.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-03 18:46:55 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Opus 5
parent 8299ee9fb4
commit 5b9605d8e9
7 changed files with 153 additions and 40 deletions
+5 -16
View File
@@ -51,22 +51,11 @@ const PROBE_AMOUNTS = [100, 1000, 1234.56, 99.99, 3333.33]
* deserves its own review rather than riding along inside a file-format change.
*/
const KNOWN_BROKEN: Record<string, string> = {
loneutbetalning:
'Does not balance: debits total 1.42x the amount (2710 @0.3 + 2920 @0.12 + 7010 @1.0) ' +
'against a single 1.0 credit, so applying it can never produce a postable verifikat. ' +
'Per the swedish-payroll skill the correct shape is Debit 7010 gross, Credit 2710 tax, ' +
'Credit 1930 net, and the 2920 semesterlöneskuld line belongs to a separate accrual entry. ' +
'Fixing it changes what the template posts: needs a domain sign-off.',
'periodiseringsfond-avsattning-ab':
'References account 2113, which is not in BAS 2026 and is not seeded into any company chart, ' +
'so the template cannot resolve. BAS 2026 has 2110 Periodiseringsfonder. Remapping it is a ' +
'domain decision (the 211x accounts are year-tagged).',
'periodiseringsfond-aterforing-ab':
'Same 2113 problem as periodiseringsfond-avsattning-ab.',
'preliminar-f-skatt-ef':
'References account 2012, which is not in BAS 2026 and is not seeded into any company chart. ' +
'The neighbouring egna-uttag accounts that do exist are 2011/2013/2017/2018. Picking the right ' +
'one is a domain decision.',
// Empty, and that is the point: the four templates ported out of migration
// 20260413160000 with real defects (an unbalanced salary template, and
// accounts that could not resolve) were fixed rather than accepted. The list
// may only shrink; the validator fails if an entry here validates cleanly, so
// a stale quarantine cannot linger.
}
interface Failure {