262 lines
13 KiB
JSON
262 lines
13 KiB
JSON
[
|
||
{
|
||
"id": "C1-cap-removed",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"pin": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"what": "предел снят вовсе",
|
||
"old": "\tif l.AttemptNo >= s.maxAttempts() {",
|
||
"new": "\tif false {"
|
||
},
|
||
{
|
||
"id": "C2-cap-off-by-one",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"pin": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"what": "предел сдвинут на единицу — прогон получает попытку сверх разрешённого",
|
||
"old": "\tif l.AttemptNo >= s.maxAttempts() {",
|
||
"new": "\tif l.AttemptNo > s.maxAttempts() {"
|
||
},
|
||
{
|
||
"id": "C3-cap-on-the-counter-a-restart-resets",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"pin": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"what": "предел положен на счётчик отсрочек — тот, что рестарт обнуляет по построению",
|
||
"old": "\tif l.AttemptNo >= s.maxAttempts() {",
|
||
"new": "\tif l.ReconcileFailures >= s.maxAttempts() {"
|
||
},
|
||
{
|
||
"id": "C4-cap-does-not-end-the-run",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"pin": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"what": "упёрлись в предел и НЕ закончили прогон — он остаётся живым навсегда",
|
||
"old": "\t\treturn s.finish(ctx, l, ending)",
|
||
"new": "\t\treturn nil"
|
||
},
|
||
{
|
||
"id": "C5-policy-word-not-written",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"pin": "TestTheRestartLoopStopsAtTheCapWithTheMoneyClosedAndNoNewHold",
|
||
"what": "наше слово подменено на «юнит исчез» — политика снова неотличима от чужого обрыва",
|
||
"old": "\t\tending.Result = runner.AttemptsExhaustedResult",
|
||
"new": "\t\tending.Result = runner.UnitVanishedResult"
|
||
},
|
||
{
|
||
"id": "C6-exhaustion-called-retryable",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAnExhaustedRunIsNotCalledARetryableInterruption",
|
||
"pin": "TestAnExhaustedRunIsNotCalledARetryableInterruption",
|
||
"what": "исчерпание выпало из списка причин — клиенту обещан повтор после двадцати повторов",
|
||
"old": "\t\trunner.AttemptsExhaustedResult:\n\t\treturn \"service_error\"",
|
||
"new": "\t\t\"nothing-systemd-writes\":\n\t\treturn \"service_error\""
|
||
},
|
||
{
|
||
"id": "C7-limit-invisible-before-the-wall",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestEveryRestartSaysHowCloseTheCapIs",
|
||
"pin": "TestEveryRestartSaysHowCloseTheCapIs",
|
||
"what": "строка перезапуска больше не несёт потолка — стену не видно заранее",
|
||
"old": "\"attempt\", next.AttemptNo,\n\t\t\"cap\", s.maxAttempts())",
|
||
"new": "\"attempt\", next.AttemptNo)"
|
||
},
|
||
{
|
||
"id": "C8-default-cap-out-of-its-band",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheDefaultAttemptCapStaysInTheBandItsArgumentGives",
|
||
"pin": "TestTheDefaultAttemptCapStaysInTheBandItsArgumentGives",
|
||
"what": "дефолт уведён за полосу, которую даёт его собственный довод",
|
||
"old": "const DefaultMaxAttempts = 20",
|
||
"new": "const DefaultMaxAttempts = 500"
|
||
},
|
||
{
|
||
"id": "B1-no-write-ahead-mark",
|
||
"file": "internal/runs/bank.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheWriteAheadMarkIsCommittedBeforeTheVerbRuns",
|
||
"pin": "TestTheWriteAheadMarkIsCommittedBeforeTheVerbRuns",
|
||
"what": "намерение не ставится вовсе — смерть в глаголе снова без канала",
|
||
"old": "\tif !in.Preview {\n\t\tif err := s.Store.MarkBankMovePending(",
|
||
"new": "\tif in.Preview {\n\t\tif err := s.Store.MarkBankMovePending("
|
||
},
|
||
{
|
||
"id": "B2-reader-ignores-the-mark",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAResumeAfterACorrectionWhoseStampWasLostStillGrantsTheConsents",
|
||
"pin": "TestAResumeAfterACorrectionWhoseStampWasLostStillGrantsTheConsents",
|
||
"what": "факт читается без намерения — резюм снова идёт без пере-снапшота",
|
||
"old": " (b.bank_moved_at is not null or b.bank_move_pending_at is not null),",
|
||
"new": " (b.bank_moved_at is not null),"
|
||
},
|
||
{
|
||
"id": "B3-retirement-forgets-the-mark",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestRetiringTheBankMoveRetiresItsWriteAheadMarkToo",
|
||
"pin": "TestRetiringTheBankMoveRetiresItsWriteAheadMarkToo",
|
||
"what": "ретайр факта не снимает намерения — флаг становится вечным",
|
||
"old": "`update books set bank_moved_at = null, bank_move_pending_at = null where id = $1`",
|
||
"new": "`update books set bank_moved_at = null where id = $1`"
|
||
},
|
||
{
|
||
"id": "B4-stamp-leaves-the-mark",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAStampRetiresTheMarkItStoodInFor",
|
||
"pin": "TestAStampRetiresTheMarkItStoodInFor",
|
||
"what": "штамп не снимает намерение, которое за него стояло",
|
||
"old": "`update books set bank_moved_at = now(), bank_move_pending_at = null where id = $1`",
|
||
"new": "`update books set bank_moved_at = now() where id = $1`"
|
||
},
|
||
{
|
||
"id": "B5-mark-dropped-without-a-receipt",
|
||
"file": "internal/runs/bank.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAVerbThatMayHaveDiedMidWriteKeepsItsMark",
|
||
"pin": "TestAVerbThatMayHaveDiedMidWriteKeepsItsMark",
|
||
"what": "намерение снимается на ЛЮБОМ исходе — убитый глагол теряет свою улику",
|
||
"old": "\tif !in.Preview && ((err == nil && !corrected(rec)) || errors.As(err, &refused)) {",
|
||
"new": "\tif !in.Preview {"
|
||
},
|
||
{
|
||
"id": "L1-quarantine-half-dropped",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestARunWhoseProjectionIsNotFollowingItSaysSoToTheBuyer",
|
||
"pin": "TestARunWhoseProjectionIsNotFollowingItSaysSoToTheBuyer",
|
||
"what": "поле молчит на карантине — лжёт в половине своей популяции",
|
||
"old": "\t and (a.parked_at is not null or a.quarantine_reason is not null)),",
|
||
"new": "\t and (a.parked_at is not null)),"
|
||
},
|
||
{
|
||
"id": "L2-history-reported-as-todays-lag",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAParkAnEarlierAttemptEndedWithIsNotReportedAsTodaysLag",
|
||
"pin": "TestAParkAnEarlierAttemptEndedWithIsNotReportedAsTodaysLag",
|
||
"what": "парковка ЗАКОНЧЕННОЙ попытки предъявляется как сегодняшнее отставание",
|
||
"old": "\texists (select 1 from run_attempts a where a.run_id = r.id and a.ended_at is null",
|
||
"new": "\texists (select 1 from run_attempts a where a.run_id = r.id"
|
||
},
|
||
{
|
||
"id": "L3-wire-drops-the-member",
|
||
"file": "internal/httpapi/project.go",
|
||
"pkg": "./internal/httpapi",
|
||
"run": "TestTheRunTheWireServesCarriesBothMembersTheMinorAdded",
|
||
"pin": "TestTheRunTheWireServesCarriesBothMembersTheMinorAdded",
|
||
"what": "провод всегда отдаёт false — канон объявил форму, которой сервис не отдаёт",
|
||
"old": "\t\tProgressLagging: r.ProgressLagging,",
|
||
"new": "\t\tProgressLagging: false,"
|
||
},
|
||
{
|
||
"id": "K1-consent-not-projected",
|
||
"file": "internal/httpapi/project.go",
|
||
"pkg": "./internal/httpapi",
|
||
"run": "TestTheRunTheWireServesCarriesBothMembersTheMinorAdded",
|
||
"pin": "TestTheRunTheWireServesCarriesBothMembersTheMinorAdded",
|
||
"what": "сумма согласия не уходит на провод — человек снова не видит, что подписывает",
|
||
"old": "\tif r.RebillConsent > 0 {",
|
||
"new": "\tif false {"
|
||
},
|
||
{
|
||
"id": "K2-consent-read-as-zero",
|
||
"file": "internal/pgstore/books.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheConsentAResumeGrantedIsVisibleWithItsRun",
|
||
"pin": "TestTheConsentAResumeGrantedIsVisibleWithItsRun",
|
||
"what": "согласие читается нулём из строки прогона",
|
||
"old": "\tr.accept_rebill_micro`",
|
||
"new": "\t0`"
|
||
},
|
||
{
|
||
"id": "V1-ending-not-announced",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAKillByOurOwnGraceIsRecordedWhereAPersonCanSeeIt",
|
||
"pin": "TestAKillByOurOwnGraceIsRecordedWhereAPersonCanSeeIt",
|
||
"what": "конец прогона больше не НАЗЫВАЕТ слово машины — факт остаётся только в колонке",
|
||
"old": "s.log().InfoContext(ctx, \"run finished\", \"run\", l.RunID, \"status\", status, \"result\", m.Result)",
|
||
"new": "s.log().InfoContext(ctx, \"run finished\", \"run\", l.RunID, \"status\", status)"
|
||
},
|
||
{
|
||
"id": "G1-canon-drops-the-promise",
|
||
"file": "../docs/architecture/14-api-contract/openapi.yaml",
|
||
"pkg": "./internal/httpapi",
|
||
"run": "TestEveryAlwaysSentMemberOfARunIsPromisedByTheCanon",
|
||
"pin": "TestEveryAlwaysSentMemberOfARunIsPromisedByTheCanon",
|
||
"what": "канон перестаёт ОБЕЩАТЬ член, который провод всегда посылает",
|
||
"old": " - progress_lagging",
|
||
"new": " # - progress_lagging"
|
||
},
|
||
{
|
||
"id": "G2-wire-renames-a-promised-member",
|
||
"file": "internal/httpapi/v0.go",
|
||
"pkg": "./internal/httpapi",
|
||
"run": "TestEveryAlwaysSentMemberOfARunIsPromisedByTheCanon",
|
||
"pin": "TestEveryAlwaysSentMemberOfARunIsPromisedByTheCanon",
|
||
"what": "провод шлёт член под ДРУГИМ именем — канон обещает одно, сервис отдаёт другое",
|
||
"old": "json:\"rebill_consent_micro_usd\"",
|
||
"new": "json:\"rebill_consent\""
|
||
},
|
||
{
|
||
"id": "S1-belt-on-a-shrinking-consent",
|
||
"file": "internal/runs/reconcile.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestTheConsentAResumeGrantedIsVisibleWithItsRun",
|
||
"pin": "TestTheConsentAResumeGrantedIsVisibleWithItsRun",
|
||
"what": "ПОЯС на съеденное меньшее согласие снят — населения у него сегодня нет, поимки не ожидаю",
|
||
"old": "\tif consent > 0 && next.AcceptRebill > consent {",
|
||
"new": "\tif false {"
|
||
},
|
||
{
|
||
"id": "D1-vocabulary-drifts-up",
|
||
"file": "internal/pgstore/sink.go",
|
||
"pkg": "./internal/gates",
|
||
"run": "TestTheFailureReasonVocabularyIsTheSameInAllThreeOfItsCarriers",
|
||
"pin": "TestTheFailureReasonVocabularyIsTheSameInAllThreeOfItsCarriers",
|
||
"what": "валидатор принимает наше внутреннее слово как контрактную причину",
|
||
"old": "\tcase \"source_unreadable\", \"service_error\", \"interrupted\":",
|
||
"new": "\tcase \"source_unreadable\", \"service_error\", \"interrupted\", \"attempts-exhausted\":"
|
||
},
|
||
{
|
||
"id": "D2-vocabulary-drifts-down",
|
||
"file": "internal/pgstore/sink.go",
|
||
"pkg": "./internal/gates",
|
||
"run": "TestTheFailureReasonVocabularyIsTheSameInAllThreeOfItsCarriers",
|
||
"pin": "TestTheFailureReasonVocabularyIsTheSameInAllThreeOfItsCarriers",
|
||
"what": "валидатор теряет ратифицированное значение — прогон, кончившийся так, не записать",
|
||
"old": "\tcase \"source_unreadable\", \"service_error\", \"interrupted\":",
|
||
"new": "\tcase \"source_unreadable\", \"service_error\":"
|
||
},
|
||
{
|
||
"id": "D3-operators-verdict-unnamed",
|
||
"file": "internal/pgstore/sink.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAnOperatorsVerdictIsRecordedAsHisAndNotAsAFault",
|
||
"pin": "TestAnOperatorsVerdictIsRecordedAsHisAndNotAsAFault",
|
||
"what": "слово оператора пустое — его решение снова неотличимо от поломки деплоя",
|
||
"old": "const AbandonedResult = \"abandoned\"",
|
||
"new": "const AbandonedResult = \"\""
|
||
},
|
||
{
|
||
"id": "D4-operators-word-overwrites-the-machine",
|
||
"file": "internal/pgstore/runs.go",
|
||
"pkg": "./internal/runs",
|
||
"run": "TestAnOperatorsWordDoesNotOverwriteWhatTheMachineSaid",
|
||
"pin": "TestAnOperatorsWordDoesNotOverwriteWhatTheMachineSaid",
|
||
"what": "вердикт оператора затирает то, что сказала машина",
|
||
"old": "exit_result = coalesce(exit_result, $4)",
|
||
"new": "exit_result = $4"
|
||
}
|
||
]
|