Proposal to correct only the permitted billing parser so numeric Retry-After seconds are converted to milliseconds, while preserving the exported API and all non-numeric behavior, and to add bounded numeric regression coverage.
- modify
packages/billing/src/retry-after.mjsMultiply the existing numeric Retry-After result by 1000 so HTTP seconds are returned as milliseconds. Leave the function signature and HTTP-date, expired-date, blank, and invalid-value paths unchanged.
- create
test/retry-after-regression.test.mjsAdd bounded regression cases for the billing parser covering representative numeric Retry-After values and their corrected millisecond results.
test/retry-after-regression.test.mjs · Billing parseRetryAfter converts numeric HTTP Retry-After seconds to milliseconds for 1, 5, and 120 seconds.
Inspect actual sanitized typed IR
{
"schemaVersion": "change-plan.v2",
"intentDigest": "c399b9f8d862dcffc434c28f72df12b583796c8b6b20d8e41b7a50a4bc40ee1c",
"repositoryDigest": "0130de9c6f6fbe102ad11f0f2d62644ebfac42f1cbcfcfce35e60b90c79898cf",
"evidenceDigest": "910021139e3af95ef2465ba73cd4d656032aca43815984eef93dbf80362302d2",
"intentConformance": {
"schemaVersion": "intent-conformance.v1",
"policyId": "read-only-versioned-scenario.v1",
"scenarioId": "retry-after-reasoning-holdout",
"scenarioVersion": "2026.07.15.1",
"requestMode": "read_only_versioned_scenario",
"conforms": true,
"classification": "exact_scenario_intent",
"reasons": [
"Intent exactly matches retry-after-reasoning-holdout@2026.07.15.1, whose semantics and transformation variant are server-owned."
],
"digest": "abee95cb87af46aec45df1b8b9f92082e0aeb16e65ef6480e00cdd96b7134663"
},
"summary": "Proposal to correct only the permitted billing parser so numeric Retry-After seconds are converted to milliseconds, while preserving the exported API and all non-numeric behavior, and to add bounded numeric regression coverage.",
"changes": [
{
"id": "C1",
"path": "packages/billing/src/retry-after.mjs",
"symbol": "parseRetryAfter",
"description": "Multiply the existing numeric Retry-After result by 1000 so HTTP seconds are returned as milliseconds. Leave the function signature and HTTP-date, expired-date, blank, and invalid-value paths unchanged.",
"rationale": "The billing parser currently returns the parsed numeric value without unit conversion, while repository policy requires numeric HTTP seconds to be returned as milliseconds.",
"evidenceIds": [
"E-SRC-002",
"E-CON-001",
"E-CON-002",
"E-CON-003"
],
"operation": "modify",
"expectedPreimageSha256": "9eb54c75c4d15de06ab755e63cfe1c17e33c10928a7051b7097839093392d980",
"transformation": {
"kind": "numeric_multiply_return",
"targetEvidenceId": "E-SRC-002",
"expectedPreimageSha256": "9eb54c75c4d15de06ab755e63cfe1c17e33c10928a7051b7097839093392d980",
"permittedSymbol": "parseRetryAfter",
"numericExpression": "Number(normalized)",
"inputUnit": "seconds",
"outputUnit": "milliseconds",
"factor": 1000
}
},
{
"id": "C2",
"path": "test/retry-after-regression.test.mjs",
"symbol": "parseRetryAfter",
"description": "Add bounded regression cases for the billing parser covering representative numeric Retry-After values and their corrected millisecond results.",
"rationale": "These cases fail under the unconverted numeric return and pass after the seconds-to-milliseconds correction, without requiring changes to existing HTTP-date coverage.",
"evidenceIds": [
"E-SRC-002",
"E-CON-002",
"E-CON-003",
"E-CON-004"
],
"operation": "create",
"expectedPreimageSha256": null,
"transformation": {
"kind": "bounded_numeric_regression_cases",
"permittedSymbol": "parseRetryAfter",
"sourceChangeIds": [
"C1"
],
"cases": [
{
"input": "1",
"expectedMilliseconds": 1000
},
{
"input": "5",
"expectedMilliseconds": 5000
},
{
"input": "120",
"expectedMilliseconds": 120000
}
],
"expectedBaselineOutcome": "fail",
"expectedPatchedOutcome": "pass"
}
}
],
"regressionTests": [
{
"id": "T1",
"behavior": "Billing parseRetryAfter converts numeric HTTP Retry-After seconds to milliseconds for 1, 5, and 120 seconds.",
"targetPath": "test/retry-after-regression.test.mjs",
"expectedBaselineOutcome": "fail",
"expectedPatchedOutcome": "pass",
"evidenceIds": [
"E-SRC-002",
"E-CON-002",
"E-CON-004"
]
}
],
"constraintsAcknowledged": [
"Preserve the exported parseRetryAfter(value, nowMs) public API.",
"Convert numeric Retry-After values from HTTP seconds to milliseconds.",
"Do not alter HTTP-date, expired-date, blank, or invalid-value behavior.",
"Modify only packages/billing/src/retry-after.mjs and create only test/retry-after-regression.test.mjs, as constrained by the permitted boundary.",
"Do not modify manifests, dependencies, CI, infrastructure, credentials, or deployment files.",
"Verification remains limited to the fixture-owned Node test profile; no network, Git, package-manager, shell, merge, or deployment access is proposed."
],
"verificationProfileId": "fixture-node-test-v1",
"risk": {
"level": "low",
"reasons": [
"The production change is confined to the evidenced numeric return expression in one permitted module.",
"The conversion factor is directly established by the repository policy.",
"The public API and non-numeric control paths remain unchanged.",
"Regression inputs and expected values are small, deterministic, and bounded."
]
},
"confidence": 0.99,
"provenance": {
"requestedModel": "gpt-5.6",
"schemaVersion": "change-plan.v2",
"disclosure": "One protected GPT-5.6 Responses API call proposes typed IR over synthetic evidence with store:false and no tools. Deterministic policy stops at REQUIRE_HUMAN_APPROVAL; a separate non-human, fixture-only evaluation authorization permits one isolated verification.",
"adapter": "openai.responses",
"actualModel": "gpt-5.6-sol",
"liveModelCall": true,
"promptVersion": "change-factory-holdout-planner.v4",
"responseId": "resp_0a222ed277eee6b8016a57696eb0248198a400ae6952e2c256"
}
}