@invaro/opentax 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/http.js +1282 -852
- package/bundle/index.js +1267 -837
- package/bundle/main.js +1598 -1104
- package/package.json +4 -4
package/bundle/index.js
CHANGED
|
@@ -1035,10 +1035,10 @@ var require_codegen = __commonJS({
|
|
|
1035
1035
|
}
|
|
1036
1036
|
exports.not = not8;
|
|
1037
1037
|
var andCode = mappend(exports.operators.AND);
|
|
1038
|
-
function
|
|
1038
|
+
function and12(...args) {
|
|
1039
1039
|
return args.reduce(andCode);
|
|
1040
1040
|
}
|
|
1041
|
-
exports.and =
|
|
1041
|
+
exports.and = and12;
|
|
1042
1042
|
var orCode = mappend(exports.operators.OR);
|
|
1043
1043
|
function or11(...args) {
|
|
1044
1044
|
return args.reduce(orCode);
|
|
@@ -1475,12 +1475,12 @@ var require_applicability = __commonJS({
|
|
|
1475
1475
|
}
|
|
1476
1476
|
exports.schemaHasRulesForType = schemaHasRulesForType;
|
|
1477
1477
|
function shouldUseGroup(schema, group) {
|
|
1478
|
-
return group.rules.some((
|
|
1478
|
+
return group.rules.some((rule2) => shouldUseRule(schema, rule2));
|
|
1479
1479
|
}
|
|
1480
1480
|
exports.shouldUseGroup = shouldUseGroup;
|
|
1481
|
-
function shouldUseRule(schema,
|
|
1481
|
+
function shouldUseRule(schema, rule2) {
|
|
1482
1482
|
var _a3;
|
|
1483
|
-
return schema[
|
|
1483
|
+
return schema[rule2.keyword] !== void 0 || ((_a3 = rule2.definition.implements) === null || _a3 === void 0 ? void 0 : _a3.some((kwd) => schema[kwd] !== void 0));
|
|
1484
1484
|
}
|
|
1485
1485
|
exports.shouldUseRule = shouldUseRule;
|
|
1486
1486
|
}
|
|
@@ -2236,10 +2236,10 @@ var require_resolve = __commonJS({
|
|
|
2236
2236
|
}
|
|
2237
2237
|
return count;
|
|
2238
2238
|
}
|
|
2239
|
-
function getFullPath(resolver,
|
|
2239
|
+
function getFullPath(resolver, id2 = "", normalize) {
|
|
2240
2240
|
if (normalize !== false)
|
|
2241
|
-
|
|
2242
|
-
const p = resolver.parse(
|
|
2241
|
+
id2 = normalizeId(id2);
|
|
2242
|
+
const p = resolver.parse(id2);
|
|
2243
2243
|
return _getFullPath(resolver, p);
|
|
2244
2244
|
}
|
|
2245
2245
|
exports.getFullPath = getFullPath;
|
|
@@ -2249,13 +2249,13 @@ var require_resolve = __commonJS({
|
|
|
2249
2249
|
}
|
|
2250
2250
|
exports._getFullPath = _getFullPath;
|
|
2251
2251
|
var TRAILING_SLASH_HASH = /#\/?$/;
|
|
2252
|
-
function normalizeId(
|
|
2253
|
-
return
|
|
2252
|
+
function normalizeId(id2) {
|
|
2253
|
+
return id2 ? id2.replace(TRAILING_SLASH_HASH, "") : "";
|
|
2254
2254
|
}
|
|
2255
2255
|
exports.normalizeId = normalizeId;
|
|
2256
|
-
function resolveUrl(resolver, baseId,
|
|
2257
|
-
|
|
2258
|
-
return resolver.resolve(baseId,
|
|
2256
|
+
function resolveUrl(resolver, baseId, id2) {
|
|
2257
|
+
id2 = normalizeId(id2);
|
|
2258
|
+
return resolver.resolve(baseId, id2);
|
|
2259
2259
|
}
|
|
2260
2260
|
exports.resolveUrl = resolveUrl;
|
|
2261
2261
|
var ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
|
|
@@ -2532,9 +2532,9 @@ var require_validate = __commonJS({
|
|
|
2532
2532
|
if (useDefaults)
|
|
2533
2533
|
(0, defaults_1.assignDefaults)(it, group.type);
|
|
2534
2534
|
gen.block(() => {
|
|
2535
|
-
for (const
|
|
2536
|
-
if ((0, applicability_1.shouldUseRule)(schema,
|
|
2537
|
-
keywordCode(it,
|
|
2535
|
+
for (const rule2 of group.rules) {
|
|
2536
|
+
if ((0, applicability_1.shouldUseRule)(schema, rule2)) {
|
|
2537
|
+
keywordCode(it, rule2.keyword, rule2.definition, group.type);
|
|
2538
2538
|
}
|
|
2539
2539
|
}
|
|
2540
2540
|
});
|
|
@@ -2569,9 +2569,9 @@ var require_validate = __commonJS({
|
|
|
2569
2569
|
function checkKeywordTypes(it, ts) {
|
|
2570
2570
|
const rules = it.self.RULES.all;
|
|
2571
2571
|
for (const keyword in rules) {
|
|
2572
|
-
const
|
|
2573
|
-
if (typeof
|
|
2574
|
-
const { type } =
|
|
2572
|
+
const rule2 = rules[keyword];
|
|
2573
|
+
if (typeof rule2 == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule2)) {
|
|
2574
|
+
const { type } = rule2.definition;
|
|
2575
2575
|
if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
|
|
2576
2576
|
strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
|
|
2577
2577
|
}
|
|
@@ -3025,8 +3025,8 @@ var require_compile = __commonJS({
|
|
|
3025
3025
|
if (Object.keys(root.schema).length > 0 && refPath === baseId) {
|
|
3026
3026
|
return getJsonPointer.call(this, p, root);
|
|
3027
3027
|
}
|
|
3028
|
-
const
|
|
3029
|
-
const schOrRef = this.refs[
|
|
3028
|
+
const id2 = (0, resolve_1.normalizeId)(refPath);
|
|
3029
|
+
const schOrRef = this.refs[id2] || this.schemas[id2];
|
|
3030
3030
|
if (typeof schOrRef == "string") {
|
|
3031
3031
|
const sch = resolveSchema.call(this, root, schOrRef);
|
|
3032
3032
|
if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
|
|
@@ -3037,7 +3037,7 @@ var require_compile = __commonJS({
|
|
|
3037
3037
|
return;
|
|
3038
3038
|
if (!schOrRef.validate)
|
|
3039
3039
|
compileSchema.call(this, schOrRef);
|
|
3040
|
-
if (
|
|
3040
|
+
if (id2 === (0, resolve_1.normalizeId)(ref)) {
|
|
3041
3041
|
const { schema } = schOrRef;
|
|
3042
3042
|
const { schemaId } = this.opts;
|
|
3043
3043
|
const schId = schema[schemaId];
|
|
@@ -3609,10 +3609,10 @@ var require_utils = __commonJS({
|
|
|
3609
3609
|
}
|
|
3610
3610
|
return output2;
|
|
3611
3611
|
}
|
|
3612
|
-
function recomposeZonedIPv6Host(
|
|
3613
|
-
const zone =
|
|
3612
|
+
function recomposeZonedIPv6Host(component2) {
|
|
3613
|
+
const zone = component2.ipv6Zone;
|
|
3614
3614
|
if (zone === void 0) return void 0;
|
|
3615
|
-
const host =
|
|
3615
|
+
const host = component2.host;
|
|
3616
3616
|
const separator = host.indexOf("%");
|
|
3617
3617
|
if (separator === -1) return void 0;
|
|
3618
3618
|
const address = host.slice(0, separator);
|
|
@@ -3623,16 +3623,16 @@ var require_utils = __commonJS({
|
|
|
3623
3623
|
}
|
|
3624
3624
|
return void 0;
|
|
3625
3625
|
}
|
|
3626
|
-
function recomposeAuthority(
|
|
3626
|
+
function recomposeAuthority(component2, allowNonAscii = false) {
|
|
3627
3627
|
const uriTokens = [];
|
|
3628
|
-
if (
|
|
3629
|
-
uriTokens.push(encodeUserinfo(
|
|
3628
|
+
if (component2.userinfo !== void 0) {
|
|
3629
|
+
uriTokens.push(encodeUserinfo(component2.userinfo));
|
|
3630
3630
|
uriTokens.push("@");
|
|
3631
3631
|
}
|
|
3632
|
-
if (
|
|
3633
|
-
let host =
|
|
3632
|
+
if (component2.host !== void 0) {
|
|
3633
|
+
let host = component2.host;
|
|
3634
3634
|
if (!isIPv4(host)) {
|
|
3635
|
-
const zonedHost = recomposeZonedIPv6Host(
|
|
3635
|
+
const zonedHost = recomposeZonedIPv6Host(component2);
|
|
3636
3636
|
if (zonedHost !== void 0) {
|
|
3637
3637
|
host = zonedHost;
|
|
3638
3638
|
} else {
|
|
@@ -3650,8 +3650,8 @@ var require_utils = __commonJS({
|
|
|
3650
3650
|
}
|
|
3651
3651
|
uriTokens.push(host);
|
|
3652
3652
|
}
|
|
3653
|
-
if (typeof
|
|
3654
|
-
const port = String(
|
|
3653
|
+
if (typeof component2.port === "number" || typeof component2.port === "string") {
|
|
3654
|
+
const port = String(component2.port);
|
|
3655
3655
|
if (!isPort(port)) {
|
|
3656
3656
|
throw new TypeError("URI port is malformed.");
|
|
3657
3657
|
}
|
|
@@ -3720,21 +3720,21 @@ var require_schemes = __commonJS({
|
|
|
3720
3720
|
return false;
|
|
3721
3721
|
}
|
|
3722
3722
|
}
|
|
3723
|
-
function httpParse(
|
|
3724
|
-
if (!
|
|
3725
|
-
|
|
3723
|
+
function httpParse(component2) {
|
|
3724
|
+
if (!component2.host) {
|
|
3725
|
+
component2.error = component2.error || "HTTP URIs must have a host.";
|
|
3726
3726
|
}
|
|
3727
|
-
return
|
|
3727
|
+
return component2;
|
|
3728
3728
|
}
|
|
3729
|
-
function httpSerialize(
|
|
3730
|
-
const secure = String(
|
|
3731
|
-
if (
|
|
3732
|
-
|
|
3729
|
+
function httpSerialize(component2) {
|
|
3730
|
+
const secure = String(component2.scheme).toLowerCase() === "https";
|
|
3731
|
+
if (component2.port === (secure ? 443 : 80) || component2.port === "") {
|
|
3732
|
+
component2.port = void 0;
|
|
3733
3733
|
}
|
|
3734
|
-
if (!
|
|
3735
|
-
|
|
3734
|
+
if (!component2.path) {
|
|
3735
|
+
component2.path = "/";
|
|
3736
3736
|
}
|
|
3737
|
-
return
|
|
3737
|
+
return component2;
|
|
3738
3738
|
}
|
|
3739
3739
|
function wsParse(wsComponent) {
|
|
3740
3740
|
wsComponent.secure = wsIsSecure(wsComponent);
|
|
@@ -3952,7 +3952,7 @@ var require_schemes = __commonJS({
|
|
|
3952
3952
|
}
|
|
3953
3953
|
return result;
|
|
3954
3954
|
}
|
|
3955
|
-
function mailtoNormalizeDomain(domain2, options,
|
|
3955
|
+
function mailtoNormalizeDomain(domain2, options, component2) {
|
|
3956
3956
|
const normalizedDomain = String(domain2).toLowerCase();
|
|
3957
3957
|
if (MAILTO_DOMAIN_LITERAL.test(normalizedDomain)) {
|
|
3958
3958
|
return normalizedDomain;
|
|
@@ -3967,8 +3967,8 @@ var require_schemes = __commonJS({
|
|
|
3967
3967
|
}
|
|
3968
3968
|
return options && options.unicodeSupport ? normalizedDomain : parsedDomain.hostname;
|
|
3969
3969
|
} catch {
|
|
3970
|
-
if (
|
|
3971
|
-
|
|
3970
|
+
if (component2) {
|
|
3971
|
+
component2.error = component2.error || MAILTO_DOMAIN_ERROR;
|
|
3972
3972
|
}
|
|
3973
3973
|
return normalizedDomain;
|
|
3974
3974
|
}
|
|
@@ -3980,8 +3980,8 @@ var require_schemes = __commonJS({
|
|
|
3980
3980
|
}
|
|
3981
3981
|
return encodeWithAllow(domain2, set2);
|
|
3982
3982
|
}
|
|
3983
|
-
function mailtoParse(
|
|
3984
|
-
const mailtoComponent =
|
|
3983
|
+
function mailtoParse(component2, options) {
|
|
3984
|
+
const mailtoComponent = component2;
|
|
3985
3985
|
let rawPath = mailtoComponent.path;
|
|
3986
3986
|
let rawQuery = mailtoComponent.query;
|
|
3987
3987
|
if (rawPath && HAS_SURROGATE.test(rawPath)) rawPath = replaceLoneSurrogates(rawPath);
|
|
@@ -4048,8 +4048,8 @@ var require_schemes = __commonJS({
|
|
|
4048
4048
|
function mailtoEncodeHeaderName(name) {
|
|
4049
4049
|
return encodeWithAllow(name.replace(/%/gu, "%25"), HFNAME);
|
|
4050
4050
|
}
|
|
4051
|
-
function mailtoSerialize(
|
|
4052
|
-
const mailtoComponent =
|
|
4051
|
+
function mailtoSerialize(component2, options) {
|
|
4052
|
+
const mailtoComponent = component2;
|
|
4053
4053
|
const to = Array.isArray(mailtoComponent.to) ? mailtoComponent.to.slice() : [];
|
|
4054
4054
|
const sourceHeaders = mailtoComponent.headers && typeof mailtoComponent.headers === "object" ? Object.assign(/* @__PURE__ */ Object.create(null), mailtoComponent.headers) : /* @__PURE__ */ Object.create(null);
|
|
4055
4055
|
const headers = /* @__PURE__ */ Object.create(null);
|
|
@@ -4285,7 +4285,7 @@ var require_fast_uri = __commonJS({
|
|
|
4285
4285
|
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
4286
4286
|
}
|
|
4287
4287
|
function serialize2(cmpts, opts) {
|
|
4288
|
-
const
|
|
4288
|
+
const component2 = {
|
|
4289
4289
|
host: cmpts.host,
|
|
4290
4290
|
ipv6Zone: cmpts.ipv6Zone,
|
|
4291
4291
|
scheme: cmpts.scheme,
|
|
@@ -4308,38 +4308,38 @@ var require_fast_uri = __commonJS({
|
|
|
4308
4308
|
};
|
|
4309
4309
|
const options = Object.assign({}, opts);
|
|
4310
4310
|
const uriTokens = [];
|
|
4311
|
-
if (
|
|
4312
|
-
|
|
4311
|
+
if (component2.scheme) {
|
|
4312
|
+
component2.scheme = validateScheme(component2.scheme);
|
|
4313
4313
|
}
|
|
4314
|
-
const schemeHandler = getSchemeHandler(options.scheme ||
|
|
4315
|
-
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(
|
|
4316
|
-
const hasAuthority =
|
|
4317
|
-
const schemelessReference = (
|
|
4314
|
+
const schemeHandler = getSchemeHandler(options.scheme || component2.scheme);
|
|
4315
|
+
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component2, options);
|
|
4316
|
+
const hasAuthority = component2.userinfo !== void 0 || component2.host !== void 0 || component2.port !== void 0;
|
|
4317
|
+
const schemelessReference = (component2.scheme === void 0 || options.reference === "suffix") && !hasAuthority;
|
|
4318
4318
|
const pathNoScheme = !options.skipEscape && schemelessReference;
|
|
4319
|
-
if (
|
|
4319
|
+
if (component2.path !== void 0) {
|
|
4320
4320
|
if (!options.skipEscape) {
|
|
4321
|
-
|
|
4321
|
+
component2.path = serializePathEncoding(component2.path, pathNoScheme);
|
|
4322
4322
|
} else {
|
|
4323
|
-
|
|
4323
|
+
component2.path = normalizePercentEncoding(component2.path);
|
|
4324
4324
|
}
|
|
4325
4325
|
}
|
|
4326
|
-
if (options.reference !== "suffix" &&
|
|
4327
|
-
|
|
4328
|
-
uriTokens.push(
|
|
4326
|
+
if (options.reference !== "suffix" && component2.scheme) {
|
|
4327
|
+
component2.scheme = validateScheme(component2.scheme);
|
|
4328
|
+
uriTokens.push(component2.scheme, ":");
|
|
4329
4329
|
}
|
|
4330
4330
|
const allowNonAsciiHost = options.unicodeSupport === true || Boolean(schemeHandler && schemeHandler.unicodeSupport);
|
|
4331
|
-
const authority = recomposeAuthority(
|
|
4331
|
+
const authority = recomposeAuthority(component2, allowNonAsciiHost);
|
|
4332
4332
|
if (authority !== void 0) {
|
|
4333
4333
|
if (options.reference !== "suffix") {
|
|
4334
4334
|
uriTokens.push("//");
|
|
4335
4335
|
}
|
|
4336
4336
|
uriTokens.push(authority);
|
|
4337
|
-
if (
|
|
4337
|
+
if (component2.path && component2.path[0] !== "/") {
|
|
4338
4338
|
uriTokens.push("/");
|
|
4339
4339
|
}
|
|
4340
4340
|
}
|
|
4341
|
-
if (
|
|
4342
|
-
let s =
|
|
4341
|
+
if (component2.path !== void 0) {
|
|
4342
|
+
let s = component2.path;
|
|
4343
4343
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
4344
4344
|
s = schemelessReference && s[0] !== "/" ? removeDotSegmentsRelative(s) : removeDotSegments(s);
|
|
4345
4345
|
}
|
|
@@ -4351,11 +4351,11 @@ var require_fast_uri = __commonJS({
|
|
|
4351
4351
|
}
|
|
4352
4352
|
uriTokens.push(s);
|
|
4353
4353
|
}
|
|
4354
|
-
if (
|
|
4355
|
-
uriTokens.push("?", encodeQuery(
|
|
4354
|
+
if (component2.query !== void 0) {
|
|
4355
|
+
uriTokens.push("?", encodeQuery(component2.query));
|
|
4356
4356
|
}
|
|
4357
|
-
if (
|
|
4358
|
-
uriTokens.push("#", encodeFragment(
|
|
4357
|
+
if (component2.fragment !== void 0) {
|
|
4358
|
+
uriTokens.push("#", encodeFragment(component2.fragment));
|
|
4359
4359
|
}
|
|
4360
4360
|
return uriTokens.join("");
|
|
4361
4361
|
}
|
|
@@ -4371,14 +4371,14 @@ var require_fast_uri = __commonJS({
|
|
|
4371
4371
|
}
|
|
4372
4372
|
return void 0;
|
|
4373
4373
|
}
|
|
4374
|
-
function hasMalformedPercentEncoding(
|
|
4375
|
-
if (
|
|
4376
|
-
let percent =
|
|
4374
|
+
function hasMalformedPercentEncoding(component2) {
|
|
4375
|
+
if (component2 === void 0) return false;
|
|
4376
|
+
let percent = component2.indexOf("%");
|
|
4377
4377
|
while (percent !== -1) {
|
|
4378
|
-
if (percent + 2 >=
|
|
4378
|
+
if (percent + 2 >= component2.length || !/^[\da-f]{2}$/iu.test(component2.slice(percent + 1, percent + 3))) {
|
|
4379
4379
|
return true;
|
|
4380
4380
|
}
|
|
4381
|
-
percent =
|
|
4381
|
+
percent = component2.indexOf("%", percent + 3);
|
|
4382
4382
|
}
|
|
4383
4383
|
return false;
|
|
4384
4384
|
}
|
|
@@ -4854,15 +4854,15 @@ var require_core = __commonJS({
|
|
|
4854
4854
|
this.addSchema(sch, void 0, _meta, _validateSchema);
|
|
4855
4855
|
return this;
|
|
4856
4856
|
}
|
|
4857
|
-
let
|
|
4857
|
+
let id2;
|
|
4858
4858
|
if (typeof schema === "object") {
|
|
4859
4859
|
const { schemaId } = this.opts;
|
|
4860
|
-
|
|
4861
|
-
if (
|
|
4860
|
+
id2 = schema[schemaId];
|
|
4861
|
+
if (id2 !== void 0 && typeof id2 != "string") {
|
|
4862
4862
|
throw new Error(`schema ${schemaId} must be string`);
|
|
4863
4863
|
}
|
|
4864
4864
|
}
|
|
4865
|
-
key = (0, resolve_1.normalizeId)(key ||
|
|
4865
|
+
key = (0, resolve_1.normalizeId)(key || id2);
|
|
4866
4866
|
this._checkUnique(key);
|
|
4867
4867
|
this.schemas[key] = this._addSchema(schema, _meta, key, _validateSchema, true);
|
|
4868
4868
|
return this;
|
|
@@ -4941,11 +4941,11 @@ var require_core = __commonJS({
|
|
|
4941
4941
|
case "object": {
|
|
4942
4942
|
const cacheKey = schemaKeyRef;
|
|
4943
4943
|
this._cache.delete(cacheKey);
|
|
4944
|
-
let
|
|
4945
|
-
if (
|
|
4946
|
-
|
|
4947
|
-
delete this.schemas[
|
|
4948
|
-
delete this.refs[
|
|
4944
|
+
let id2 = schemaKeyRef[this.opts.schemaId];
|
|
4945
|
+
if (id2) {
|
|
4946
|
+
id2 = (0, resolve_1.normalizeId)(id2);
|
|
4947
|
+
delete this.schemas[id2];
|
|
4948
|
+
delete this.refs[id2];
|
|
4949
4949
|
}
|
|
4950
4950
|
return this;
|
|
4951
4951
|
}
|
|
@@ -4991,8 +4991,8 @@ var require_core = __commonJS({
|
|
|
4991
4991
|
return this;
|
|
4992
4992
|
}
|
|
4993
4993
|
getKeyword(keyword) {
|
|
4994
|
-
const
|
|
4995
|
-
return typeof
|
|
4994
|
+
const rule2 = this.RULES.all[keyword];
|
|
4995
|
+
return typeof rule2 == "object" ? rule2.definition : !!rule2;
|
|
4996
4996
|
}
|
|
4997
4997
|
// Remove keyword
|
|
4998
4998
|
removeKeyword(keyword) {
|
|
@@ -5000,7 +5000,7 @@ var require_core = __commonJS({
|
|
|
5000
5000
|
delete RULES.keywords[keyword];
|
|
5001
5001
|
delete RULES.all[keyword];
|
|
5002
5002
|
for (const group of RULES.rules) {
|
|
5003
|
-
const i = group.rules.findIndex((
|
|
5003
|
+
const i = group.rules.findIndex((rule2) => rule2.keyword === keyword);
|
|
5004
5004
|
if (i >= 0)
|
|
5005
5005
|
group.rules.splice(i, 1);
|
|
5006
5006
|
}
|
|
@@ -5027,10 +5027,10 @@ var require_core = __commonJS({
|
|
|
5027
5027
|
for (const seg of segments)
|
|
5028
5028
|
keywords = keywords[seg];
|
|
5029
5029
|
for (const key in rules) {
|
|
5030
|
-
const
|
|
5031
|
-
if (typeof
|
|
5030
|
+
const rule2 = rules[key];
|
|
5031
|
+
if (typeof rule2 != "object")
|
|
5032
5032
|
continue;
|
|
5033
|
-
const { $data } =
|
|
5033
|
+
const { $data } = rule2.definition;
|
|
5034
5034
|
const schema = keywords[key];
|
|
5035
5035
|
if ($data && schema)
|
|
5036
5036
|
keywords[key] = schemaOrData(schema);
|
|
@@ -5052,10 +5052,10 @@ var require_core = __commonJS({
|
|
|
5052
5052
|
}
|
|
5053
5053
|
}
|
|
5054
5054
|
_addSchema(schema, meta3, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
|
|
5055
|
-
let
|
|
5055
|
+
let id2;
|
|
5056
5056
|
const { schemaId } = this.opts;
|
|
5057
5057
|
if (typeof schema == "object") {
|
|
5058
|
-
|
|
5058
|
+
id2 = schema[schemaId];
|
|
5059
5059
|
} else {
|
|
5060
5060
|
if (this.opts.jtd)
|
|
5061
5061
|
throw new Error("schema must be object");
|
|
@@ -5065,7 +5065,7 @@ var require_core = __commonJS({
|
|
|
5065
5065
|
let sch = this._cache.get(schema);
|
|
5066
5066
|
if (sch !== void 0)
|
|
5067
5067
|
return sch;
|
|
5068
|
-
baseId = (0, resolve_1.normalizeId)(
|
|
5068
|
+
baseId = (0, resolve_1.normalizeId)(id2 || baseId);
|
|
5069
5069
|
const localRefs = resolve_1.getSchemaRefs.call(this, schema, baseId);
|
|
5070
5070
|
sch = new compile_1.SchemaEnv({ schema, schemaId, meta: meta3, baseId, localRefs });
|
|
5071
5071
|
this._cache.set(sch.schema, sch);
|
|
@@ -5078,9 +5078,9 @@ var require_core = __commonJS({
|
|
|
5078
5078
|
this.validateSchema(schema, true);
|
|
5079
5079
|
return sch;
|
|
5080
5080
|
}
|
|
5081
|
-
_checkUnique(
|
|
5082
|
-
if (this.schemas[
|
|
5083
|
-
throw new Error(`schema with key or id "${
|
|
5081
|
+
_checkUnique(id2) {
|
|
5082
|
+
if (this.schemas[id2] || this.refs[id2]) {
|
|
5083
|
+
throw new Error(`schema with key or id "${id2}" already exists`);
|
|
5084
5084
|
}
|
|
5085
5085
|
}
|
|
5086
5086
|
_compileSchemaEnv(sch) {
|
|
@@ -5194,7 +5194,7 @@ var require_core = __commonJS({
|
|
|
5194
5194
|
RULES.keywords[keyword] = true;
|
|
5195
5195
|
if (!definition)
|
|
5196
5196
|
return;
|
|
5197
|
-
const
|
|
5197
|
+
const rule2 = {
|
|
5198
5198
|
keyword,
|
|
5199
5199
|
definition: {
|
|
5200
5200
|
...definition,
|
|
@@ -5203,18 +5203,18 @@ var require_core = __commonJS({
|
|
|
5203
5203
|
}
|
|
5204
5204
|
};
|
|
5205
5205
|
if (definition.before)
|
|
5206
|
-
addBeforeRule.call(this, ruleGroup,
|
|
5206
|
+
addBeforeRule.call(this, ruleGroup, rule2, definition.before);
|
|
5207
5207
|
else
|
|
5208
|
-
ruleGroup.rules.push(
|
|
5209
|
-
RULES.all[keyword] =
|
|
5208
|
+
ruleGroup.rules.push(rule2);
|
|
5209
|
+
RULES.all[keyword] = rule2;
|
|
5210
5210
|
(_a3 = definition.implements) === null || _a3 === void 0 ? void 0 : _a3.forEach((kwd) => this.addKeyword(kwd));
|
|
5211
5211
|
}
|
|
5212
|
-
function addBeforeRule(ruleGroup,
|
|
5212
|
+
function addBeforeRule(ruleGroup, rule2, before) {
|
|
5213
5213
|
const i = ruleGroup.rules.findIndex((_rule) => _rule.keyword === before);
|
|
5214
5214
|
if (i >= 0) {
|
|
5215
|
-
ruleGroup.rules.splice(i, 0,
|
|
5215
|
+
ruleGroup.rules.splice(i, 0, rule2);
|
|
5216
5216
|
} else {
|
|
5217
|
-
ruleGroup.rules.push(
|
|
5217
|
+
ruleGroup.rules.push(rule2);
|
|
5218
5218
|
this.logger.warn(`rule ${before} is not defined`);
|
|
5219
5219
|
}
|
|
5220
5220
|
}
|
|
@@ -6052,8 +6052,8 @@ var require_contains = __commonJS({
|
|
|
6052
6052
|
var codegen_1 = require_codegen();
|
|
6053
6053
|
var util_1 = require_util();
|
|
6054
6054
|
var error62 = {
|
|
6055
|
-
message: ({ params: { min:
|
|
6056
|
-
params: ({ params: { min:
|
|
6055
|
+
message: ({ params: { min: min7, max: max2 } }) => max2 === void 0 ? (0, codegen_1.str)`must contain at least ${min7} valid item(s)` : (0, codegen_1.str)`must contain at least ${min7} and no more than ${max2} valid item(s)`,
|
|
6056
|
+
params: ({ params: { min: min7, max: max2 } }) => max2 === void 0 ? (0, codegen_1._)`{minContains: ${min7}}` : (0, codegen_1._)`{minContains: ${min7}, maxContains: ${max2}}`
|
|
6057
6057
|
};
|
|
6058
6058
|
var def = {
|
|
6059
6059
|
keyword: "contains",
|
|
@@ -6064,28 +6064,28 @@ var require_contains = __commonJS({
|
|
|
6064
6064
|
error: error62,
|
|
6065
6065
|
code(cxt) {
|
|
6066
6066
|
const { gen, schema, parentSchema, data, it } = cxt;
|
|
6067
|
-
let
|
|
6067
|
+
let min7;
|
|
6068
6068
|
let max2;
|
|
6069
6069
|
const { minContains, maxContains } = parentSchema;
|
|
6070
6070
|
if (it.opts.next) {
|
|
6071
|
-
|
|
6071
|
+
min7 = minContains === void 0 ? 1 : minContains;
|
|
6072
6072
|
max2 = maxContains;
|
|
6073
6073
|
} else {
|
|
6074
|
-
|
|
6074
|
+
min7 = 1;
|
|
6075
6075
|
}
|
|
6076
6076
|
const len = gen.const("len", (0, codegen_1._)`${data}.length`);
|
|
6077
|
-
cxt.setParams({ min:
|
|
6078
|
-
if (max2 === void 0 &&
|
|
6077
|
+
cxt.setParams({ min: min7, max: max2 });
|
|
6078
|
+
if (max2 === void 0 && min7 === 0) {
|
|
6079
6079
|
(0, util_1.checkStrictMode)(it, `"minContains" == 0 without "maxContains": "contains" keyword ignored`);
|
|
6080
6080
|
return;
|
|
6081
6081
|
}
|
|
6082
|
-
if (max2 !== void 0 &&
|
|
6082
|
+
if (max2 !== void 0 && min7 > max2) {
|
|
6083
6083
|
(0, util_1.checkStrictMode)(it, `"minContains" > "maxContains" is always invalid`);
|
|
6084
6084
|
cxt.fail();
|
|
6085
6085
|
return;
|
|
6086
6086
|
}
|
|
6087
6087
|
if ((0, util_1.alwaysValidSchema)(it, schema)) {
|
|
6088
|
-
let cond = (0, codegen_1._)`${len} >= ${
|
|
6088
|
+
let cond = (0, codegen_1._)`${len} >= ${min7}`;
|
|
6089
6089
|
if (max2 !== void 0)
|
|
6090
6090
|
cond = (0, codegen_1._)`${cond} && ${len} <= ${max2}`;
|
|
6091
6091
|
cxt.pass(cond);
|
|
@@ -6093,9 +6093,9 @@ var require_contains = __commonJS({
|
|
|
6093
6093
|
}
|
|
6094
6094
|
it.items = true;
|
|
6095
6095
|
const valid = gen.name("valid");
|
|
6096
|
-
if (max2 === void 0 &&
|
|
6096
|
+
if (max2 === void 0 && min7 === 1) {
|
|
6097
6097
|
validateItems(valid, () => gen.if(valid, () => gen.break()));
|
|
6098
|
-
} else if (
|
|
6098
|
+
} else if (min7 === 0) {
|
|
6099
6099
|
gen.let(valid, true);
|
|
6100
6100
|
if (max2 !== void 0)
|
|
6101
6101
|
gen.if((0, codegen_1._)`${data}.length > 0`, validateItemsWithCount);
|
|
@@ -6123,13 +6123,13 @@ var require_contains = __commonJS({
|
|
|
6123
6123
|
function checkLimits(count) {
|
|
6124
6124
|
gen.code((0, codegen_1._)`${count}++`);
|
|
6125
6125
|
if (max2 === void 0) {
|
|
6126
|
-
gen.if((0, codegen_1._)`${count} >= ${
|
|
6126
|
+
gen.if((0, codegen_1._)`${count} >= ${min7}`, () => gen.assign(valid, true).break());
|
|
6127
6127
|
} else {
|
|
6128
6128
|
gen.if((0, codegen_1._)`${count} > ${max2}`, () => gen.assign(valid, false).break());
|
|
6129
|
-
if (
|
|
6129
|
+
if (min7 === 1)
|
|
6130
6130
|
gen.assign(valid, true);
|
|
6131
6131
|
else
|
|
6132
|
-
gen.if((0, codegen_1._)`${count} >= ${
|
|
6132
|
+
gen.if((0, codegen_1._)`${count} >= ${min7}`, () => gen.assign(valid, true));
|
|
6133
6133
|
}
|
|
6134
6134
|
}
|
|
6135
6135
|
}
|
|
@@ -7375,7 +7375,7 @@ var require_formats = __commonJS({
|
|
|
7375
7375
|
if (!matches)
|
|
7376
7376
|
return false;
|
|
7377
7377
|
const hr = +matches[1];
|
|
7378
|
-
const
|
|
7378
|
+
const min7 = +matches[2];
|
|
7379
7379
|
const sec = +matches[3];
|
|
7380
7380
|
const tz = matches[4];
|
|
7381
7381
|
const tzSign = matches[5] === "-" ? -1 : 1;
|
|
@@ -7383,9 +7383,9 @@ var require_formats = __commonJS({
|
|
|
7383
7383
|
const tzM = +(matches[7] || 0);
|
|
7384
7384
|
if (tzH > 23 || tzM > 59 || strictTimeZone && !tz)
|
|
7385
7385
|
return false;
|
|
7386
|
-
if (hr <= 23 &&
|
|
7386
|
+
if (hr <= 23 && min7 <= 59 && sec < 60)
|
|
7387
7387
|
return true;
|
|
7388
|
-
const utcMin =
|
|
7388
|
+
const utcMin = min7 - tzM * tzSign;
|
|
7389
7389
|
const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0);
|
|
7390
7390
|
return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61;
|
|
7391
7391
|
};
|
|
@@ -9208,11 +9208,11 @@ function node(obj, key, make) {
|
|
|
9208
9208
|
function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
9209
9209
|
const fieldErrors = {};
|
|
9210
9210
|
const formErrors = [];
|
|
9211
|
-
for (const
|
|
9212
|
-
if (
|
|
9213
|
-
node(fieldErrors,
|
|
9211
|
+
for (const sub28 of error62.issues) {
|
|
9212
|
+
if (sub28.path.length > 0) {
|
|
9213
|
+
node(fieldErrors, sub28.path[0], () => []).push(mapper(sub28));
|
|
9214
9214
|
} else {
|
|
9215
|
-
formErrors.push(mapper(
|
|
9215
|
+
formErrors.push(mapper(sub28));
|
|
9216
9216
|
}
|
|
9217
9217
|
}
|
|
9218
9218
|
return { formErrors, fieldErrors };
|
|
@@ -11211,15 +11211,15 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
11211
11211
|
const syms = normalized.symbolKeys;
|
|
11212
11212
|
const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
|
|
11213
11213
|
const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
11214
|
-
const prefixStr = (
|
|
11215
|
-
let ${
|
|
11216
|
-
for (let i = 0; i < ${
|
|
11217
|
-
const iss = ${
|
|
11214
|
+
const prefixStr = (id2, k) => `
|
|
11215
|
+
let ${id2}_ab = false;
|
|
11216
|
+
for (let i = 0; i < ${id2}.issues.length; i++) {
|
|
11217
|
+
const iss = ${id2}.issues[i];
|
|
11218
11218
|
iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
|
|
11219
11219
|
payload.issues.push(iss);
|
|
11220
|
-
if (iss.continue !== true) ${
|
|
11220
|
+
if (iss.continue !== true) ${id2}_ab = true;
|
|
11221
11221
|
}
|
|
11222
|
-
if (${
|
|
11222
|
+
if (${id2}_ab && ctx && ctx.abortEarly) {
|
|
11223
11223
|
payload.value = newResult;
|
|
11224
11224
|
return payload;
|
|
11225
11225
|
}`;
|
|
@@ -11233,34 +11233,34 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
11233
11233
|
for (const key of normalized.allKeys) {
|
|
11234
11234
|
if (key === "__proto__")
|
|
11235
11235
|
continue;
|
|
11236
|
-
const
|
|
11236
|
+
const id2 = ids[key];
|
|
11237
11237
|
const k = typeof key === "symbol" ? `syms[${syms.indexOf(key)}]` : esc(key);
|
|
11238
11238
|
const isPresent = `${k} in input`;
|
|
11239
11239
|
const schema = shape[key];
|
|
11240
11240
|
const optin = schema?._zod?.optin;
|
|
11241
11241
|
const isOptionalIn = optin !== void 0;
|
|
11242
11242
|
const isOptionalOut = schema?._zod?.optout === "optional";
|
|
11243
|
-
doc.write(`const ${
|
|
11243
|
+
doc.write(`const ${id2} = ${parseStr(k)};`);
|
|
11244
11244
|
if (isOptionalIn && isOptionalOut) {
|
|
11245
|
-
const assign = optin === "optional" ? `${
|
|
11245
|
+
const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
|
|
11246
11246
|
doc.write(`
|
|
11247
|
-
const ${
|
|
11248
|
-
if (!${
|
|
11249
|
-
if (${
|
|
11247
|
+
const ${id2}_present = ${isPresent};
|
|
11248
|
+
if (!${id2}.issues.length || ${id2}_present) {
|
|
11249
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
11250
11250
|
}
|
|
11251
11251
|
|
|
11252
11252
|
if (${assign}) {
|
|
11253
|
-
newResult[${k}] = ${
|
|
11253
|
+
newResult[${k}] = ${id2}.value;
|
|
11254
11254
|
}
|
|
11255
11255
|
}
|
|
11256
11256
|
|
|
11257
11257
|
`);
|
|
11258
11258
|
} else if (!isOptionalIn) {
|
|
11259
11259
|
doc.write(`
|
|
11260
|
-
const ${
|
|
11261
|
-
if (${
|
|
11260
|
+
const ${id2}_present = ${isPresent};
|
|
11261
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
11262
11262
|
}
|
|
11263
|
-
if (!${
|
|
11263
|
+
if (!${id2}_present && !${id2}.issues.length) {
|
|
11264
11264
|
payload.issues.push({
|
|
11265
11265
|
code: "invalid_type",
|
|
11266
11266
|
expected: "nonoptional",
|
|
@@ -11273,22 +11273,22 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
11273
11273
|
}
|
|
11274
11274
|
}
|
|
11275
11275
|
|
|
11276
|
-
if (${
|
|
11277
|
-
newResult[${k}] = ${
|
|
11276
|
+
if (${id2}_present) {
|
|
11277
|
+
newResult[${k}] = ${id2}.value;
|
|
11278
11278
|
}
|
|
11279
11279
|
|
|
11280
11280
|
`);
|
|
11281
11281
|
} else {
|
|
11282
11282
|
doc.write(`
|
|
11283
|
-
if (${
|
|
11283
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
11284
11284
|
}
|
|
11285
11285
|
`);
|
|
11286
11286
|
if (optin === "defaulted") {
|
|
11287
|
-
doc.write(`newResult[${k}] = ${
|
|
11287
|
+
doc.write(`newResult[${k}] = ${id2}.value;`);
|
|
11288
11288
|
} else {
|
|
11289
11289
|
doc.write(`
|
|
11290
|
-
if (${
|
|
11291
|
-
newResult[${k}] = ${
|
|
11290
|
+
if (${id2}.value !== undefined || ${isPresent}) {
|
|
11291
|
+
newResult[${k}] = ${id2}.value;
|
|
11292
11292
|
}
|
|
11293
11293
|
`);
|
|
11294
11294
|
}
|
|
@@ -11643,11 +11643,11 @@ function handleIntersectionResults(result, left, right) {
|
|
|
11643
11643
|
}
|
|
11644
11644
|
const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);
|
|
11645
11645
|
if (bothKeys.length) {
|
|
11646
|
-
const
|
|
11647
|
-
if (
|
|
11648
|
-
result.issues.push({ ...unrecIssue, keys:
|
|
11646
|
+
const aggregated2 = unrecIssue ? bothKeys.filter((k) => unrecIssue.keys.includes(k)) : [];
|
|
11647
|
+
if (aggregated2.length)
|
|
11648
|
+
result.issues.push({ ...unrecIssue, keys: aggregated2 });
|
|
11649
11649
|
for (const k of bothKeys) {
|
|
11650
|
-
if (!
|
|
11650
|
+
if (!aggregated2.includes(k) && keyIssues.has(k))
|
|
11651
11651
|
result.issues.push(keyIssues.get(k));
|
|
11652
11652
|
}
|
|
11653
11653
|
}
|
|
@@ -20750,9 +20750,9 @@ function generateChecks(doc, ctx, schema, accessor) {
|
|
|
20750
20750
|
generateNumberFormatCheck(doc, def, currentAccessor);
|
|
20751
20751
|
break;
|
|
20752
20752
|
case "min_length": {
|
|
20753
|
-
const
|
|
20754
|
-
const len = codePointLengthVar(doc, ctx, currentAccessor, `${currentAccessor}.length >= ${
|
|
20755
|
-
doc.write(`if (${len} < ${
|
|
20753
|
+
const min7 = numericOperand(def.minimum, "min_length");
|
|
20754
|
+
const len = codePointLengthVar(doc, ctx, currentAccessor, `${currentAccessor}.length >= ${min7} && ${currentAccessor}.length < ${def.minimum * 2}`);
|
|
20755
|
+
doc.write(`if (${len} < ${min7}) return INVALID;`);
|
|
20756
20756
|
break;
|
|
20757
20757
|
}
|
|
20758
20758
|
case "max_length": {
|
|
@@ -23316,26 +23316,26 @@ function extractDefs(ctx, schema) {
|
|
|
23316
23316
|
return;
|
|
23317
23317
|
const idToSchema = /* @__PURE__ */ new Map();
|
|
23318
23318
|
for (const entry of ctx.seen.entries()) {
|
|
23319
|
-
const
|
|
23320
|
-
if (
|
|
23321
|
-
const existing = idToSchema.get(
|
|
23319
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
23320
|
+
if (id2) {
|
|
23321
|
+
const existing = idToSchema.get(id2);
|
|
23322
23322
|
if (existing && existing !== entry[0]) {
|
|
23323
|
-
throw new Error(`Duplicate schema id "${
|
|
23323
|
+
throw new Error(`Duplicate schema id "${id2}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
|
23324
23324
|
}
|
|
23325
|
-
idToSchema.set(
|
|
23325
|
+
idToSchema.set(id2, entry[0]);
|
|
23326
23326
|
}
|
|
23327
23327
|
}
|
|
23328
23328
|
const makeURI = (entry) => {
|
|
23329
23329
|
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
23330
23330
|
if (ctx.external) {
|
|
23331
23331
|
const externalId = ctx.external.registry.get(entry[0])?.id;
|
|
23332
|
-
const uriGenerator = ctx.external.uri ?? ((
|
|
23332
|
+
const uriGenerator = ctx.external.uri ?? ((id3) => id3);
|
|
23333
23333
|
if (externalId) {
|
|
23334
23334
|
return { ref: uriGenerator(externalId) };
|
|
23335
23335
|
}
|
|
23336
|
-
const
|
|
23337
|
-
entry[1].defId =
|
|
23338
|
-
return { defId:
|
|
23336
|
+
const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
|
23337
|
+
entry[1].defId = id2;
|
|
23338
|
+
return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id2)}` };
|
|
23339
23339
|
}
|
|
23340
23340
|
const uriPrefix = `#`;
|
|
23341
23341
|
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
@@ -23383,8 +23383,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
23383
23383
|
continue;
|
|
23384
23384
|
}
|
|
23385
23385
|
}
|
|
23386
|
-
const
|
|
23387
|
-
if (
|
|
23386
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
23387
|
+
if (id2) {
|
|
23388
23388
|
extractToDef(entry);
|
|
23389
23389
|
continue;
|
|
23390
23390
|
}
|
|
@@ -23617,10 +23617,10 @@ function finalize(ctx, schema) {
|
|
|
23617
23617
|
} else {
|
|
23618
23618
|
}
|
|
23619
23619
|
if (ctx.external?.uri) {
|
|
23620
|
-
const
|
|
23621
|
-
if (!
|
|
23620
|
+
const id2 = ctx.external.registry.get(schema)?.id;
|
|
23621
|
+
if (!id2)
|
|
23622
23622
|
throw new Error("Schema is missing an `id` property");
|
|
23623
|
-
result.$id = ctx.external.uri(
|
|
23623
|
+
result.$id = ctx.external.uri(id2);
|
|
23624
23624
|
}
|
|
23625
23625
|
assignProps(result, root.defId ? root.schema : root.def ?? root.schema);
|
|
23626
23626
|
const rootMetaId = ctx.metadataRegistry.get(schema)?.id;
|
|
@@ -24226,7 +24226,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
|
|
|
24226
24226
|
const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
|
|
24227
24227
|
if (!numericType && !values?.some((v) => typeof v === "number"))
|
|
24228
24228
|
return json2;
|
|
24229
|
-
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json2;
|
|
24229
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id: id2, ...rest } = json2;
|
|
24230
24230
|
if (rest.enum)
|
|
24231
24231
|
rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
|
|
24232
24232
|
else if (typeof rest.const === "number")
|
|
@@ -26587,12 +26587,12 @@ function containsRef(value) {
|
|
|
26587
26587
|
return value.some(containsRef);
|
|
26588
26588
|
if (typeof value.$ref === "string")
|
|
26589
26589
|
return true;
|
|
26590
|
-
return Object.entries(value).some(([key,
|
|
26590
|
+
return Object.entries(value).some(([key, sub28]) => {
|
|
26591
26591
|
if (SCHEMA_KEYWORDS.has(key))
|
|
26592
|
-
return containsRef(
|
|
26593
|
-
if (!SCHEMA_MAP_KEYWORDS.has(key) || typeof
|
|
26592
|
+
return containsRef(sub28);
|
|
26593
|
+
if (!SCHEMA_MAP_KEYWORDS.has(key) || typeof sub28 !== "object" || sub28 === null)
|
|
26594
26594
|
return false;
|
|
26595
|
-
return Object.values(
|
|
26595
|
+
return Object.values(sub28).some(containsRef);
|
|
26596
26596
|
});
|
|
26597
26597
|
}
|
|
26598
26598
|
function plural(n) {
|
|
@@ -28951,7 +28951,7 @@ import { homedir } from "node:os";
|
|
|
28951
28951
|
import { join } from "node:path";
|
|
28952
28952
|
|
|
28953
28953
|
// dist/version.js
|
|
28954
|
-
var COMPOSER_VERSION = "0.
|
|
28954
|
+
var COMPOSER_VERSION = "0.9.1";
|
|
28955
28955
|
|
|
28956
28956
|
// dist/phone-home.js
|
|
28957
28957
|
var ENDPOINT = "https://opentax.invaro.ai/api/t";
|
|
@@ -29161,8 +29161,8 @@ var ZodError2 = class _ZodError extends Error {
|
|
|
29161
29161
|
constructor(issues) {
|
|
29162
29162
|
super();
|
|
29163
29163
|
this.issues = [];
|
|
29164
|
-
this.addIssue = (
|
|
29165
|
-
this.issues = [...this.issues,
|
|
29164
|
+
this.addIssue = (sub28) => {
|
|
29165
|
+
this.issues = [...this.issues, sub28];
|
|
29166
29166
|
};
|
|
29167
29167
|
this.addIssues = (subs = []) => {
|
|
29168
29168
|
this.issues = [...this.issues, ...subs];
|
|
@@ -29244,13 +29244,13 @@ var ZodError2 = class _ZodError extends Error {
|
|
|
29244
29244
|
flatten(mapper = (issue2) => issue2.message) {
|
|
29245
29245
|
const fieldErrors = /* @__PURE__ */ Object.create(null);
|
|
29246
29246
|
const formErrors = [];
|
|
29247
|
-
for (const
|
|
29248
|
-
if (
|
|
29249
|
-
const firstEl =
|
|
29247
|
+
for (const sub28 of this.issues) {
|
|
29248
|
+
if (sub28.path.length > 0) {
|
|
29249
|
+
const firstEl = sub28.path[0];
|
|
29250
29250
|
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
|
|
29251
|
-
fieldErrors[firstEl].push(mapper(
|
|
29251
|
+
fieldErrors[firstEl].push(mapper(sub28));
|
|
29252
29252
|
} else {
|
|
29253
|
-
formErrors.push(mapper(
|
|
29253
|
+
formErrors.push(mapper(sub28));
|
|
29254
29254
|
}
|
|
29255
29255
|
}
|
|
29256
29256
|
return { formErrors, fieldErrors };
|
|
@@ -30432,14 +30432,14 @@ var ZodString2 = class _ZodString2 extends ZodType2 {
|
|
|
30432
30432
|
return !!this._def.checks.find((ch) => ch.kind === "base64url");
|
|
30433
30433
|
}
|
|
30434
30434
|
get minLength() {
|
|
30435
|
-
let
|
|
30435
|
+
let min7 = null;
|
|
30436
30436
|
for (const ch of this._def.checks) {
|
|
30437
30437
|
if (ch.kind === "min") {
|
|
30438
|
-
if (
|
|
30439
|
-
|
|
30438
|
+
if (min7 === null || ch.value > min7)
|
|
30439
|
+
min7 = ch.value;
|
|
30440
30440
|
}
|
|
30441
30441
|
}
|
|
30442
|
-
return
|
|
30442
|
+
return min7;
|
|
30443
30443
|
}
|
|
30444
30444
|
get maxLength() {
|
|
30445
30445
|
let max2 = null;
|
|
@@ -30653,14 +30653,14 @@ var ZodNumber2 = class _ZodNumber extends ZodType2 {
|
|
|
30653
30653
|
});
|
|
30654
30654
|
}
|
|
30655
30655
|
get minValue() {
|
|
30656
|
-
let
|
|
30656
|
+
let min7 = null;
|
|
30657
30657
|
for (const ch of this._def.checks) {
|
|
30658
30658
|
if (ch.kind === "min") {
|
|
30659
|
-
if (
|
|
30660
|
-
|
|
30659
|
+
if (min7 === null || ch.value > min7)
|
|
30660
|
+
min7 = ch.value;
|
|
30661
30661
|
}
|
|
30662
30662
|
}
|
|
30663
|
-
return
|
|
30663
|
+
return min7;
|
|
30664
30664
|
}
|
|
30665
30665
|
get maxValue() {
|
|
30666
30666
|
let max2 = null;
|
|
@@ -30677,19 +30677,19 @@ var ZodNumber2 = class _ZodNumber extends ZodType2 {
|
|
|
30677
30677
|
}
|
|
30678
30678
|
get isFinite() {
|
|
30679
30679
|
let max2 = null;
|
|
30680
|
-
let
|
|
30680
|
+
let min7 = null;
|
|
30681
30681
|
for (const ch of this._def.checks) {
|
|
30682
30682
|
if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") {
|
|
30683
30683
|
return true;
|
|
30684
30684
|
} else if (ch.kind === "min") {
|
|
30685
|
-
if (
|
|
30686
|
-
|
|
30685
|
+
if (min7 === null || ch.value > min7)
|
|
30686
|
+
min7 = ch.value;
|
|
30687
30687
|
} else if (ch.kind === "max") {
|
|
30688
30688
|
if (max2 === null || ch.value < max2)
|
|
30689
30689
|
max2 = ch.value;
|
|
30690
30690
|
}
|
|
30691
30691
|
}
|
|
30692
|
-
return Number.isFinite(
|
|
30692
|
+
return Number.isFinite(min7) && Number.isFinite(max2);
|
|
30693
30693
|
}
|
|
30694
30694
|
};
|
|
30695
30695
|
ZodNumber2.create = (params) => {
|
|
@@ -30844,14 +30844,14 @@ var ZodBigInt2 = class _ZodBigInt extends ZodType2 {
|
|
|
30844
30844
|
});
|
|
30845
30845
|
}
|
|
30846
30846
|
get minValue() {
|
|
30847
|
-
let
|
|
30847
|
+
let min7 = null;
|
|
30848
30848
|
for (const ch of this._def.checks) {
|
|
30849
30849
|
if (ch.kind === "min") {
|
|
30850
|
-
if (
|
|
30851
|
-
|
|
30850
|
+
if (min7 === null || ch.value > min7)
|
|
30851
|
+
min7 = ch.value;
|
|
30852
30852
|
}
|
|
30853
30853
|
}
|
|
30854
|
-
return
|
|
30854
|
+
return min7;
|
|
30855
30855
|
}
|
|
30856
30856
|
get maxValue() {
|
|
30857
30857
|
let max2 = null;
|
|
@@ -30978,14 +30978,14 @@ var ZodDate2 = class _ZodDate extends ZodType2 {
|
|
|
30978
30978
|
});
|
|
30979
30979
|
}
|
|
30980
30980
|
get minDate() {
|
|
30981
|
-
let
|
|
30981
|
+
let min7 = null;
|
|
30982
30982
|
for (const ch of this._def.checks) {
|
|
30983
30983
|
if (ch.kind === "min") {
|
|
30984
|
-
if (
|
|
30985
|
-
|
|
30984
|
+
if (min7 === null || ch.value > min7)
|
|
30985
|
+
min7 = ch.value;
|
|
30986
30986
|
}
|
|
30987
30987
|
}
|
|
30988
|
-
return
|
|
30988
|
+
return min7 != null ? new Date(min7) : null;
|
|
30989
30989
|
}
|
|
30990
30990
|
get maxDate() {
|
|
30991
30991
|
let max2 = null;
|
|
@@ -35586,7 +35586,7 @@ var ExperimentalServerTasks = class {
|
|
|
35586
35586
|
if (hasPreviousToolUse) {
|
|
35587
35587
|
const toolUseIds = new Set(previousContent.filter((c2) => c2.type === "tool_use").map((c2) => c2.id));
|
|
35588
35588
|
const toolResultIds = new Set(lastContent.filter((c2) => c2.type === "tool_result").map((c2) => c2.toolUseId));
|
|
35589
|
-
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((
|
|
35589
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id2) => toolResultIds.has(id2))) {
|
|
35590
35590
|
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
35591
35591
|
}
|
|
35592
35592
|
}
|
|
@@ -36011,7 +36011,7 @@ var Server = class extends Protocol {
|
|
|
36011
36011
|
if (hasPreviousToolUse) {
|
|
36012
36012
|
const toolUseIds = new Set(previousContent.filter((c2) => c2.type === "tool_use").map((c2) => c2.id));
|
|
36013
36013
|
const toolResultIds = new Set(lastContent.filter((c2) => c2.type === "tool_result").map((c2) => c2.toolUseId));
|
|
36014
|
-
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((
|
|
36014
|
+
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every((id2) => toolResultIds.has(id2))) {
|
|
36015
36015
|
throw new Error("ids of tool_result blocks and tool_use blocks from previous message do not match");
|
|
36016
36016
|
}
|
|
36017
36017
|
}
|
|
@@ -37273,23 +37273,23 @@ function divRound(n, d3, mode) {
|
|
|
37273
37273
|
const r = n % d3;
|
|
37274
37274
|
if (r === 0n)
|
|
37275
37275
|
return q;
|
|
37276
|
-
const
|
|
37276
|
+
const neg3 = n < 0n;
|
|
37277
37277
|
const twiceAbsRem = (r < 0n ? -r : r) * 2n;
|
|
37278
37278
|
switch (mode) {
|
|
37279
37279
|
case "floor":
|
|
37280
|
-
return
|
|
37280
|
+
return neg3 ? q - 1n : q;
|
|
37281
37281
|
case "ceil":
|
|
37282
|
-
return
|
|
37282
|
+
return neg3 ? q : q + 1n;
|
|
37283
37283
|
case "half-up":
|
|
37284
37284
|
if (twiceAbsRem >= d3)
|
|
37285
|
-
return
|
|
37285
|
+
return neg3 ? q - 1n : q + 1n;
|
|
37286
37286
|
return q;
|
|
37287
37287
|
case "half-even":
|
|
37288
37288
|
if (twiceAbsRem > d3)
|
|
37289
|
-
return
|
|
37289
|
+
return neg3 ? q - 1n : q + 1n;
|
|
37290
37290
|
if (twiceAbsRem < d3)
|
|
37291
37291
|
return q;
|
|
37292
|
-
return q % 2n === 0n ? q :
|
|
37292
|
+
return q % 2n === 0n ? q : neg3 ? q - 1n : q + 1n;
|
|
37293
37293
|
}
|
|
37294
37294
|
}
|
|
37295
37295
|
function mulRate(cents, rate2, mode) {
|
|
@@ -37516,8 +37516,8 @@ function sha256Hex(input2) {
|
|
|
37516
37516
|
function hashOf(value) {
|
|
37517
37517
|
return `sha256:${sha256Hex(canonical(value))}`;
|
|
37518
37518
|
}
|
|
37519
|
-
function ruleHash(
|
|
37520
|
-
return hashOf(
|
|
37519
|
+
function ruleHash(rule2) {
|
|
37520
|
+
return hashOf(rule2);
|
|
37521
37521
|
}
|
|
37522
37522
|
function merkleRoot(rules, facts2 = []) {
|
|
37523
37523
|
const ordered = [...rules].sort((a, b) => a.id.localeCompare(b.id) || a.version - b.version);
|
|
@@ -37649,60 +37649,60 @@ function loadCorpus(input2) {
|
|
|
37649
37649
|
const factById2 = /* @__PURE__ */ new Map();
|
|
37650
37650
|
const overriders = /* @__PURE__ */ new Map();
|
|
37651
37651
|
const contributors2 = /* @__PURE__ */ new Map();
|
|
37652
|
-
for (const
|
|
37653
|
-
if (factById2.has(
|
|
37654
|
-
issues.push(`duplicate fact id "${
|
|
37655
|
-
factById2.set(
|
|
37656
|
-
if (
|
|
37657
|
-
issues.push(`enum fact "${
|
|
37652
|
+
for (const fact47 of input2.facts) {
|
|
37653
|
+
if (factById2.has(fact47.id))
|
|
37654
|
+
issues.push(`duplicate fact id "${fact47.id}"`);
|
|
37655
|
+
factById2.set(fact47.id, fact47);
|
|
37656
|
+
if (fact47.type === "enum" && !fact47.enumValues?.length) {
|
|
37657
|
+
issues.push(`enum fact "${fact47.id}" must declare enumValues`);
|
|
37658
37658
|
}
|
|
37659
37659
|
}
|
|
37660
37660
|
const knownRuleIds = byIdRefChecker(input2);
|
|
37661
37661
|
const contributorIds = new Set(input2.rules.filter((r) => r.contributesTo !== void 0).map((r) => r.id));
|
|
37662
37662
|
const seenVersions = /* @__PURE__ */ new Set();
|
|
37663
|
-
for (const
|
|
37664
|
-
const key = `${
|
|
37663
|
+
for (const rule2 of input2.rules) {
|
|
37664
|
+
const key = `${rule2.id}@${rule2.version}`;
|
|
37665
37665
|
if (seenVersions.has(key))
|
|
37666
37666
|
issues.push(`duplicate rule version "${key}"`);
|
|
37667
37667
|
seenVersions.add(key);
|
|
37668
|
-
if (!ISO_DATE.test(
|
|
37669
|
-
issues.push(`rule "${key}": invalid effectiveFrom "${
|
|
37668
|
+
if (!ISO_DATE.test(rule2.effectiveFrom)) {
|
|
37669
|
+
issues.push(`rule "${key}": invalid effectiveFrom "${rule2.effectiveFrom}"`);
|
|
37670
37670
|
}
|
|
37671
|
-
if (
|
|
37672
|
-
if (!ISO_DATE.test(
|
|
37673
|
-
issues.push(`rule "${key}": invalid effectiveTo "${
|
|
37674
|
-
} else if (
|
|
37671
|
+
if (rule2.effectiveTo !== void 0) {
|
|
37672
|
+
if (!ISO_DATE.test(rule2.effectiveTo)) {
|
|
37673
|
+
issues.push(`rule "${key}": invalid effectiveTo "${rule2.effectiveTo}"`);
|
|
37674
|
+
} else if (rule2.effectiveTo <= rule2.effectiveFrom) {
|
|
37675
37675
|
issues.push(`rule "${key}": empty validity window`);
|
|
37676
37676
|
}
|
|
37677
37677
|
}
|
|
37678
|
-
const list = byId.get(
|
|
37679
|
-
list.push(
|
|
37680
|
-
byId.set(
|
|
37681
|
-
if (
|
|
37682
|
-
const list2 = overriders.get(
|
|
37683
|
-
list2.push(
|
|
37684
|
-
overriders.set(
|
|
37685
|
-
if (
|
|
37678
|
+
const list = byId.get(rule2.id) ?? [];
|
|
37679
|
+
list.push(rule2);
|
|
37680
|
+
byId.set(rule2.id, list);
|
|
37681
|
+
if (rule2.overrides) {
|
|
37682
|
+
const list2 = overriders.get(rule2.overrides.ruleId) ?? [];
|
|
37683
|
+
list2.push(rule2);
|
|
37684
|
+
overriders.set(rule2.overrides.ruleId, list2);
|
|
37685
|
+
if (rule2.overrides.priority <= 0) {
|
|
37686
37686
|
issues.push(`rule "${key}": override priority must be > 0 (base rule has implicit priority 0)`);
|
|
37687
37687
|
}
|
|
37688
|
-
if (!
|
|
37688
|
+
if (!rule2.applicability) {
|
|
37689
37689
|
issues.push(`rule "${key}": an override must declare an applicability guard`);
|
|
37690
37690
|
}
|
|
37691
37691
|
}
|
|
37692
|
-
if (
|
|
37693
|
-
const list2 = contributors2.get(
|
|
37694
|
-
list2.push(
|
|
37695
|
-
contributors2.set(
|
|
37696
|
-
if (
|
|
37692
|
+
if (rule2.contributesTo !== void 0) {
|
|
37693
|
+
const list2 = contributors2.get(rule2.contributesTo) ?? [];
|
|
37694
|
+
list2.push(rule2);
|
|
37695
|
+
contributors2.set(rule2.contributesTo, list2);
|
|
37696
|
+
if (rule2.output.type !== "money")
|
|
37697
37697
|
issues.push(`rule "${key}": a contribution must output money`);
|
|
37698
|
-
if (
|
|
37698
|
+
if (rule2.applicability)
|
|
37699
37699
|
issues.push(`rule "${key}": a contribution cannot declare an applicability guard`);
|
|
37700
|
-
if (
|
|
37700
|
+
if (rule2.overrides)
|
|
37701
37701
|
issues.push(`rule "${key}": a rule cannot both override and contribute`);
|
|
37702
|
-
if (
|
|
37702
|
+
if (rule2.contributesTo === rule2.id)
|
|
37703
37703
|
issues.push(`rule "${key}" contributes to itself`);
|
|
37704
37704
|
}
|
|
37705
|
-
validateExpressions(
|
|
37705
|
+
validateExpressions(rule2, knownRuleIds, contributorIds, factById2, issues);
|
|
37706
37706
|
}
|
|
37707
37707
|
for (const [targetId] of contributors2) {
|
|
37708
37708
|
const targets = byId.get(targetId);
|
|
@@ -37711,13 +37711,13 @@ function loadCorpus(input2) {
|
|
|
37711
37711
|
else if (targets[0].output.type !== "money")
|
|
37712
37712
|
issues.push(`contribution target "${targetId}" is not a money rule`);
|
|
37713
37713
|
}
|
|
37714
|
-
for (const [
|
|
37714
|
+
for (const [id2, versions2] of byId) {
|
|
37715
37715
|
const sorted = [...versions2].sort((a, b) => a.effectiveFrom.localeCompare(b.effectiveFrom));
|
|
37716
37716
|
for (let i = 0; i + 1 < sorted.length; i++) {
|
|
37717
37717
|
const cur = sorted[i];
|
|
37718
37718
|
const next = sorted[i + 1];
|
|
37719
37719
|
if (cur.effectiveTo === void 0 || next.effectiveFrom < cur.effectiveTo) {
|
|
37720
|
-
issues.push(`rule "${
|
|
37720
|
+
issues.push(`rule "${id2}": overlapping validity windows (v${cur.version} and v${next.version})`);
|
|
37721
37721
|
}
|
|
37722
37722
|
}
|
|
37723
37723
|
}
|
|
@@ -37729,23 +37729,23 @@ function loadCorpus(input2) {
|
|
|
37729
37729
|
}
|
|
37730
37730
|
const targetType = targets[0].output.type;
|
|
37731
37731
|
const prios = /* @__PURE__ */ new Map();
|
|
37732
|
-
for (const
|
|
37733
|
-
if (
|
|
37734
|
-
issues.push(`rule "${
|
|
37732
|
+
for (const rule2 of list) {
|
|
37733
|
+
if (rule2.output.type !== targetType) {
|
|
37734
|
+
issues.push(`rule "${rule2.id}" overrides "${targetId}" but output type ${rule2.output.type} != ${targetType}`);
|
|
37735
37735
|
}
|
|
37736
|
-
const p =
|
|
37736
|
+
const p = rule2.overrides.priority;
|
|
37737
37737
|
const existing = prios.get(p);
|
|
37738
|
-
if (existing !== void 0 && existing !==
|
|
37739
|
-
issues.push(`rules "${existing}" and "${
|
|
37738
|
+
if (existing !== void 0 && existing !== rule2.id) {
|
|
37739
|
+
issues.push(`rules "${existing}" and "${rule2.id}" both override "${targetId}" at priority ${p}`);
|
|
37740
37740
|
}
|
|
37741
|
-
prios.set(p,
|
|
37741
|
+
prios.set(p, rule2.id);
|
|
37742
37742
|
}
|
|
37743
37743
|
}
|
|
37744
37744
|
if (issues.length > 0)
|
|
37745
37745
|
throw new CorpusValidationError(issues);
|
|
37746
37746
|
const ruleHashes = /* @__PURE__ */ new Map();
|
|
37747
|
-
for (const
|
|
37748
|
-
ruleHashes.set(`${
|
|
37747
|
+
for (const rule2 of input2.rules) {
|
|
37748
|
+
ruleHashes.set(`${rule2.id}@${rule2.version}`, ruleHash(rule2));
|
|
37749
37749
|
}
|
|
37750
37750
|
return {
|
|
37751
37751
|
name: input2.name,
|
|
@@ -37763,11 +37763,11 @@ function loadCorpus(input2) {
|
|
|
37763
37763
|
function byIdRefChecker(input2) {
|
|
37764
37764
|
return new Set(input2.rules.map((r) => r.id));
|
|
37765
37765
|
}
|
|
37766
|
-
function validateExpressions(
|
|
37767
|
-
const key = `${
|
|
37768
|
-
const exprs = [
|
|
37769
|
-
if (
|
|
37770
|
-
exprs.push(
|
|
37766
|
+
function validateExpressions(rule2, knownRuleIds, contributorIds, factById2, issues) {
|
|
37767
|
+
const key = `${rule2.id}@${rule2.version}`;
|
|
37768
|
+
const exprs = [rule2.formula];
|
|
37769
|
+
if (rule2.applicability)
|
|
37770
|
+
exprs.push(rule2.applicability);
|
|
37771
37771
|
for (const root of exprs) {
|
|
37772
37772
|
walkExpr(root, (e) => {
|
|
37773
37773
|
switch (e.kind) {
|
|
@@ -37784,9 +37784,9 @@ function validateExpressions(rule, knownRuleIds, contributorIds, factById2, issu
|
|
|
37784
37784
|
if (!knownRuleIds.has(e.ruleId)) {
|
|
37785
37785
|
issues.push(`rule "${key}" references unknown rule "${e.ruleId}"`);
|
|
37786
37786
|
}
|
|
37787
|
-
for (const
|
|
37788
|
-
if (!contributorIds.has(
|
|
37789
|
-
issues.push(`rule "${key}" excludes "${
|
|
37787
|
+
for (const id2 of e.excluding ?? []) {
|
|
37788
|
+
if (!contributorIds.has(id2)) {
|
|
37789
|
+
issues.push(`rule "${key}" excludes "${id2}", which is not a contributing rule`);
|
|
37790
37790
|
}
|
|
37791
37791
|
}
|
|
37792
37792
|
break;
|
|
@@ -37796,7 +37796,7 @@ function validateExpressions(rule, knownRuleIds, contributorIds, factById2, issu
|
|
|
37796
37796
|
}
|
|
37797
37797
|
break;
|
|
37798
37798
|
case "param":
|
|
37799
|
-
if (!
|
|
37799
|
+
if (!rule2.parameters || !(e.name in rule2.parameters)) {
|
|
37800
37800
|
issues.push(`rule "${key}" references unknown parameter "${e.name}"`);
|
|
37801
37801
|
}
|
|
37802
37802
|
break;
|
|
@@ -38005,17 +38005,17 @@ function evalRule(ruleId, ctx) {
|
|
|
38005
38005
|
}
|
|
38006
38006
|
const contributions = [];
|
|
38007
38007
|
let contributed = 0n;
|
|
38008
|
-
for (const
|
|
38009
|
-
if (ctx.excluded.has(
|
|
38008
|
+
for (const id2 of selectContributors(ctx.corpus, ruleId, ctx.asOf)) {
|
|
38009
|
+
if (ctx.excluded.has(id2))
|
|
38010
38010
|
continue;
|
|
38011
|
-
const c2 = evalRule(
|
|
38011
|
+
const c2 = evalRule(id2, ctx);
|
|
38012
38012
|
if (c2.value === POISON || c2.node === null) {
|
|
38013
38013
|
poisoned = true;
|
|
38014
38014
|
continue;
|
|
38015
38015
|
}
|
|
38016
38016
|
if (!children.includes(c2.node))
|
|
38017
38017
|
children.push(c2.node);
|
|
38018
|
-
contributions.push({ ruleId:
|
|
38018
|
+
contributions.push({ ruleId: id2, value: valueToJSON(c2.value) });
|
|
38019
38019
|
contributed += c2.value.cents;
|
|
38020
38020
|
}
|
|
38021
38021
|
if (poisoned)
|
|
@@ -38074,15 +38074,15 @@ function passExcluding(ctx, ids) {
|
|
|
38074
38074
|
}
|
|
38075
38075
|
return pass;
|
|
38076
38076
|
}
|
|
38077
|
-
function candidateEntry(
|
|
38077
|
+
function candidateEntry(rule2, applicable) {
|
|
38078
38078
|
return {
|
|
38079
|
-
ruleId:
|
|
38080
|
-
version:
|
|
38081
|
-
priority:
|
|
38079
|
+
ruleId: rule2.id,
|
|
38080
|
+
version: rule2.version,
|
|
38081
|
+
priority: rule2.overrides?.priority ?? 0,
|
|
38082
38082
|
applicable
|
|
38083
38083
|
};
|
|
38084
38084
|
}
|
|
38085
|
-
function evalExpr(expr,
|
|
38085
|
+
function evalExpr(expr, rule2, ctx, children) {
|
|
38086
38086
|
switch (expr.kind) {
|
|
38087
38087
|
case "money":
|
|
38088
38088
|
return { type: "money", cents: parseCents(expr.cents) };
|
|
@@ -38102,29 +38102,29 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38102
38102
|
return value;
|
|
38103
38103
|
}
|
|
38104
38104
|
case "param": {
|
|
38105
|
-
const param28 =
|
|
38105
|
+
const param28 = rule2.parameters?.[expr.name];
|
|
38106
38106
|
if (!param28) {
|
|
38107
|
-
throw new EngineError(`rule "${
|
|
38107
|
+
throw new EngineError(`rule "${rule2.id}" has no parameter "${expr.name}"`);
|
|
38108
38108
|
}
|
|
38109
38109
|
return valueFromJSON({ type: param28.type, value: param28.value });
|
|
38110
38110
|
}
|
|
38111
38111
|
case "add": {
|
|
38112
|
-
const vals = evalAll(expr.args,
|
|
38112
|
+
const vals = evalAll(expr.args, rule2, ctx, children);
|
|
38113
38113
|
if (vals === POISON)
|
|
38114
38114
|
return POISON;
|
|
38115
|
-
return numericFold(vals,
|
|
38115
|
+
return numericFold(vals, rule2, "add", (acc, v) => acc + v);
|
|
38116
38116
|
}
|
|
38117
38117
|
case "sub": {
|
|
38118
|
-
const vals = evalAll([expr.left, expr.right],
|
|
38118
|
+
const vals = evalAll([expr.left, expr.right], rule2, ctx, children);
|
|
38119
38119
|
if (vals === POISON)
|
|
38120
38120
|
return POISON;
|
|
38121
|
-
return numericFold(vals,
|
|
38121
|
+
return numericFold(vals, rule2, "sub", (acc, v) => acc - v);
|
|
38122
38122
|
}
|
|
38123
38123
|
case "mulRate": {
|
|
38124
|
-
const base = evalExpr(expr.base,
|
|
38124
|
+
const base = evalExpr(expr.base, rule2, ctx, children);
|
|
38125
38125
|
if (base === POISON)
|
|
38126
38126
|
return POISON;
|
|
38127
|
-
expectType(base, "money",
|
|
38127
|
+
expectType(base, "money", rule2, "mulRate.base");
|
|
38128
38128
|
const rate2 = {
|
|
38129
38129
|
num: parseInt_(expr.rate.num),
|
|
38130
38130
|
den: parseInt_(expr.rate.den)
|
|
@@ -38135,12 +38135,12 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38135
38135
|
};
|
|
38136
38136
|
}
|
|
38137
38137
|
case "mulInt": {
|
|
38138
|
-
const vals = evalAll([expr.base, expr.count],
|
|
38138
|
+
const vals = evalAll([expr.base, expr.count], rule2, ctx, children);
|
|
38139
38139
|
if (vals === POISON)
|
|
38140
38140
|
return POISON;
|
|
38141
38141
|
const [base, count] = vals;
|
|
38142
|
-
expectType(base, "money",
|
|
38143
|
-
expectType(count, "int",
|
|
38142
|
+
expectType(base, "money", rule2, "mulInt.base");
|
|
38143
|
+
expectType(count, "int", rule2, "mulInt.count");
|
|
38144
38144
|
return {
|
|
38145
38145
|
type: "money",
|
|
38146
38146
|
cents: base.cents * count.value
|
|
@@ -38148,79 +38148,79 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38148
38148
|
}
|
|
38149
38149
|
case "min":
|
|
38150
38150
|
case "max": {
|
|
38151
|
-
const vals = evalAll(expr.args,
|
|
38151
|
+
const vals = evalAll(expr.args, rule2, ctx, children);
|
|
38152
38152
|
if (vals === POISON)
|
|
38153
38153
|
return POISON;
|
|
38154
38154
|
const pick2 = expr.kind === "min" ? (a, b) => b < a ? b : a : (a, b) => b > a ? b : a;
|
|
38155
|
-
return numericFold(vals,
|
|
38155
|
+
return numericFold(vals, rule2, expr.kind, pick2);
|
|
38156
38156
|
}
|
|
38157
38157
|
case "max0": {
|
|
38158
|
-
const v = evalExpr(expr.arg,
|
|
38158
|
+
const v = evalExpr(expr.arg, rule2, ctx, children);
|
|
38159
38159
|
if (v === POISON)
|
|
38160
38160
|
return POISON;
|
|
38161
|
-
expectType(v, "money",
|
|
38161
|
+
expectType(v, "money", rule2, "max0");
|
|
38162
38162
|
return { type: "money", cents: max0(v.cents) };
|
|
38163
38163
|
}
|
|
38164
38164
|
case "clamp": {
|
|
38165
|
-
const vals = evalAll([expr.value, expr.lo, expr.hi],
|
|
38165
|
+
const vals = evalAll([expr.value, expr.lo, expr.hi], rule2, ctx, children);
|
|
38166
38166
|
if (vals === POISON)
|
|
38167
38167
|
return POISON;
|
|
38168
38168
|
const [v, lo, hi] = vals.map((x) => {
|
|
38169
|
-
expectType(x, "money",
|
|
38169
|
+
expectType(x, "money", rule2, "clamp");
|
|
38170
38170
|
return x.cents;
|
|
38171
38171
|
});
|
|
38172
38172
|
const clamped = v < lo ? lo : v > hi ? hi : v;
|
|
38173
38173
|
return { type: "money", cents: clamped };
|
|
38174
38174
|
}
|
|
38175
38175
|
case "roundToDollar": {
|
|
38176
|
-
const v = evalExpr(expr.value,
|
|
38176
|
+
const v = evalExpr(expr.value, rule2, ctx, children);
|
|
38177
38177
|
if (v === POISON)
|
|
38178
38178
|
return POISON;
|
|
38179
|
-
expectType(v, "money",
|
|
38179
|
+
expectType(v, "money", rule2, "roundToDollar");
|
|
38180
38180
|
return {
|
|
38181
38181
|
type: "money",
|
|
38182
38182
|
cents: roundToDollar(v.cents, expr.mode)
|
|
38183
38183
|
};
|
|
38184
38184
|
}
|
|
38185
38185
|
case "mulDiv": {
|
|
38186
|
-
const vals = evalAll([expr.a, expr.b, expr.c],
|
|
38186
|
+
const vals = evalAll([expr.a, expr.b, expr.c], rule2, ctx, children);
|
|
38187
38187
|
if (vals === POISON)
|
|
38188
38188
|
return POISON;
|
|
38189
38189
|
const [a, b, c2] = vals.map((x) => {
|
|
38190
|
-
expectType(x, "money",
|
|
38190
|
+
expectType(x, "money", rule2, "mulDiv");
|
|
38191
38191
|
return x.cents;
|
|
38192
38192
|
});
|
|
38193
38193
|
if (c2 === 0n) {
|
|
38194
|
-
throw new EngineError(`rule "${
|
|
38194
|
+
throw new EngineError(`rule "${rule2.id}": mulDiv division by zero`);
|
|
38195
38195
|
}
|
|
38196
38196
|
return { type: "money", cents: divRound(a * b, c2, expr.round) };
|
|
38197
38197
|
}
|
|
38198
38198
|
case "unsupported":
|
|
38199
|
-
throw new NotModeledError(
|
|
38199
|
+
throw new NotModeledError(rule2.id, expr.reason);
|
|
38200
38200
|
case "stepUnits": {
|
|
38201
|
-
const v = evalExpr(expr.value,
|
|
38201
|
+
const v = evalExpr(expr.value, rule2, ctx, children);
|
|
38202
38202
|
if (v === POISON)
|
|
38203
38203
|
return POISON;
|
|
38204
|
-
expectType(v, "money",
|
|
38204
|
+
expectType(v, "money", rule2, "stepUnits");
|
|
38205
38205
|
return {
|
|
38206
38206
|
type: "int",
|
|
38207
38207
|
value: stepUnits(v.cents, parseCents(expr.unitCents), expr.mode)
|
|
38208
38208
|
};
|
|
38209
38209
|
}
|
|
38210
38210
|
case "cmp": {
|
|
38211
|
-
const vals = evalAll([expr.left, expr.right],
|
|
38211
|
+
const vals = evalAll([expr.left, expr.right], rule2, ctx, children);
|
|
38212
38212
|
if (vals === POISON)
|
|
38213
38213
|
return POISON;
|
|
38214
38214
|
const [l, r] = vals;
|
|
38215
38215
|
if (l.type !== r.type) {
|
|
38216
|
-
throw new EngineError(`rule "${
|
|
38216
|
+
throw new EngineError(`rule "${rule2.id}": cmp between ${l.type} and ${r.type}`);
|
|
38217
38217
|
}
|
|
38218
38218
|
if (expr.op === "eq" || expr.op === "ne") {
|
|
38219
38219
|
const eq3 = canonicalScalar(l) === canonicalScalar(r);
|
|
38220
38220
|
return { type: "bool", value: expr.op === "eq" ? eq3 : !eq3 };
|
|
38221
38221
|
}
|
|
38222
|
-
const ln = numericOf(l,
|
|
38223
|
-
const rn = numericOf(r,
|
|
38222
|
+
const ln = numericOf(l, rule2, "cmp");
|
|
38223
|
+
const rn = numericOf(r, rule2, "cmp");
|
|
38224
38224
|
const result = expr.op === "lt" ? ln < rn : expr.op === "le" ? ln <= rn : expr.op === "gt" ? ln > rn : ln >= rn;
|
|
38225
38225
|
return { type: "bool", value: result };
|
|
38226
38226
|
}
|
|
@@ -38229,12 +38229,12 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38229
38229
|
const decider = expr.kind === "and" ? false : true;
|
|
38230
38230
|
let sawPoison = false;
|
|
38231
38231
|
for (const arg of expr.args) {
|
|
38232
|
-
const v = evalExpr(arg,
|
|
38232
|
+
const v = evalExpr(arg, rule2, ctx, children);
|
|
38233
38233
|
if (v === POISON) {
|
|
38234
38234
|
sawPoison = true;
|
|
38235
38235
|
continue;
|
|
38236
38236
|
}
|
|
38237
|
-
expectType(v, "bool",
|
|
38237
|
+
expectType(v, "bool", rule2, expr.kind);
|
|
38238
38238
|
if (v.value === decider) {
|
|
38239
38239
|
return { type: "bool", value: decider };
|
|
38240
38240
|
}
|
|
@@ -38244,24 +38244,24 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38244
38244
|
return { type: "bool", value: !decider };
|
|
38245
38245
|
}
|
|
38246
38246
|
case "not": {
|
|
38247
|
-
const v = evalExpr(expr.arg,
|
|
38247
|
+
const v = evalExpr(expr.arg, rule2, ctx, children);
|
|
38248
38248
|
if (v === POISON)
|
|
38249
38249
|
return POISON;
|
|
38250
|
-
expectType(v, "bool",
|
|
38250
|
+
expectType(v, "bool", rule2, "not");
|
|
38251
38251
|
return { type: "bool", value: !v.value };
|
|
38252
38252
|
}
|
|
38253
38253
|
case "if": {
|
|
38254
|
-
const cond = evalExpr(expr.cond,
|
|
38254
|
+
const cond = evalExpr(expr.cond, rule2, ctx, children);
|
|
38255
38255
|
if (cond === POISON)
|
|
38256
38256
|
return POISON;
|
|
38257
|
-
expectType(cond, "bool",
|
|
38258
|
-
return evalExpr(cond.value ? expr.then : expr.else,
|
|
38257
|
+
expectType(cond, "bool", rule2, "if.cond");
|
|
38258
|
+
return evalExpr(cond.value ? expr.then : expr.else, rule2, ctx, children);
|
|
38259
38259
|
}
|
|
38260
38260
|
case "brackets": {
|
|
38261
|
-
const base = evalExpr(expr.base,
|
|
38261
|
+
const base = evalExpr(expr.base, rule2, ctx, children);
|
|
38262
38262
|
if (base === POISON)
|
|
38263
38263
|
return POISON;
|
|
38264
|
-
expectType(base, "money",
|
|
38264
|
+
expectType(base, "money", rule2, "brackets.base");
|
|
38265
38265
|
const amount = base.cents;
|
|
38266
38266
|
let tax = 0n;
|
|
38267
38267
|
for (let i = 0; i < expr.table.length; i++) {
|
|
@@ -38279,17 +38279,17 @@ function evalExpr(expr, rule, ctx, children) {
|
|
|
38279
38279
|
return { type: "money", cents: tax };
|
|
38280
38280
|
}
|
|
38281
38281
|
case "match": {
|
|
38282
|
-
const on = evalExpr(expr.on,
|
|
38282
|
+
const on = evalExpr(expr.on, rule2, ctx, children);
|
|
38283
38283
|
if (on === POISON)
|
|
38284
38284
|
return POISON;
|
|
38285
|
-
expectType(on, "enum",
|
|
38285
|
+
expectType(on, "enum", rule2, "match.on");
|
|
38286
38286
|
const tag = on.value;
|
|
38287
38287
|
const found = expr.cases.find((c2) => c2.when === tag);
|
|
38288
38288
|
if (found)
|
|
38289
|
-
return evalExpr(found.value,
|
|
38289
|
+
return evalExpr(found.value, rule2, ctx, children);
|
|
38290
38290
|
if (expr.else)
|
|
38291
|
-
return evalExpr(expr.else,
|
|
38292
|
-
throw new UnhandledEnumCaseError(
|
|
38291
|
+
return evalExpr(expr.else, rule2, ctx, children);
|
|
38292
|
+
throw new UnhandledEnumCaseError(rule2.id, tag);
|
|
38293
38293
|
}
|
|
38294
38294
|
}
|
|
38295
38295
|
}
|
|
@@ -38333,11 +38333,11 @@ function resolveFact(factId, ctx, children) {
|
|
|
38333
38333
|
children.push(node2);
|
|
38334
38334
|
return ctx.facts.get(factId);
|
|
38335
38335
|
}
|
|
38336
|
-
function evalAll(exprs,
|
|
38336
|
+
function evalAll(exprs, rule2, ctx, children) {
|
|
38337
38337
|
const out = [];
|
|
38338
38338
|
let poisoned = false;
|
|
38339
38339
|
for (const e of exprs) {
|
|
38340
|
-
const v = evalExpr(e,
|
|
38340
|
+
const v = evalExpr(e, rule2, ctx, children);
|
|
38341
38341
|
if (v === POISON)
|
|
38342
38342
|
poisoned = true;
|
|
38343
38343
|
else
|
|
@@ -38345,28 +38345,28 @@ function evalAll(exprs, rule, ctx, children) {
|
|
|
38345
38345
|
}
|
|
38346
38346
|
return poisoned ? POISON : out;
|
|
38347
38347
|
}
|
|
38348
|
-
function numericFold(vals,
|
|
38348
|
+
function numericFold(vals, rule2, op, fold) {
|
|
38349
38349
|
if (vals.length === 0)
|
|
38350
|
-
throw new EngineError(`rule "${
|
|
38350
|
+
throw new EngineError(`rule "${rule2.id}": empty ${op}`);
|
|
38351
38351
|
const type = vals[0].type;
|
|
38352
38352
|
if (type !== "money" && type !== "int") {
|
|
38353
|
-
throw new EngineError(`rule "${
|
|
38353
|
+
throw new EngineError(`rule "${rule2.id}": ${op} over ${type}`);
|
|
38354
38354
|
}
|
|
38355
|
-
let acc = numericOf(vals[0],
|
|
38355
|
+
let acc = numericOf(vals[0], rule2, op);
|
|
38356
38356
|
for (const v of vals.slice(1)) {
|
|
38357
38357
|
if (v.type !== type) {
|
|
38358
|
-
throw new EngineError(`rule "${
|
|
38358
|
+
throw new EngineError(`rule "${rule2.id}": ${op} mixes ${type} and ${v.type}`);
|
|
38359
38359
|
}
|
|
38360
|
-
acc = fold(acc, numericOf(v,
|
|
38360
|
+
acc = fold(acc, numericOf(v, rule2, op));
|
|
38361
38361
|
}
|
|
38362
38362
|
return type === "money" ? { type: "money", cents: acc } : { type: "int", value: acc };
|
|
38363
38363
|
}
|
|
38364
|
-
function numericOf(v,
|
|
38364
|
+
function numericOf(v, rule2, op) {
|
|
38365
38365
|
if (v.type === "money")
|
|
38366
38366
|
return v.cents;
|
|
38367
38367
|
if (v.type === "int")
|
|
38368
38368
|
return v.value;
|
|
38369
|
-
throw new EngineError(`rule "${
|
|
38369
|
+
throw new EngineError(`rule "${rule2.id}": ${op} expects money|int, got ${v.type}`);
|
|
38370
38370
|
}
|
|
38371
38371
|
function canonicalScalar(v) {
|
|
38372
38372
|
switch (v.type) {
|
|
@@ -38380,9 +38380,9 @@ function canonicalScalar(v) {
|
|
|
38380
38380
|
return `e:${v.value}`;
|
|
38381
38381
|
}
|
|
38382
38382
|
}
|
|
38383
|
-
function expectType(v, type,
|
|
38383
|
+
function expectType(v, type, rule2, where) {
|
|
38384
38384
|
if (v.type !== type) {
|
|
38385
|
-
throw new EngineError(`rule "${
|
|
38385
|
+
throw new EngineError(`rule "${rule2.id}": ${where} expects ${type}, got ${v.type}`);
|
|
38386
38386
|
}
|
|
38387
38387
|
}
|
|
38388
38388
|
function coerceFacts(corpus2, plain) {
|
|
@@ -38568,9 +38568,9 @@ function compareAcross(corpus2, baseFacts, options) {
|
|
|
38568
38568
|
|
|
38569
38569
|
// ../solve/dist/lookup.js
|
|
38570
38570
|
var tokenize = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, " ").split(" ").filter((t) => t.length > 2);
|
|
38571
|
-
function extractByStatus(
|
|
38571
|
+
function extractByStatus(rule2) {
|
|
38572
38572
|
const out = {};
|
|
38573
|
-
walkExpr(
|
|
38573
|
+
walkExpr(rule2.formula, (e) => {
|
|
38574
38574
|
if (e.kind === "match" && e.on.kind === "fact" && e.on.factId === "filingStatus") {
|
|
38575
38575
|
for (const c2 of e.cases) {
|
|
38576
38576
|
if (c2.value.kind === "money")
|
|
@@ -38613,13 +38613,13 @@ function lookupParameters(corpus2, query, asOf) {
|
|
|
38613
38613
|
if (tokens.length === 0)
|
|
38614
38614
|
return [];
|
|
38615
38615
|
const hits = [];
|
|
38616
|
-
for (const
|
|
38617
|
-
if (asOf && !(
|
|
38616
|
+
for (const rule2 of corpus2.rules) {
|
|
38617
|
+
if (asOf && !(rule2.effectiveFrom <= asOf && (rule2.effectiveTo === void 0 || asOf < rule2.effectiveTo))) {
|
|
38618
38618
|
continue;
|
|
38619
38619
|
}
|
|
38620
|
-
const paramWords = Object.keys(
|
|
38621
|
-
const haystackStrong = `${
|
|
38622
|
-
const haystackWeak = `${
|
|
38620
|
+
const paramWords = Object.keys(rule2.parameters ?? {}).map((n) => n.replace(/([A-Z])/g, " $1").toLowerCase()).join(" ");
|
|
38621
|
+
const haystackStrong = `${rule2.id} ${rule2.title} ${paramWords} ${JURISDICTION_NAMES[rule2.jurisdiction] ?? ""}`.toLowerCase();
|
|
38622
|
+
const haystackWeak = `${rule2.citation.source} ${rule2.citation.section} ${rule2.citation.excerpt}`.toLowerCase();
|
|
38623
38623
|
let score = 0;
|
|
38624
38624
|
for (const t of tokens) {
|
|
38625
38625
|
if (haystackStrong.includes(t))
|
|
@@ -38630,23 +38630,23 @@ function lookupParameters(corpus2, query, asOf) {
|
|
|
38630
38630
|
if (score === 0)
|
|
38631
38631
|
continue;
|
|
38632
38632
|
const parameters = {};
|
|
38633
|
-
for (const [name, p] of Object.entries(
|
|
38633
|
+
for (const [name, p] of Object.entries(rule2.parameters ?? {})) {
|
|
38634
38634
|
if (p.type === "money")
|
|
38635
38635
|
parameters[name] = String(p.value);
|
|
38636
38636
|
}
|
|
38637
|
-
const byFilingStatus = extractByStatus(
|
|
38637
|
+
const byFilingStatus = extractByStatus(rule2);
|
|
38638
38638
|
if (Object.keys(parameters).length === 0 && Object.keys(byFilingStatus).length === 0) {
|
|
38639
38639
|
score -= 1;
|
|
38640
38640
|
if (score <= 0)
|
|
38641
38641
|
continue;
|
|
38642
38642
|
}
|
|
38643
38643
|
hits.push({
|
|
38644
|
-
ruleId:
|
|
38645
|
-
version:
|
|
38646
|
-
title:
|
|
38647
|
-
citation:
|
|
38648
|
-
effectiveFrom:
|
|
38649
|
-
effectiveTo:
|
|
38644
|
+
ruleId: rule2.id,
|
|
38645
|
+
version: rule2.version,
|
|
38646
|
+
title: rule2.title,
|
|
38647
|
+
citation: rule2.citation,
|
|
38648
|
+
effectiveFrom: rule2.effectiveFrom,
|
|
38649
|
+
effectiveTo: rule2.effectiveTo,
|
|
38650
38650
|
parameters,
|
|
38651
38651
|
byFilingStatus,
|
|
38652
38652
|
score
|
|
@@ -38674,16 +38674,16 @@ function searchRules(corpus2, query, asOf, limit = 8) {
|
|
|
38674
38674
|
const allTokens = [...new Set(tokenize(query.slice(0, 500)))].slice(0, 12);
|
|
38675
38675
|
if (allTokens.length === 0)
|
|
38676
38676
|
return [];
|
|
38677
|
-
const haystacks = corpus2.rules.map((
|
|
38678
|
-
const paramWords = Object.keys(
|
|
38677
|
+
const haystacks = corpus2.rules.map((rule2) => {
|
|
38678
|
+
const paramWords = Object.keys(rule2.parameters ?? {}).map((n) => n.replace(/([A-Z])/g, " $1").toLowerCase()).join(" ");
|
|
38679
38679
|
return {
|
|
38680
|
-
rule,
|
|
38680
|
+
rule: rule2,
|
|
38681
38681
|
// "_" is a regex word character — split snake_case so \b-anchored
|
|
38682
38682
|
// tokens ("tax") still reach id segments ("kiddie_tax").
|
|
38683
|
-
id:
|
|
38684
|
-
title:
|
|
38685
|
-
meta: `${paramWords} ${JURISDICTION_NAMES[
|
|
38686
|
-
weak: `${
|
|
38683
|
+
id: rule2.id.toLowerCase().replace(/[._]/g, " "),
|
|
38684
|
+
title: rule2.title.toLowerCase(),
|
|
38685
|
+
meta: `${paramWords} ${JURISDICTION_NAMES[rule2.jurisdiction] ?? ""}`.toLowerCase(),
|
|
38686
|
+
weak: `${rule2.citation.source} ${rule2.citation.section} ${rule2.citation.excerpt ?? ""}`.toLowerCase()
|
|
38687
38687
|
};
|
|
38688
38688
|
});
|
|
38689
38689
|
const matchers = new Map(allTokens.map((t) => [t, new RegExp(`\\b${t}`)]));
|
|
@@ -38695,8 +38695,8 @@ function searchRules(corpus2, query, asOf, limit = 8) {
|
|
|
38695
38695
|
const boost = new Map(tokens.map((t) => [t, dfCache.get(t) <= haystacks.length * 0.05 ? 2 : 1]));
|
|
38696
38696
|
const minScore = tokens.length >= 2 ? 2 : 1;
|
|
38697
38697
|
const hits = [];
|
|
38698
|
-
for (const { rule, id, title, meta: meta3, weak } of haystacks) {
|
|
38699
|
-
if (asOf && !(
|
|
38698
|
+
for (const { rule: rule2, id: id2, title, meta: meta3, weak } of haystacks) {
|
|
38699
|
+
if (asOf && !(rule2.effectiveFrom <= asOf && (rule2.effectiveTo === void 0 || asOf < rule2.effectiveTo))) {
|
|
38700
38700
|
continue;
|
|
38701
38701
|
}
|
|
38702
38702
|
let raw = 0;
|
|
@@ -38705,7 +38705,7 @@ function searchRules(corpus2, query, asOf, limit = 8) {
|
|
|
38705
38705
|
let sawStrong = false;
|
|
38706
38706
|
for (const t of tokens) {
|
|
38707
38707
|
let s = 0;
|
|
38708
|
-
if (has(
|
|
38708
|
+
if (has(id2, t))
|
|
38709
38709
|
s += 2;
|
|
38710
38710
|
if (has(title, t))
|
|
38711
38711
|
s += 2;
|
|
@@ -38725,15 +38725,15 @@ function searchRules(corpus2, query, asOf, limit = 8) {
|
|
|
38725
38725
|
if (tokens.length >= 2 && !sawStrong)
|
|
38726
38726
|
continue;
|
|
38727
38727
|
hits.push({
|
|
38728
|
-
ruleId:
|
|
38729
|
-
version:
|
|
38730
|
-
title:
|
|
38731
|
-
jurisdiction:
|
|
38732
|
-
citation:
|
|
38733
|
-
effectiveFrom:
|
|
38734
|
-
effectiveTo:
|
|
38735
|
-
snippet: makeSnippet(
|
|
38736
|
-
hasParameters: Object.keys(
|
|
38728
|
+
ruleId: rule2.id,
|
|
38729
|
+
version: rule2.version,
|
|
38730
|
+
title: rule2.title,
|
|
38731
|
+
jurisdiction: rule2.jurisdiction,
|
|
38732
|
+
citation: rule2.citation,
|
|
38733
|
+
effectiveFrom: rule2.effectiveFrom,
|
|
38734
|
+
effectiveTo: rule2.effectiveTo,
|
|
38735
|
+
snippet: makeSnippet(rule2.citation.excerpt ?? "", tokens),
|
|
38736
|
+
hasParameters: Object.keys(rule2.parameters ?? {}).length > 0,
|
|
38737
38737
|
score
|
|
38738
38738
|
});
|
|
38739
38739
|
}
|
|
@@ -38833,17 +38833,17 @@ var isIncompleteReturnRefusal = (err) => err instanceof Error && err.code === "I
|
|
|
38833
38833
|
// ../compose/dist/money.js
|
|
38834
38834
|
var c = (d3) => BigInt(Math.round((d3 ?? 0) * 100));
|
|
38835
38835
|
var rd = (x) => {
|
|
38836
|
-
const
|
|
38837
|
-
const a =
|
|
38836
|
+
const neg3 = x < 0n;
|
|
38837
|
+
const a = neg3 ? -x : x;
|
|
38838
38838
|
const r = (a + 50n) / 100n * 100n;
|
|
38839
|
-
return
|
|
38839
|
+
return neg3 ? -r : r;
|
|
38840
38840
|
};
|
|
38841
38841
|
var max02 = (x) => x > 0n ? x : 0n;
|
|
38842
38842
|
var min2 = (a, b) => a < b ? a : b;
|
|
38843
38843
|
var fmtD = (x) => {
|
|
38844
|
-
const
|
|
38845
|
-
const a =
|
|
38846
|
-
return `${
|
|
38844
|
+
const neg3 = x < 0n;
|
|
38845
|
+
const a = neg3 ? -x : x;
|
|
38846
|
+
return `${neg3 ? "-" : ""}$${(a / 100n).toLocaleString()}`;
|
|
38847
38847
|
};
|
|
38848
38848
|
|
|
38849
38849
|
// ../compose/dist/types.js
|
|
@@ -39442,8 +39442,8 @@ function composeMO(input2, evalStateTax, notes) {
|
|
|
39442
39442
|
const privRaw = min2(rd(c(input2.moPrivatePensionYou)), PRIVATE_PENSION_CAP) + min2(rd(c(input2.moPrivatePensionSpouse)), PRIVATE_PENSION_CAP);
|
|
39443
39443
|
let secB = 0n;
|
|
39444
39444
|
if (privRaw > 0n) {
|
|
39445
|
-
const
|
|
39446
|
-
secB = max02(privRaw -
|
|
39445
|
+
const excess2 = max02(l6 - rd(c(input2.taxableSocialSecurity)) - privateLimit);
|
|
39446
|
+
secB = max02(privRaw - excess2);
|
|
39447
39447
|
notes.push(`MO-A Section B private pension exemption ${fmtD(secB)} ($6,000/spouse cap, reduced by the excess of MO AGI less taxable SS over ${fmtD(privateLimit)})`);
|
|
39448
39448
|
}
|
|
39449
39449
|
const l8 = secAY + secAS + secB + secC;
|
|
@@ -39484,7 +39484,7 @@ function composeMO(input2, evalStateTax, notes) {
|
|
|
39484
39484
|
const l2124 = rd(c(input2.moOtherDeductions));
|
|
39485
39485
|
const l25 = l8 + l13 + l14 + l15 + l16 + l17 + l18 + l19 + l2124;
|
|
39486
39486
|
const l26 = l6 - l25;
|
|
39487
|
-
const alloc = (
|
|
39487
|
+
const alloc = (pct13) => rd((l26 * pct13 + 50n) / 100n);
|
|
39488
39488
|
const l27Y = pctY === 100n ? rd(l26) : alloc(pctY);
|
|
39489
39489
|
const l27S = pctS === 0n ? 0n : pctS === 100n ? rd(l26) : alloc(pctS);
|
|
39490
39490
|
const l28Y = rd(c(input2.moEnterpriseZoneYou));
|
|
@@ -41550,10 +41550,10 @@ function composeAR(input2, evalStateTax, notes) {
|
|
|
41550
41550
|
if (itemize) {
|
|
41551
41551
|
method = "itemized";
|
|
41552
41552
|
if (status4) {
|
|
41553
|
-
const
|
|
41554
|
-
a27 = (itemized *
|
|
41553
|
+
const pct13 = agiAll > 0n ? (a25 * 200n + agiAll) / (2n * agiAll) : 100n;
|
|
41554
|
+
a27 = (itemized * pct13 + 50n) / 100n;
|
|
41555
41555
|
b27 = itemized - a27;
|
|
41556
|
-
n.push(`AR3 lines 31-35: itemized deductions ${fmtD(itemized)} prorated ${
|
|
41556
|
+
n.push(`AR3 lines 31-35: itemized deductions ${fmtD(itemized)} prorated ${pct13}% to the primary (${fmtD(a27)}) and ${fmtD(b27)} to the spouse by AGI share (whole percent)`);
|
|
41557
41557
|
} else
|
|
41558
41558
|
a27 = itemized;
|
|
41559
41559
|
if (fs === "mfs")
|
|
@@ -46889,7 +46889,7 @@ var facts = [
|
|
|
46889
46889
|
id: "qbiW2Wages",
|
|
46890
46890
|
type: "money",
|
|
46891
46891
|
min: "0",
|
|
46892
|
-
description: "W-2 wages PAID BY the qualified trade or business, allocable to QBI (\xA7 199A(b)(4)) \u2014 drives the above-threshold wage limit. Intake forms often label this 'W-2 Wages Paid' under the business section: it is a \xA7 199A LIMIT input, NOT a Schedule C expense \u2014 never subtract it from selfEmploymentNetProfit. Defaults to $0, which can only understate the deduction (conservative). In dollars.",
|
|
46892
|
+
description: "W-2 wages PAID BY the qualified trade or business, allocable to QBI (\xA7 199A(b)(4)) \u2014 drives the above-threshold wage limit. Intake forms often label this 'W-2 Wages Paid' under the business section: it is a \xA7 199A LIMIT input, NOT a Schedule C expense \u2014 never subtract it from selfEmploymentNetProfit. With businesses listed separately (qbiAdditionalBusinesses) these are the main business's wages \u2014 the business holding whatever QBI is not listed. Defaults to $0, which can only understate the deduction (conservative). In dollars.",
|
|
46893
46893
|
default: {
|
|
46894
46894
|
value: "0",
|
|
46895
46895
|
rationale: "Assumed the business paid no W-2 wages absent contrary input (conservative above the threshold)"
|
|
@@ -46899,7 +46899,7 @@ var facts = [
|
|
|
46899
46899
|
id: "qbiUBIA",
|
|
46900
46900
|
type: "money",
|
|
46901
46901
|
min: "0",
|
|
46902
|
-
description: "Unadjusted basis immediately after acquisition of the business's qualified property (\xA7 199A(b)(6)) \u2014 the 2.5% prong of the wage limit. Defaults to $0 (conservative). In dollars.",
|
|
46902
|
+
description: "Unadjusted basis immediately after acquisition of the business's qualified property (\xA7 199A(b)(6)) \u2014 the 2.5% prong of the wage limit. With businesses listed separately, the main business's UBIA. Defaults to $0 (conservative). In dollars.",
|
|
46903
46903
|
default: {
|
|
46904
46904
|
value: "0",
|
|
46905
46905
|
rationale: "Assumed no qualified-property UBIA absent contrary input (conservative)"
|
|
@@ -46908,10 +46908,294 @@ var facts = [
|
|
|
46908
46908
|
{
|
|
46909
46909
|
id: "businessIsSSTB",
|
|
46910
46910
|
type: "bool",
|
|
46911
|
-
description: "The trade or business is a specified service trade or business (\xA7 199A(d)(2): health, law, accounting, consulting, financial services, athletics, performing arts, \u2026) \u2014 above the threshold an SSTB's deduction phases to zero."
|
|
46911
|
+
description: "The trade or business is a specified service trade or business (\xA7 199A(d)(2): health, law, accounting, consulting, financial services, athletics, performing arts, \u2026) \u2014 above the threshold an SSTB's deduction phases to zero. With businesses listed separately, this is the main business \u2014 the one holding whatever QBI is not listed."
|
|
46912
46912
|
// no default — only demanded above the § 199A threshold, where it
|
|
46913
46913
|
// decides everything; the engine must never guess it
|
|
46914
46914
|
},
|
|
46915
|
+
{
|
|
46916
|
+
id: "qbiAggregationGroup",
|
|
46917
|
+
type: "int",
|
|
46918
|
+
min: "0",
|
|
46919
|
+
max: "9",
|
|
46920
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of the main business (QBI not listed separately): businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
46921
|
+
default: {
|
|
46922
|
+
value: "0",
|
|
46923
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
46924
|
+
}
|
|
46925
|
+
},
|
|
46926
|
+
{
|
|
46927
|
+
id: "spouseQbiW2Wages",
|
|
46928
|
+
type: "money",
|
|
46929
|
+
min: "0",
|
|
46930
|
+
description: "JOINT RETURN: W-2 wages PAID BY the second spouse's own Schedule C business (\xA7 199A(b)(4)) \u2014 its above-threshold wage limit; that business is its own \xA7 199A trade or business. Never subtract it from spouseSelfEmploymentNetProfit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
46931
|
+
default: {
|
|
46932
|
+
value: "0",
|
|
46933
|
+
rationale: "Assumed the second spouse's business paid no W-2 wages (conservative above the threshold)"
|
|
46934
|
+
}
|
|
46935
|
+
},
|
|
46936
|
+
{
|
|
46937
|
+
id: "spouseQbiUBIA",
|
|
46938
|
+
type: "money",
|
|
46939
|
+
min: "0",
|
|
46940
|
+
description: "JOINT RETURN: UBIA of the second spouse's own Schedule C business's qualified property (\xA7 199A(b)(6)) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
46941
|
+
default: {
|
|
46942
|
+
value: "0",
|
|
46943
|
+
rationale: "Assumed no qualified-property UBIA in the second spouse's business (conservative)"
|
|
46944
|
+
}
|
|
46945
|
+
},
|
|
46946
|
+
{
|
|
46947
|
+
id: "spouseBusinessIsSSTB",
|
|
46948
|
+
type: "bool",
|
|
46949
|
+
description: "JOINT RETURN: the second spouse's own Schedule C business is a specified service trade or business (\xA7 199A(d)(2)). Asked only above the \xA7 199A threshold when that spouse has QBI."
|
|
46950
|
+
// no default — decides the deduction above the threshold; never guessed
|
|
46951
|
+
},
|
|
46952
|
+
{
|
|
46953
|
+
id: "spouseQbiAggregationGroup",
|
|
46954
|
+
type: "int",
|
|
46955
|
+
min: "0",
|
|
46956
|
+
max: "9",
|
|
46957
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of the second spouse's Schedule C business: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
46958
|
+
default: {
|
|
46959
|
+
value: "0",
|
|
46960
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
46961
|
+
}
|
|
46962
|
+
},
|
|
46963
|
+
{
|
|
46964
|
+
id: "qbiAdditionalBusinesses",
|
|
46965
|
+
type: "int",
|
|
46966
|
+
min: "0",
|
|
46967
|
+
max: "5",
|
|
46968
|
+
description: "How many trades or businesses to list separately for \xA7 199A (0\u20135), each in qbiBusiness2\u2026 through qbiBusiness6\u2026: each listed business gets its own W-2 wage and UBIA limit, SSTB status and aggregation group (Form 8995-A Part II, one column each). A listed business STAYS in the return's totals \u2014 its profit is part of selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a QBI loss part of qbiLossOffset \u2014 and listing it only takes it out of the main business, which keeps whatever QBI is not listed (with qbiW2Wages, qbiUBIA and businessIsSSTB). The second spouse's Schedule C on a joint return is already its own business: do not list it. List each S corporation or partnership K-1 with its Statement A amounts.",
|
|
46969
|
+
default: {
|
|
46970
|
+
value: "0",
|
|
46971
|
+
rationale: "Assumed one trade or business (plus the second spouse's Schedule C on a joint return)"
|
|
46972
|
+
}
|
|
46973
|
+
},
|
|
46974
|
+
{
|
|
46975
|
+
id: "qbiBusiness2Income",
|
|
46976
|
+
type: "money",
|
|
46977
|
+
description: "Listed business 2 (when qbiAdditionalBusinesses \u2265 1): its qualified business income, or a QBI LOSS as a NEGATIVE number (\xA7 199A(c); Form 8995-A Schedule C line 1(a)) \u2014 for a K-1, Statement A's QBI; for a Schedule C, net profit less its share of the \xBD-SE, SEP and SE-health deductions. Its income or loss must already be in the return's totals (a profit within selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a loss within qbiLossOffset). In dollars."
|
|
46978
|
+
// no default — a listed business's QBI is never guessed
|
|
46979
|
+
},
|
|
46980
|
+
{
|
|
46981
|
+
id: "qbiBusiness2W2Wages",
|
|
46982
|
+
type: "money",
|
|
46983
|
+
min: "0",
|
|
46984
|
+
description: "Listed business 2: W-2 wages paid by the business allocable to QBI (\xA7 199A(b)(4); K-1 Statement A) \u2014 its above-threshold wage limit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
46985
|
+
default: {
|
|
46986
|
+
value: "0",
|
|
46987
|
+
rationale: "Assumed listed business 2 paid no W-2 wages (conservative above the threshold)"
|
|
46988
|
+
}
|
|
46989
|
+
},
|
|
46990
|
+
{
|
|
46991
|
+
id: "qbiBusiness2UBIA",
|
|
46992
|
+
type: "money",
|
|
46993
|
+
min: "0",
|
|
46994
|
+
description: "Listed business 2: UBIA of its qualified property (\xA7 199A(b)(6); K-1 Statement A) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
46995
|
+
default: {
|
|
46996
|
+
value: "0",
|
|
46997
|
+
rationale: "Assumed no qualified-property UBIA in listed business 2 (conservative)"
|
|
46998
|
+
}
|
|
46999
|
+
},
|
|
47000
|
+
{
|
|
47001
|
+
id: "qbiBusiness2IsSSTB",
|
|
47002
|
+
type: "bool",
|
|
47003
|
+
description: "Listed business 2 is a specified service trade or business (\xA7 199A(d)(2); K-1 Statement A). Asked only above the \xA7 199A threshold."
|
|
47004
|
+
// no default — never guessed
|
|
47005
|
+
},
|
|
47006
|
+
{
|
|
47007
|
+
id: "qbiBusiness2AggregationGroup",
|
|
47008
|
+
type: "int",
|
|
47009
|
+
min: "0",
|
|
47010
|
+
max: "9",
|
|
47011
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of listed business 2: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
47012
|
+
default: {
|
|
47013
|
+
value: "0",
|
|
47014
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
47015
|
+
}
|
|
47016
|
+
},
|
|
47017
|
+
{
|
|
47018
|
+
id: "qbiBusiness3Income",
|
|
47019
|
+
type: "money",
|
|
47020
|
+
description: "Listed business 3 (when qbiAdditionalBusinesses \u2265 2): its qualified business income, or a QBI LOSS as a NEGATIVE number (\xA7 199A(c); Form 8995-A Schedule C line 1(a)) \u2014 for a K-1, Statement A's QBI; for a Schedule C, net profit less its share of the \xBD-SE, SEP and SE-health deductions. Its income or loss must already be in the return's totals (a profit within selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a loss within qbiLossOffset). In dollars."
|
|
47021
|
+
// no default — a listed business's QBI is never guessed
|
|
47022
|
+
},
|
|
47023
|
+
{
|
|
47024
|
+
id: "qbiBusiness3W2Wages",
|
|
47025
|
+
type: "money",
|
|
47026
|
+
min: "0",
|
|
47027
|
+
description: "Listed business 3: W-2 wages paid by the business allocable to QBI (\xA7 199A(b)(4); K-1 Statement A) \u2014 its above-threshold wage limit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
47028
|
+
default: {
|
|
47029
|
+
value: "0",
|
|
47030
|
+
rationale: "Assumed listed business 3 paid no W-2 wages (conservative above the threshold)"
|
|
47031
|
+
}
|
|
47032
|
+
},
|
|
47033
|
+
{
|
|
47034
|
+
id: "qbiBusiness3UBIA",
|
|
47035
|
+
type: "money",
|
|
47036
|
+
min: "0",
|
|
47037
|
+
description: "Listed business 3: UBIA of its qualified property (\xA7 199A(b)(6); K-1 Statement A) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
47038
|
+
default: {
|
|
47039
|
+
value: "0",
|
|
47040
|
+
rationale: "Assumed no qualified-property UBIA in listed business 3 (conservative)"
|
|
47041
|
+
}
|
|
47042
|
+
},
|
|
47043
|
+
{
|
|
47044
|
+
id: "qbiBusiness3IsSSTB",
|
|
47045
|
+
type: "bool",
|
|
47046
|
+
description: "Listed business 3 is a specified service trade or business (\xA7 199A(d)(2); K-1 Statement A). Asked only above the \xA7 199A threshold."
|
|
47047
|
+
// no default — never guessed
|
|
47048
|
+
},
|
|
47049
|
+
{
|
|
47050
|
+
id: "qbiBusiness3AggregationGroup",
|
|
47051
|
+
type: "int",
|
|
47052
|
+
min: "0",
|
|
47053
|
+
max: "9",
|
|
47054
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of listed business 3: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
47055
|
+
default: {
|
|
47056
|
+
value: "0",
|
|
47057
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
47058
|
+
}
|
|
47059
|
+
},
|
|
47060
|
+
{
|
|
47061
|
+
id: "qbiBusiness4Income",
|
|
47062
|
+
type: "money",
|
|
47063
|
+
description: "Listed business 4 (when qbiAdditionalBusinesses \u2265 3): its qualified business income, or a QBI LOSS as a NEGATIVE number (\xA7 199A(c); Form 8995-A Schedule C line 1(a)) \u2014 for a K-1, Statement A's QBI; for a Schedule C, net profit less its share of the \xBD-SE, SEP and SE-health deductions. Its income or loss must already be in the return's totals (a profit within selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a loss within qbiLossOffset). In dollars."
|
|
47064
|
+
// no default — a listed business's QBI is never guessed
|
|
47065
|
+
},
|
|
47066
|
+
{
|
|
47067
|
+
id: "qbiBusiness4W2Wages",
|
|
47068
|
+
type: "money",
|
|
47069
|
+
min: "0",
|
|
47070
|
+
description: "Listed business 4: W-2 wages paid by the business allocable to QBI (\xA7 199A(b)(4); K-1 Statement A) \u2014 its above-threshold wage limit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
47071
|
+
default: {
|
|
47072
|
+
value: "0",
|
|
47073
|
+
rationale: "Assumed listed business 4 paid no W-2 wages (conservative above the threshold)"
|
|
47074
|
+
}
|
|
47075
|
+
},
|
|
47076
|
+
{
|
|
47077
|
+
id: "qbiBusiness4UBIA",
|
|
47078
|
+
type: "money",
|
|
47079
|
+
min: "0",
|
|
47080
|
+
description: "Listed business 4: UBIA of its qualified property (\xA7 199A(b)(6); K-1 Statement A) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
47081
|
+
default: {
|
|
47082
|
+
value: "0",
|
|
47083
|
+
rationale: "Assumed no qualified-property UBIA in listed business 4 (conservative)"
|
|
47084
|
+
}
|
|
47085
|
+
},
|
|
47086
|
+
{
|
|
47087
|
+
id: "qbiBusiness4IsSSTB",
|
|
47088
|
+
type: "bool",
|
|
47089
|
+
description: "Listed business 4 is a specified service trade or business (\xA7 199A(d)(2); K-1 Statement A). Asked only above the \xA7 199A threshold."
|
|
47090
|
+
// no default — never guessed
|
|
47091
|
+
},
|
|
47092
|
+
{
|
|
47093
|
+
id: "qbiBusiness4AggregationGroup",
|
|
47094
|
+
type: "int",
|
|
47095
|
+
min: "0",
|
|
47096
|
+
max: "9",
|
|
47097
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of listed business 4: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
47098
|
+
default: {
|
|
47099
|
+
value: "0",
|
|
47100
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
47101
|
+
}
|
|
47102
|
+
},
|
|
47103
|
+
{
|
|
47104
|
+
id: "qbiBusiness5Income",
|
|
47105
|
+
type: "money",
|
|
47106
|
+
description: "Listed business 5 (when qbiAdditionalBusinesses \u2265 4): its qualified business income, or a QBI LOSS as a NEGATIVE number (\xA7 199A(c); Form 8995-A Schedule C line 1(a)) \u2014 for a K-1, Statement A's QBI; for a Schedule C, net profit less its share of the \xBD-SE, SEP and SE-health deductions. Its income or loss must already be in the return's totals (a profit within selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a loss within qbiLossOffset). In dollars."
|
|
47107
|
+
// no default — a listed business's QBI is never guessed
|
|
47108
|
+
},
|
|
47109
|
+
{
|
|
47110
|
+
id: "qbiBusiness5W2Wages",
|
|
47111
|
+
type: "money",
|
|
47112
|
+
min: "0",
|
|
47113
|
+
description: "Listed business 5: W-2 wages paid by the business allocable to QBI (\xA7 199A(b)(4); K-1 Statement A) \u2014 its above-threshold wage limit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
47114
|
+
default: {
|
|
47115
|
+
value: "0",
|
|
47116
|
+
rationale: "Assumed listed business 5 paid no W-2 wages (conservative above the threshold)"
|
|
47117
|
+
}
|
|
47118
|
+
},
|
|
47119
|
+
{
|
|
47120
|
+
id: "qbiBusiness5UBIA",
|
|
47121
|
+
type: "money",
|
|
47122
|
+
min: "0",
|
|
47123
|
+
description: "Listed business 5: UBIA of its qualified property (\xA7 199A(b)(6); K-1 Statement A) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
47124
|
+
default: {
|
|
47125
|
+
value: "0",
|
|
47126
|
+
rationale: "Assumed no qualified-property UBIA in listed business 5 (conservative)"
|
|
47127
|
+
}
|
|
47128
|
+
},
|
|
47129
|
+
{
|
|
47130
|
+
id: "qbiBusiness5IsSSTB",
|
|
47131
|
+
type: "bool",
|
|
47132
|
+
description: "Listed business 5 is a specified service trade or business (\xA7 199A(d)(2); K-1 Statement A). Asked only above the \xA7 199A threshold."
|
|
47133
|
+
// no default — never guessed
|
|
47134
|
+
},
|
|
47135
|
+
{
|
|
47136
|
+
id: "qbiBusiness5AggregationGroup",
|
|
47137
|
+
type: "int",
|
|
47138
|
+
min: "0",
|
|
47139
|
+
max: "9",
|
|
47140
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of listed business 5: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
47141
|
+
default: {
|
|
47142
|
+
value: "0",
|
|
47143
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
47144
|
+
}
|
|
47145
|
+
},
|
|
47146
|
+
{
|
|
47147
|
+
id: "qbiBusiness6Income",
|
|
47148
|
+
type: "money",
|
|
47149
|
+
description: "Listed business 6 (when qbiAdditionalBusinesses \u2265 5): its qualified business income, or a QBI LOSS as a NEGATIVE number (\xA7 199A(c); Form 8995-A Schedule C line 1(a)) \u2014 for a K-1, Statement A's QBI; for a Schedule C, net profit less its share of the \xBD-SE, SEP and SE-health deductions. Its income or loss must already be in the return's totals (a profit within selfEmploymentNetProfit or k1OrdinaryBusinessIncome, a loss within qbiLossOffset). In dollars."
|
|
47150
|
+
// no default — a listed business's QBI is never guessed
|
|
47151
|
+
},
|
|
47152
|
+
{
|
|
47153
|
+
id: "qbiBusiness6W2Wages",
|
|
47154
|
+
type: "money",
|
|
47155
|
+
min: "0",
|
|
47156
|
+
description: "Listed business 6: W-2 wages paid by the business allocable to QBI (\xA7 199A(b)(4); K-1 Statement A) \u2014 its above-threshold wage limit. Defaults to $0, which can only understate the deduction. In dollars.",
|
|
47157
|
+
default: {
|
|
47158
|
+
value: "0",
|
|
47159
|
+
rationale: "Assumed listed business 6 paid no W-2 wages (conservative above the threshold)"
|
|
47160
|
+
}
|
|
47161
|
+
},
|
|
47162
|
+
{
|
|
47163
|
+
id: "qbiBusiness6UBIA",
|
|
47164
|
+
type: "money",
|
|
47165
|
+
min: "0",
|
|
47166
|
+
description: "Listed business 6: UBIA of its qualified property (\xA7 199A(b)(6); K-1 Statement A) \u2014 the 2.5% prong of its wage limit. Defaults to $0 (conservative). In dollars.",
|
|
47167
|
+
default: {
|
|
47168
|
+
value: "0",
|
|
47169
|
+
rationale: "Assumed no qualified-property UBIA in listed business 6 (conservative)"
|
|
47170
|
+
}
|
|
47171
|
+
},
|
|
47172
|
+
{
|
|
47173
|
+
id: "qbiBusiness6IsSSTB",
|
|
47174
|
+
type: "bool",
|
|
47175
|
+
description: "Listed business 6 is a specified service trade or business (\xA7 199A(d)(2); K-1 Statement A). Asked only above the \xA7 199A threshold."
|
|
47176
|
+
// no default — never guessed
|
|
47177
|
+
},
|
|
47178
|
+
{
|
|
47179
|
+
id: "qbiBusiness6AggregationGroup",
|
|
47180
|
+
type: "int",
|
|
47181
|
+
min: "0",
|
|
47182
|
+
max: "9",
|
|
47183
|
+
description: "\xA7 199A aggregation group (Reg. \xA7 1.199A-4) of listed business 6: businesses given the same number from 1 to 9 are one business for the W-2 wage and UBIA limits (Form 8995-A Schedule B), adding their QBI, W-2 wages and UBIA; 0 = not aggregated. Aggregation requires 50% common ownership for the majority of the year, the same tax year, and two of the three Reg. \xA7 1.199A-4(b)(1)(v) factors; once chosen it must be kept in later years. A specified service trade or business may not be aggregated (refused). Read only above the \xA7 199A threshold when the return has two or more businesses.",
|
|
47184
|
+
default: {
|
|
47185
|
+
value: "0",
|
|
47186
|
+
rationale: "Assumed the business is not aggregated with another"
|
|
47187
|
+
}
|
|
47188
|
+
},
|
|
47189
|
+
{
|
|
47190
|
+
id: "qbiLossCarryforward",
|
|
47191
|
+
type: "money",
|
|
47192
|
+
min: "0",
|
|
47193
|
+
description: "Qualified business net LOSS carried forward from prior years, as a POSITIVE number (\xA7 199A(c)(2); last year's Form 8995 line 16 or Schedule C (Form 8995-A) line 6) \u2014 it reduces this year's QBI for the deduction only, never taxable income. Next year's amount is the target us.federal.qbi.loss_carryforward. In dollars.",
|
|
47194
|
+
default: {
|
|
47195
|
+
value: "0",
|
|
47196
|
+
rationale: "Assumed no qualified business loss carryforward from prior years"
|
|
47197
|
+
}
|
|
47198
|
+
},
|
|
46915
47199
|
{
|
|
46916
47200
|
id: "sepContribution",
|
|
46917
47201
|
type: "money",
|
|
@@ -52169,7 +52453,7 @@ function studentLoanRule(version2, effectiveFrom, effectiveTo, jointThresholdCen
|
|
|
52169
52453
|
then: param("thresholdJoint"),
|
|
52170
52454
|
else: param("threshold")
|
|
52171
52455
|
};
|
|
52172
|
-
const
|
|
52456
|
+
const range2 = {
|
|
52173
52457
|
kind: "if",
|
|
52174
52458
|
cond: isStatus("mfj"),
|
|
52175
52459
|
then: param("rangeJoint"),
|
|
@@ -52223,10 +52507,10 @@ function studentLoanRule(version2, effectiveFrom, effectiveTo, jointThresholdCen
|
|
|
52223
52507
|
kind: "min",
|
|
52224
52508
|
args: [
|
|
52225
52509
|
{ kind: "max0", arg: { kind: "sub", left: magi2, right: threshold2 } },
|
|
52226
|
-
|
|
52510
|
+
range2
|
|
52227
52511
|
]
|
|
52228
52512
|
},
|
|
52229
|
-
c:
|
|
52513
|
+
c: range2,
|
|
52230
52514
|
round: "half-up"
|
|
52231
52515
|
}
|
|
52232
52516
|
}
|
|
@@ -53006,14 +53290,14 @@ function quarterRule(q, year, from, to, proratedLimitCents, proratedLabel, withQ
|
|
|
53006
53290
|
{ kind: "mulRate", base: tiBeforeQbi, rate: { num: "20", den: "100" }, round: "half-up" }
|
|
53007
53291
|
]
|
|
53008
53292
|
};
|
|
53009
|
-
const
|
|
53293
|
+
const qbi = withQbiMinimum ? {
|
|
53010
53294
|
kind: "if",
|
|
53011
53295
|
cond: { kind: "cmp", op: "ge", left: qbiBase, right: money4("100000") },
|
|
53012
53296
|
then: { kind: "max", args: [qbiCore, money4("40000")] },
|
|
53013
53297
|
// OBBBA $400 min
|
|
53014
53298
|
else: qbiCore
|
|
53015
53299
|
} : qbiCore;
|
|
53016
|
-
const ti = { kind: "max0", arg: { kind: "sub", left: tiBeforeQbi, right:
|
|
53300
|
+
const ti = { kind: "max0", arg: { kind: "sub", left: tiBeforeQbi, right: qbi } };
|
|
53017
53301
|
const line17 = {
|
|
53018
53302
|
kind: "add",
|
|
53019
53303
|
args: [ordinaryRateTaxExpr(ti, "filingStatus", year), seTax]
|
|
@@ -55550,7 +55834,7 @@ function phased(tentative) {
|
|
|
55550
55834
|
then: param7("thresholdJoint"),
|
|
55551
55835
|
else: param7("threshold")
|
|
55552
55836
|
};
|
|
55553
|
-
const
|
|
55837
|
+
const range2 = {
|
|
55554
55838
|
kind: "if",
|
|
55555
55839
|
cond: isStatus4("mfj"),
|
|
55556
55840
|
then: param7("rangeJoint"),
|
|
@@ -55579,10 +55863,10 @@ function phased(tentative) {
|
|
|
55579
55863
|
right: threshold2
|
|
55580
55864
|
}
|
|
55581
55865
|
},
|
|
55582
|
-
|
|
55866
|
+
range2
|
|
55583
55867
|
]
|
|
55584
55868
|
},
|
|
55585
|
-
c:
|
|
55869
|
+
c: range2,
|
|
55586
55870
|
round: "half-up"
|
|
55587
55871
|
}
|
|
55588
55872
|
}
|
|
@@ -56460,7 +56744,7 @@ function repayment2025() {
|
|
|
56460
56744
|
else: capFor("162500", "325000")
|
|
56461
56745
|
}
|
|
56462
56746
|
};
|
|
56463
|
-
const
|
|
56747
|
+
const excess2 = {
|
|
56464
56748
|
kind: "max0",
|
|
56465
56749
|
arg: {
|
|
56466
56750
|
kind: "sub",
|
|
@@ -56496,8 +56780,8 @@ function repayment2025() {
|
|
|
56496
56780
|
then: {
|
|
56497
56781
|
kind: "if",
|
|
56498
56782
|
cond: { kind: "cmp", op: "lt", left: fplPercentCents, right: money19("40000") },
|
|
56499
|
-
then: { kind: "min", args: [
|
|
56500
|
-
else:
|
|
56783
|
+
then: { kind: "min", args: [excess2, cappedBand] },
|
|
56784
|
+
else: excess2
|
|
56501
56785
|
},
|
|
56502
56786
|
else: zero12
|
|
56503
56787
|
}
|
|
@@ -58042,8 +58326,8 @@ function iraRule(version2, effectiveFrom, effectiveTo, yearLabel, p, source, amo
|
|
|
58042
58326
|
{ kind: "if", cond: fact28("isAge50OrOlder"), then: param15("catchUp"), else: zero16 }
|
|
58043
58327
|
]
|
|
58044
58328
|
};
|
|
58045
|
-
const phasedLimit = (threshold2,
|
|
58046
|
-
const
|
|
58329
|
+
const phasedLimit = (threshold2, range2) => {
|
|
58330
|
+
const excess2 = {
|
|
58047
58331
|
kind: "max0",
|
|
58048
58332
|
arg: { kind: "sub", left: magi, right: threshold2 }
|
|
58049
58333
|
};
|
|
@@ -58054,14 +58338,14 @@ function iraRule(version2, effectiveFrom, effectiveTo, yearLabel, p, source, amo
|
|
|
58054
58338
|
// $10
|
|
58055
58339
|
count: {
|
|
58056
58340
|
kind: "stepUnits",
|
|
58057
|
-
value: { kind: "mulDiv", a: limit, b:
|
|
58341
|
+
value: { kind: "mulDiv", a: limit, b: excess2, c: range2, round: "floor" },
|
|
58058
58342
|
unitCents: "1000",
|
|
58059
58343
|
mode: "floor"
|
|
58060
58344
|
}
|
|
58061
58345
|
};
|
|
58062
58346
|
return {
|
|
58063
58347
|
kind: "if",
|
|
58064
|
-
cond: { kind: "cmp", op: "ge", left:
|
|
58348
|
+
cond: { kind: "cmp", op: "ge", left: excess2, right: range2 },
|
|
58065
58349
|
then: zero16,
|
|
58066
58350
|
// fully phased: the $200 floor does not apply
|
|
58067
58351
|
else: {
|
|
@@ -59320,8 +59604,8 @@ var F5695_2025 = "2025 Form 5695 (Cat. No. 13540P, created 3/20/25) and Instruct
|
|
|
59320
59604
|
var URL_25D = "https://www.law.cornell.edu/uscode/text/26/25D";
|
|
59321
59605
|
var URL_25C = "https://www.law.cornell.edu/uscode/text/26/25C";
|
|
59322
59606
|
var URL_I5695 = "https://www.irs.gov/pub/irs-pdf/i5695.pdf";
|
|
59323
|
-
var line = (
|
|
59324
|
-
id: `${J26}.energy.${
|
|
59607
|
+
var line = (id2, title, citation, formula, extra = {}) => ({
|
|
59608
|
+
id: `${J26}.energy.${id2}`,
|
|
59325
59609
|
version: 1,
|
|
59326
59610
|
jurisdiction: J26,
|
|
59327
59611
|
title,
|
|
@@ -60871,8 +61155,8 @@ var caRules = [
|
|
|
60871
61155
|
};
|
|
60872
61156
|
const param28 = (name) => ({ kind: "param", name });
|
|
60873
61157
|
const agi2 = ruleRef32("us.federal.agi");
|
|
60874
|
-
const
|
|
60875
|
-
const line26Hundredths = { kind: "stepUnits", value:
|
|
61158
|
+
const excess2 = { kind: "sub", left: earned2, right: param28("phaseOutStart") };
|
|
61159
|
+
const line26Hundredths = { kind: "stepUnits", value: excess2, unitCents: "100", mode: "floor" };
|
|
60876
61160
|
const line27Cents = {
|
|
60877
61161
|
kind: "mulInt",
|
|
60878
61162
|
base: money35("1"),
|
|
@@ -62089,7 +62373,7 @@ var njRules = [
|
|
|
62089
62373
|
},
|
|
62090
62374
|
formula: (() => {
|
|
62091
62375
|
const ti = max08(fact38("stateTaxableIncome"));
|
|
62092
|
-
const
|
|
62376
|
+
const pct13 = (num) => ({
|
|
62093
62377
|
kind: "mulRate",
|
|
62094
62378
|
base: fact38("njFederalCdcc"),
|
|
62095
62379
|
rate: { num, den: "100" },
|
|
@@ -62098,7 +62382,7 @@ var njRules = [
|
|
|
62098
62382
|
const tier = (max2, num, next) => ({
|
|
62099
62383
|
kind: "if",
|
|
62100
62384
|
cond: le(ti, param19(max2)),
|
|
62101
|
-
then:
|
|
62385
|
+
then: pct13(num),
|
|
62102
62386
|
else: next
|
|
62103
62387
|
});
|
|
62104
62388
|
return rd3(tier("tier1Max", "50", tier("tier2Max", "40", tier("tier3Max", "30", tier("tier4Max", "20", tier("tier5Max", "10", money35("0")))))));
|
|
@@ -62570,7 +62854,7 @@ var ohRules = [
|
|
|
62570
62854
|
// $75,000 → 10%; above → 5%
|
|
62571
62855
|
},
|
|
62572
62856
|
formula: (() => {
|
|
62573
|
-
const
|
|
62857
|
+
const pct13 = (num) => ({
|
|
62574
62858
|
kind: "mulRate",
|
|
62575
62859
|
base: max09(fact38("ohTaxLessCredits")),
|
|
62576
62860
|
rate: { num, den: "100" },
|
|
@@ -62579,16 +62863,16 @@ var ohRules = [
|
|
|
62579
62863
|
const tiered = {
|
|
62580
62864
|
kind: "if",
|
|
62581
62865
|
cond: le2(magiLessExemptions, param20("tier1Max")),
|
|
62582
|
-
then:
|
|
62866
|
+
then: pct13("20"),
|
|
62583
62867
|
else: {
|
|
62584
62868
|
kind: "if",
|
|
62585
62869
|
cond: le2(magiLessExemptions, param20("tier2Max")),
|
|
62586
|
-
then:
|
|
62870
|
+
then: pct13("15"),
|
|
62587
62871
|
else: {
|
|
62588
62872
|
kind: "if",
|
|
62589
62873
|
cond: le2(magiLessExemptions, param20("tier3Max")),
|
|
62590
|
-
then:
|
|
62591
|
-
else:
|
|
62874
|
+
then: pct13("10"),
|
|
62875
|
+
else: pct13("5")
|
|
62592
62876
|
}
|
|
62593
62877
|
}
|
|
62594
62878
|
};
|
|
@@ -63824,8 +64108,8 @@ var moRules = [
|
|
|
63824
64108
|
formula: (() => {
|
|
63825
64109
|
const magi2 = fact38("moMagi");
|
|
63826
64110
|
const total = { kind: "max0", arg: fact38("moFederalTaxTotal") };
|
|
63827
|
-
const
|
|
63828
|
-
const uncapped = iff2(le5(magi2, money35("2500000")),
|
|
64111
|
+
const pct13 = (num) => rd8({ kind: "mulRate", base: total, rate: { num, den: "100" }, round: "half-up" });
|
|
64112
|
+
const uncapped = iff2(le5(magi2, money35("2500000")), pct13("35"), iff2(le5(magi2, money35("5000000")), pct13("25"), iff2(le5(magi2, money35("10000000")), pct13("15"), iff2(le5(magi2, money35("12500000")), pct13("5"), money35("0")))));
|
|
63829
64113
|
const cap = iff2({ kind: "cmp", op: "eq", left: fact38("filingStatus"), right: { kind: "enum", value: "mfj" } }, money35("1000000"), money35("500000"));
|
|
63830
64114
|
return { kind: "min", args: [uncapped, cap] };
|
|
63831
64115
|
})()
|
|
@@ -64143,8 +64427,8 @@ var wiRules = [
|
|
|
64143
64427
|
formula: (() => {
|
|
64144
64428
|
const eic = { kind: "max0", arg: fact38("wiFederalEicForWi") };
|
|
64145
64429
|
const kids = fact38("wiQualifyingChildren");
|
|
64146
|
-
const
|
|
64147
|
-
return iff3({ kind: "cmp", op: "ge", left: kids, right: { kind: "int", value: "3" } },
|
|
64430
|
+
const pct13 = (num) => rd9({ kind: "mulRate", base: eic, rate: { num, den: "100" }, round: "half-up" });
|
|
64431
|
+
return iff3({ kind: "cmp", op: "ge", left: kids, right: { kind: "int", value: "3" } }, pct13("34"), iff3({ kind: "cmp", op: "eq", left: kids, right: { kind: "int", value: "2" } }, pct13("11"), iff3({ kind: "cmp", op: "eq", left: kids, right: { kind: "int", value: "1" } }, pct13("4"), money35("0"))));
|
|
64148
64432
|
})()
|
|
64149
64433
|
},
|
|
64150
64434
|
{
|
|
@@ -64482,12 +64766,12 @@ var mnRules = [
|
|
|
64482
64766
|
formula: (() => {
|
|
64483
64767
|
const total = mulInt3(money35("520000"), fact38("mnDependents"));
|
|
64484
64768
|
const threshold2 = iff4({ kind: "or", args: [isStatus12("mfj"), isStatus12("qss")] }, money35("35855000"), iff4(isStatus12("hoh"), money35("29880000"), iff4(isStatus12("mfs"), money35("17927500"), money35("23905000"))));
|
|
64485
|
-
const
|
|
64769
|
+
const excess2 = { kind: "max0", arg: sub8(fact38("mnAgi"), threshold2) };
|
|
64486
64770
|
const cutoff = iff4(isStatus12("mfs"), money35("6125000"), money35("12250000"));
|
|
64487
|
-
const stepsMfs = stepsCeil(
|
|
64488
|
-
const stepsOther = stepsCeil(
|
|
64771
|
+
const stepsMfs = stepsCeil(excess2, "125000");
|
|
64772
|
+
const stepsOther = stepsCeil(excess2, "250000");
|
|
64489
64773
|
const reduction = (steps) => mulInt3({ kind: "mulRate", base: total, rate: { num: "2", den: "100" }, round: "half-up" }, steps);
|
|
64490
|
-
return iff4(fact38("isClaimedAsDependent"), money35("0"), iff4({ kind: "cmp", op: "gt", left:
|
|
64774
|
+
return iff4(fact38("isClaimedAsDependent"), money35("0"), iff4({ kind: "cmp", op: "gt", left: excess2, right: cutoff }, money35("0"), rd10({
|
|
64491
64775
|
kind: "max0",
|
|
64492
64776
|
arg: sub8(total, iff4(isStatus12("mfs"), reduction(stepsMfs), reduction(stepsOther)))
|
|
64493
64777
|
})));
|
|
@@ -64526,8 +64810,8 @@ var mnRules = [
|
|
|
64526
64810
|
formula: (() => {
|
|
64527
64811
|
const ss2 = { kind: "max0", arg: fact38("mnTaxableSs") };
|
|
64528
64812
|
const threshold2 = iff4({ kind: "or", args: [isStatus12("mfj"), isStatus12("qss")] }, money35("10832000"), iff4(isStatus12("mfs"), money35("5416000"), money35("8449000")));
|
|
64529
|
-
const
|
|
64530
|
-
const steps = iff4(isStatus12("mfs"), stepsCeil(
|
|
64813
|
+
const excess2 = { kind: "max0", arg: sub8(fact38("mnAgi"), threshold2) };
|
|
64814
|
+
const steps = iff4(isStatus12("mfs"), stepsCeil(excess2, "200000"), stepsCeil(excess2, "400000"));
|
|
64531
64815
|
const cappedSteps = { kind: "min", args: [steps, { kind: "int", value: "10" }] };
|
|
64532
64816
|
const reduction = mulInt3({ kind: "mulRate", base: ss2, rate: { num: "10", den: "100" }, round: "half-up" }, cappedSteps);
|
|
64533
64817
|
return rd10({ kind: "max0", arg: sub8(ss2, reduction) });
|
|
@@ -64707,9 +64991,9 @@ var scRules = [
|
|
|
64707
64991
|
// $110,000
|
|
64708
64992
|
},
|
|
64709
64993
|
formula: (() => {
|
|
64710
|
-
const phased2 = (base, start,
|
|
64711
|
-
const
|
|
64712
|
-
const reductionRaw = { kind: "mulDiv", a: money35(base), b:
|
|
64994
|
+
const phased2 = (base, start, range2) => {
|
|
64995
|
+
const excess2 = { kind: "max0", arg: sub9(fact38("scAgi"), money35(start)) };
|
|
64996
|
+
const reductionRaw = { kind: "mulDiv", a: money35(base), b: excess2, c: money35(range2), round: "floor" };
|
|
64713
64997
|
const reduction10 = mulInt4(money35("1000"), { kind: "stepUnits", value: reductionRaw, unitCents: "1000", mode: "floor" });
|
|
64714
64998
|
return { kind: "max0", arg: sub9(money35(base), reduction10) };
|
|
64715
64999
|
};
|
|
@@ -64991,10 +65275,10 @@ var alRules = [
|
|
|
64991
65275
|
formula: (() => {
|
|
64992
65276
|
const agi2 = { kind: "max0", arg: fact38("alAgi") };
|
|
64993
65277
|
const chart = (max2, step, floor, start, width) => {
|
|
64994
|
-
const
|
|
65278
|
+
const excess2 = sub10(agi2, money35(start));
|
|
64995
65279
|
const steps = {
|
|
64996
65280
|
kind: "add",
|
|
64997
|
-
args: [{ kind: "stepUnits", value:
|
|
65281
|
+
args: [{ kind: "stepUnits", value: excess2, unitCents: width, mode: "floor" }, { kind: "int", value: "1" }]
|
|
64998
65282
|
};
|
|
64999
65283
|
const reduced = { kind: "max", args: [sub10(money35(max2), mulInt5(money35(step), steps)), money35(floor)] };
|
|
65000
65284
|
return iff6(lt8(agi2, money35(start)), money35(max2), reduced);
|
|
@@ -65366,8 +65650,8 @@ var orRules = [
|
|
|
65366
65650
|
formula: (() => {
|
|
65367
65651
|
const qi = fact38("orKidsQualifyingIncome");
|
|
65368
65652
|
const base = iff7({ kind: "cmp", op: "gt", left: fact38("orKidsUnder6"), right: { kind: "int", value: "5" } }, mulInt6(money35("105000"), { kind: "int", value: "5" }), mulInt6(money35("105000"), fact38("orKidsUnder6")));
|
|
65369
|
-
const
|
|
65370
|
-
const hundredths = { kind: "mulDiv", a:
|
|
65653
|
+
const excess2 = { kind: "max0", arg: sub11(qi, money35("2655000")) };
|
|
65654
|
+
const hundredths = { kind: "mulDiv", a: excess2, b: money35("100"), c: money35("500000"), round: "half-up" };
|
|
65371
65655
|
const reduction = { kind: "mulDiv", a: base, b: hundredths, c: money35("100"), round: "half-up" };
|
|
65372
65656
|
const credit = { kind: "max0", arg: sub11(base, reduction) };
|
|
65373
65657
|
return iff7({ kind: "cmp", op: "ge", left: qi, right: money35("3155000") }, money35("0"), iff7(isStatus15("mfs"), money35("0"), rd13(credit)));
|
|
@@ -65452,8 +65736,8 @@ var times = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, ro
|
|
|
65452
65736
|
var scaled = (cents) => times(money35(cents), "10000");
|
|
65453
65737
|
var dollarsFromScaled = (n) => times({ kind: "mulDiv", a: n, b: money35("1"), c: money35("1000000"), round: "half-up" }, "100");
|
|
65454
65738
|
var scaledSchedule = (base, rows) => add8(...rows.map((r, i) => {
|
|
65455
|
-
const
|
|
65456
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
65739
|
+
const excess2 = sub12(base, money35(r.thresholdCents));
|
|
65740
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max012(excess2);
|
|
65457
65741
|
return times(portion, r.rateNum);
|
|
65458
65742
|
}));
|
|
65459
65743
|
var SCHED_2025_S = [
|
|
@@ -66007,8 +66291,8 @@ var stepsOver = (agi2, startCents, unitCents, maxUnits) => {
|
|
|
66007
66291
|
var times2 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, round: "half-up" });
|
|
66008
66292
|
var dollarsFromScaled2 = (n, denCents) => times2({ kind: "mulDiv", a: n, b: money35("1"), c: money35(denCents), round: "half-up" }, "100");
|
|
66009
66293
|
var scaledSchedule2 = (base, rows) => add9(...rows.map((r, i) => {
|
|
66010
|
-
const
|
|
66011
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
66294
|
+
const excess2 = sub13(base, money35(r.thresholdCents));
|
|
66295
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max013(excess2);
|
|
66012
66296
|
return times2(portion, r.rateNum);
|
|
66013
66297
|
}));
|
|
66014
66298
|
var bands = (agi2, rows, beyond, wrap) => {
|
|
@@ -66234,15 +66518,15 @@ var tcsFor = (agi2, s, method) => {
|
|
|
66234
66518
|
const taxable3 = max013(sub13(agi2, exemptionFor(agi2, s)));
|
|
66235
66519
|
const scaledTax = scaledSchedule2(taxable3, SCHED[s]);
|
|
66236
66520
|
const cAndD = add9(addbackFor(agi2, s), recaptureFor(agi2, s));
|
|
66237
|
-
const
|
|
66521
|
+
const pct13 = creditPctFor(agi2, s);
|
|
66238
66522
|
if (method === "schedule") {
|
|
66239
66523
|
const line4 = dollarsFromScaled2(scaledTax, "1000000");
|
|
66240
66524
|
const line72 = add9(line4, cAndD);
|
|
66241
|
-
const line92 = rd15({ kind: "mulDiv", a: line72, b: mulInt8(money35("1"),
|
|
66525
|
+
const line92 = rd15({ kind: "mulDiv", a: line72, b: mulInt8(money35("1"), pct13), c: money35("100"), round: "half-up" });
|
|
66242
66526
|
return sub13(line72, line92);
|
|
66243
66527
|
}
|
|
66244
66528
|
const totalScaled = add9(scaledTax, times2(cAndD, "10000"));
|
|
66245
|
-
const keep = sub13(int5("100"),
|
|
66529
|
+
const keep = sub13(int5("100"), pct13);
|
|
66246
66530
|
const scaledAfterCredit = mulInt8(totalScaled, keep);
|
|
66247
66531
|
return dollarsFromScaled2(scaledAfterCredit, "100000000");
|
|
66248
66532
|
};
|
|
@@ -66519,8 +66803,8 @@ var isKsHoh = { kind: "or", args: [isStatus18("hoh"), isStatus18("qss")] };
|
|
|
66519
66803
|
var times3 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, round: "half-up" });
|
|
66520
66804
|
var dollarsFromScaled3 = (n, denCents) => times3({ kind: "mulDiv", a: n, b: money35("1"), c: money35(denCents), round: "half-up" }, "100");
|
|
66521
66805
|
var scaledSchedule3 = (base, rows) => add10(...rows.map((r, i) => {
|
|
66522
|
-
const
|
|
66523
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
66806
|
+
const excess2 = sub14(base, money35(r.thresholdCents));
|
|
66807
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max014(excess2);
|
|
66524
66808
|
return times3(portion, r.rateNum);
|
|
66525
66809
|
}));
|
|
66526
66810
|
var SCHED_MFJ2 = [
|
|
@@ -66992,8 +67276,8 @@ var isMfs3 = isStatus19("mfs");
|
|
|
66992
67276
|
var times4 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, round: "half-up" });
|
|
66993
67277
|
var dollarsFromScaled4 = (n, denCents) => times4({ kind: "mulDiv", a: n, b: money35("1"), c: money35(denCents), round: "half-up" }, "100");
|
|
66994
67278
|
var scaledSchedule4 = (base, rows) => add11(...rows.map((r, i) => {
|
|
66995
|
-
const
|
|
66996
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
67279
|
+
const excess2 = sub15(base, money35(r.thresholdCents));
|
|
67280
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max015(excess2);
|
|
66997
67281
|
return times4(portion, r.rateNum);
|
|
66998
67282
|
}));
|
|
66999
67283
|
var dollars3 = (d3) => money35(String(d3) + "00");
|
|
@@ -67227,8 +67511,8 @@ var arRules = [
|
|
|
67227
67511
|
const earned2 = max015(fact38("arEarnedIncome"));
|
|
67228
67512
|
const l6 = iff11(isMfj2, minE(l3, earned2, max015(fact38("arSpouseEarnedIncome"))), minE(l3, earned2));
|
|
67229
67513
|
const steps = stepUnits2(max015(sub15(fact38("arFederalAgi"), money35("1500000"))), "200000", "ceil");
|
|
67230
|
-
const
|
|
67231
|
-
const l9 = rd17({ kind: "mulDiv", a: l6, b:
|
|
67514
|
+
const pct13 = maxE(sub15(money35("35"), mulInt10(money35("1"), steps)), money35("20"));
|
|
67515
|
+
const l9 = rd17({ kind: "mulDiv", a: l6, b: pct13, c: money35("100"), round: "half-up" });
|
|
67232
67516
|
return rd17({ kind: "mulRate", base: l9, rate: { num: "20", den: "100" }, round: "half-up" });
|
|
67233
67517
|
})()
|
|
67234
67518
|
},
|
|
@@ -67442,8 +67726,8 @@ var isMfs4 = isStatus20("mfs");
|
|
|
67442
67726
|
var times5 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, round: "half-up" });
|
|
67443
67727
|
var dollarsFromScaled5 = (n, denCents) => times5({ kind: "mulDiv", a: n, b: money35("1"), c: money35(denCents), round: "half-up" }, "100");
|
|
67444
67728
|
var scaledSchedule5 = (base, rows) => add12(...rows.map((r, i) => {
|
|
67445
|
-
const
|
|
67446
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
67729
|
+
const excess2 = sub16(base, money35(r.thresholdCents));
|
|
67730
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max016(excess2);
|
|
67447
67731
|
return times5(portion, r.rateNum);
|
|
67448
67732
|
}));
|
|
67449
67733
|
var dollars4 = (d3) => money35(String(d3) + "00");
|
|
@@ -67958,8 +68242,8 @@ var times6 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, r
|
|
|
67958
68242
|
var pct4 = (base, num, den) => ({ kind: "mulRate", base, rate: { num, den }, round: "half-up" });
|
|
67959
68243
|
var dollarsFromScaled6 = (n, denCents) => times6({ kind: "mulDiv", a: n, b: money35("1"), c: money35(denCents), round: "half-up" }, "100");
|
|
67960
68244
|
var scaledSchedule6 = (base, rows) => add13(...rows.map((r, i) => {
|
|
67961
|
-
const
|
|
67962
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
68245
|
+
const excess2 = sub17(base, money35(r.thresholdCents));
|
|
68246
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max017(excess2);
|
|
67963
68247
|
return times6(portion, r.rateNum);
|
|
67964
68248
|
}));
|
|
67965
68249
|
var calcSchedule = (base, rows) => {
|
|
@@ -68860,8 +69144,8 @@ var times7 = (base, num) => ({ kind: "mulRate", base, rate: { num, den: "1" }, r
|
|
|
68860
69144
|
var pct6 = (base, num, den) => ({ kind: "mulRate", base, rate: { num, den }, round: "half-up" });
|
|
68861
69145
|
var dollarsFromScaled8 = (n) => times7({ kind: "mulDiv", a: n, b: money35("1"), c: money35("1000000"), round: "half-up" }, "100");
|
|
68862
69146
|
var scaledSchedule7 = (base, rows) => add15(...rows.map((r, i) => {
|
|
68863
|
-
const
|
|
68864
|
-
const portion = i + 1 < rows.length ? { kind: "clamp", value:
|
|
69147
|
+
const excess2 = sub19(base, money35(r.thresholdCents));
|
|
69148
|
+
const portion = i + 1 < rows.length ? { kind: "clamp", value: excess2, lo: money35("0"), hi: money35(String(BigInt(rows[i + 1].thresholdCents) - BigInt(r.thresholdCents))) } : max019(excess2);
|
|
68865
69149
|
return times7(portion, r.rateNum);
|
|
68866
69150
|
}));
|
|
68867
69151
|
var sched = (rates, mfs) => {
|
|
@@ -71109,7 +71393,7 @@ var FORMS4 = "https://revenuefiles.delaware.gov/2025/PITForms_Instructions/";
|
|
|
71109
71393
|
var INSTR_URL2 = FORMS4 + "Instructions/PIT-RES_Instructions_2025-01.pdf";
|
|
71110
71394
|
var FORM_URL2 = FORMS4 + "PIT-RES_2025-01_PaperInteractiveIPM.pdf";
|
|
71111
71395
|
var TABLE_URL = "https://revenuefiles.delaware.gov/2025/TY25_taxtable.pdf";
|
|
71112
|
-
var DELC = (
|
|
71396
|
+
var DELC = (sub28) => `https://delcode.delaware.gov/title30/c011/${sub28}/index.html`;
|
|
71113
71397
|
var deRules = [
|
|
71114
71398
|
{
|
|
71115
71399
|
id: "us.de.income_tax",
|
|
@@ -71530,8 +71814,8 @@ var ndRules = [
|
|
|
71530
71814
|
parameters: { maximumCredit: { value: "31200", type: "money" }, taxableIncomeFloor: { value: "8103600", type: "money" }, lowerIncomeFloor: { value: "4755000", type: "money" }, halfJointStandardDeduction: { value: "1575000", type: "money" } },
|
|
71531
71815
|
formula: (() => {
|
|
71532
71816
|
const eligible = and9(isStatus30("mfj"), gt13(fact38("ndTaxableIncome"), money35("8103600")), gt13(fact38("ndLowerQualifiedIncome"), money35("4755000")));
|
|
71533
|
-
const
|
|
71534
|
-
return iff21(eligible, minE11(
|
|
71817
|
+
const excess2 = max025(sub25(max025(fact38("ndJointScheduleTax")), add21(max025(fact38("ndSingleScheduleTaxA")), max025(fact38("ndSingleScheduleTaxB")))));
|
|
71818
|
+
return iff21(eligible, minE11(excess2, money35("31200")), money35("0"));
|
|
71535
71819
|
})()
|
|
71536
71820
|
},
|
|
71537
71821
|
{
|
|
@@ -72652,133 +72936,275 @@ var stateParameterRules = [
|
|
|
72652
72936
|
...otherStateRules
|
|
72653
72937
|
];
|
|
72654
72938
|
|
|
72655
|
-
// ../corpus-us-federal/dist/rules/qbi.js
|
|
72939
|
+
// ../corpus-us-federal/dist/rules/qbi-businesses.js
|
|
72940
|
+
var J29 = "us.federal";
|
|
72656
72941
|
var fact39 = (factId) => ({ kind: "fact", factId });
|
|
72657
72942
|
var money36 = (cents) => ({ kind: "money", cents });
|
|
72943
|
+
var int15 = (value) => ({ kind: "int", value });
|
|
72658
72944
|
var ruleRef33 = (ruleId) => ({ kind: "rule", ruleId });
|
|
72659
|
-
var param23 = (name) => ({ kind: "param", name });
|
|
72660
72945
|
var zero26 = money36("0");
|
|
72661
|
-
var
|
|
72662
|
-
|
|
72663
|
-
|
|
72664
|
-
|
|
72665
|
-
|
|
72666
|
-
});
|
|
72946
|
+
var add23 = (...args) => ({ kind: "add", args });
|
|
72947
|
+
var sub27 = (left, right) => ({ kind: "sub", left, right });
|
|
72948
|
+
var max027 = (arg) => ({ kind: "max0", arg });
|
|
72949
|
+
var min6 = (...args) => ({ kind: "min", args });
|
|
72950
|
+
var neg2 = (e) => sub27(zero26, e);
|
|
72951
|
+
var cmp16 = (op, left, right) => ({ kind: "cmp", op, left, right });
|
|
72952
|
+
var iff23 = (cond, then, els) => ({ kind: "if", cond, then, else: els });
|
|
72953
|
+
var and11 = (...args) => ({ kind: "and", args });
|
|
72954
|
+
var pct11 = (num, den, base) => ({ kind: "mulRate", base, rate: { num, den }, round: "half-up" });
|
|
72955
|
+
var isStatus32 = (status) => cmp16("eq", fact39("filingStatus"), { kind: "enum", value: status });
|
|
72956
|
+
var CORNELL = "https://www.law.cornell.edu/uscode/text/26/199A";
|
|
72957
|
+
var REG_1 = "https://www.law.cornell.edu/cfr/text/26/1.199A-1";
|
|
72958
|
+
var REG_4 = "https://www.law.cornell.edu/cfr/text/26/1.199A-4";
|
|
72959
|
+
var QBI_LISTED = 5;
|
|
72960
|
+
var QBI_UNITS = [
|
|
72961
|
+
{ key: "main", label: "the main business (QBI not listed separately)", w2Fact: "qbiW2Wages", ubiaFact: "qbiUBIA", sstbFact: "businessIsSSTB", groupFact: "qbiAggregationGroup" },
|
|
72962
|
+
{ key: "spouse", label: "the second spouse's Schedule C business", w2Fact: "spouseQbiW2Wages", ubiaFact: "spouseQbiUBIA", sstbFact: "spouseBusinessIsSSTB", groupFact: "spouseQbiAggregationGroup" },
|
|
72963
|
+
...Array.from({ length: QBI_LISTED }, (_, i) => {
|
|
72964
|
+
const n = i + 2;
|
|
72965
|
+
return {
|
|
72966
|
+
key: `business${n}`,
|
|
72967
|
+
label: `listed business ${n}`,
|
|
72968
|
+
w2Fact: `qbiBusiness${n}W2Wages`,
|
|
72969
|
+
ubiaFact: `qbiBusiness${n}UBIA`,
|
|
72970
|
+
sstbFact: `qbiBusiness${n}IsSSTB`,
|
|
72971
|
+
groupFact: `qbiBusiness${n}AggregationGroup`
|
|
72972
|
+
};
|
|
72973
|
+
})
|
|
72974
|
+
];
|
|
72975
|
+
var LISTED = QBI_UNITS.slice(2);
|
|
72976
|
+
var id = (u, line2) => `${J29}.qbi.${u.key}.${line2}`;
|
|
72977
|
+
var qbiOf = (u) => ruleRef33(id(u, "qbi"));
|
|
72978
|
+
var presentOf = (u) => ruleRef33(id(u, "present"));
|
|
72979
|
+
var groupOf = (u) => ruleRef33(id(u, "aggregation_group"));
|
|
72980
|
+
var excess = ruleRef33(`${J29}.qbi.excess_over_threshold`);
|
|
72981
|
+
var range = ruleRef33(`${J29}.qbi.phase_in_range`);
|
|
72982
|
+
function rule(ruleId, title, section, url2, excerpt, type, formula, source = "26 U.S.C. \xA7 199A; Form 8995-A (2025) and Schedules A\u2013C") {
|
|
72983
|
+
return {
|
|
72984
|
+
id: ruleId,
|
|
72985
|
+
version: 1,
|
|
72986
|
+
jurisdiction: J29,
|
|
72987
|
+
title,
|
|
72988
|
+
citation: { source, section, url: url2, excerpt },
|
|
72989
|
+
effectiveFrom: "2025-01-01",
|
|
72990
|
+
output: { type },
|
|
72991
|
+
formula
|
|
72992
|
+
};
|
|
72993
|
+
}
|
|
72994
|
+
var scheduleCPool = add23(max027(sub27(fact39("selfEmploymentNetProfit"), add23(ruleRef33(`${J29}.se_tax_half_deduction.taxpayer`), ruleRef33(`${J29}.sep_deduction`), ruleRef33(`${J29}.sehi_deduction`)))), fact39("k1OrdinaryBusinessIncome"));
|
|
72995
|
+
var listedProfits = add23(...LISTED.map((u) => max027(qbiOf(u))));
|
|
72996
|
+
var listedLosses = add23(...LISTED.map((u) => max027(neg2(qbiOf(u)))));
|
|
72997
|
+
var rawQbiRules = [
|
|
72998
|
+
rule(id(QBI_UNITS[0], "qbi"), "QBI of the main business: the return's Schedule C and K-1 QBI less qbiLossOffset, less every listed business", "\xA7 199A(c); Reg. \xA7 1.199A-3(b)(1)(vi)", "https://www.law.cornell.edu/cfr/text/26/1.199A-3", "QBI includes the deductible part of self-employment tax, the self-employed health insurance deduction and contributions to qualified retirement plans attributable to the trade or business. [Main = max(0, selfEmploymentNetProfit \u2212 its \xBD-SE, SEP and SE-health deductions) + k1OrdinaryBusinessIncome \u2212 qbiLossOffset, less each listed business: a listed profit comes out of the Schedule C / K-1 QBI and a listed loss out of qbiLossOffset; listing more than the return holds is refused.]", "money", iff23(cmp16("gt", listedProfits, scheduleCPool), {
|
|
72999
|
+
kind: "unsupported",
|
|
73000
|
+
reason: "the listed businesses' QBI (qbiBusiness2Income\u2013qbiBusiness6Income) is more than the return's Schedule C and K-1 QBI: a listed business must already be in the totals (selfEmploymentNetProfit or k1OrdinaryBusinessIncome)"
|
|
73001
|
+
}, iff23(cmp16("gt", listedLosses, fact39("qbiLossOffset")), {
|
|
73002
|
+
kind: "unsupported",
|
|
73003
|
+
reason: "the listed businesses' QBI losses are more than qbiLossOffset: a listed loss business's QBI loss must already be in qbiLossOffset"
|
|
73004
|
+
}, sub27(sub27(scheduleCPool, listedProfits), sub27(fact39("qbiLossOffset"), listedLosses))))),
|
|
73005
|
+
rule(id(QBI_UNITS[1], "qbi"), "QBI of the second spouse's Schedule C business (net of their own \xBD-SE deduction)", "\xA7 199A(c); Reg. \xA7 1.199A-3(b)(1)(vi)", "https://www.law.cornell.edu/cfr/text/26/1.199A-3", "QBI includes the deductible part of self-employment tax attributable to the trade or business. [On a joint return the second spouse's Schedule C is its own trade or business: their net profit less their own \xBD-SE deduction. Their SEP, solo 401(k) and SE health insurance are not modeled (those inputs are the first spouse's).]", "money", max027(sub27(ruleRef33(`${J29}.se_net_profit.spouse`), ruleRef33(`${J29}.se_tax_half_deduction.spouse`)))),
|
|
73006
|
+
...LISTED.map((u, i) => rule(id(u, "qbi"), `QBI of ${u.label} (qbiBusiness${i + 2}Income, when qbiAdditionalBusinesses \u2265 ${i + 1})`, "\xA7 199A(c)(1)", CORNELL, "The term 'qualified business income' means, for any taxable year, the net amount of qualified items of income, gain, deduction, and loss with respect to any qualified trade or business of the taxpayer. [Entered per business, a loss as a negative number; read only when the return lists at least this many businesses.]", "money", iff23(cmp16("ge", fact39("qbiAdditionalBusinesses"), int15(String(i + 1))), fact39(`qbiBusiness${i + 2}Income`), zero26))),
|
|
73007
|
+
rule(`${J29}.qbi.total`, "Total QBI of all businesses (Form 8995 line 2)", "\xA7 199A(c)", CORNELL, "Qualified business income... with respect to any qualified trade or business of the taxpayer. [The sum over every business, losses included; the prior-year carryforward is separate.]", "money", add23(...QBI_UNITS.map(qbiOf))),
|
|
73008
|
+
...QBI_UNITS.map((u, i) => rule(id(u, "present"), `Whether the return has ${u.label}`, "Reg. \xA7 1.199A-4(b)", REG_4, i === 0 ? "[The main business is present when it has QBI or a QBI loss, or above the threshold when it has W-2 wages or UBIA: a business that breaks even can still bring its W-2 wages and UBIA to an aggregation group.]" : i === 1 ? "[The second spouse's business is present when it has QBI.]" : `[A listed business is present whenever the return lists it (qbiAdditionalBusinesses \u2265 ${i - 1}), even at zero QBI: a business that breaks even can still bring its W-2 wages and UBIA to an aggregation group.]`, "bool", i === 0 ? {
|
|
73009
|
+
kind: "or",
|
|
73010
|
+
args: [
|
|
73011
|
+
cmp16("ne", qbiOf(u), zero26),
|
|
73012
|
+
and11(cmp16("gt", excess, zero26), { kind: "or", args: [cmp16("gt", fact39(u.w2Fact), zero26), cmp16("gt", fact39(u.ubiaFact), zero26)] })
|
|
73013
|
+
]
|
|
73014
|
+
} : i === 1 ? cmp16("ne", qbiOf(u), zero26) : cmp16("ge", fact39("qbiAdditionalBusinesses"), int15(String(i - 1))))),
|
|
73015
|
+
rule(`${J29}.qbi.business_count`, "Number of businesses on the return", "Reg. \xA7 1.199A-4(a)", REG_4, "[Counts the businesses present; aggregation is asked about only when there are two or more.]", "int", add23(...QBI_UNITS.map((u) => iff23(presentOf(u), int15("1"), int15("0")))))
|
|
73016
|
+
];
|
|
73017
|
+
var thresholdRules = [
|
|
73018
|
+
{
|
|
73019
|
+
id: `${J29}.qbi.threshold`,
|
|
73020
|
+
version: 1,
|
|
73021
|
+
jurisdiction: J29,
|
|
73022
|
+
title: "\xA7 199A threshold amount (TY2025)",
|
|
73023
|
+
citation: {
|
|
73024
|
+
source: "26 U.S.C. \xA7 199A(e)(2); Rev. Proc. 2024-40 \xA7 2.27",
|
|
73025
|
+
section: "\xA7 199A(e)(2)",
|
|
73026
|
+
url: CORNELL,
|
|
73027
|
+
excerpt: "Threshold amount: $394,600 married filing jointly, $197,300 for all others (including married filing separately)."
|
|
73028
|
+
},
|
|
73029
|
+
effectiveFrom: "2025-01-01",
|
|
73030
|
+
effectiveTo: "2026-01-01",
|
|
73031
|
+
output: { type: "money" },
|
|
73032
|
+
formula: iff23(isStatus32("mfj"), money36("39460000"), money36("19730000"))
|
|
73033
|
+
},
|
|
73034
|
+
{
|
|
73035
|
+
id: `${J29}.qbi.threshold`,
|
|
73036
|
+
version: 2,
|
|
73037
|
+
jurisdiction: J29,
|
|
73038
|
+
title: "\xA7 199A threshold amount (TY2026)",
|
|
73039
|
+
citation: {
|
|
73040
|
+
source: "26 U.S.C. \xA7 199A(e)(2); Rev. Proc. 2025-32 \xA7 4.26",
|
|
73041
|
+
section: "\xA7 199A(e)(2)",
|
|
73042
|
+
url: CORNELL,
|
|
73043
|
+
excerpt: "Threshold amount: $403,500 married filing jointly, $201,775 married filing separately, $201,750 for all others."
|
|
73044
|
+
},
|
|
73045
|
+
effectiveFrom: "2026-01-01",
|
|
73046
|
+
effectiveTo: "2027-01-01",
|
|
73047
|
+
output: { type: "money" },
|
|
73048
|
+
formula: {
|
|
73049
|
+
kind: "match",
|
|
73050
|
+
on: fact39("filingStatus"),
|
|
73051
|
+
cases: [
|
|
73052
|
+
{ when: "mfj", value: money36("40350000") },
|
|
73053
|
+
{ when: "mfs", value: money36("20177500") },
|
|
73054
|
+
{ when: "single", value: money36("20175000") },
|
|
73055
|
+
{ when: "hoh", value: money36("20175000") },
|
|
73056
|
+
{ when: "qss", value: money36("20175000") }
|
|
73057
|
+
]
|
|
73058
|
+
}
|
|
73059
|
+
},
|
|
73060
|
+
{
|
|
73061
|
+
id: `${J29}.qbi.phase_in_range`,
|
|
73062
|
+
version: 1,
|
|
73063
|
+
jurisdiction: J29,
|
|
73064
|
+
title: "\xA7 199A phase-in range (TY2025: $50,000, $100,000 joint)",
|
|
73065
|
+
citation: {
|
|
73066
|
+
source: "26 U.S.C. \xA7 199A(b)(3)(B), (d)(3) as enacted by Pub. L. 115-97",
|
|
73067
|
+
section: "\xA7 199A(b)(3)(B)(ii)(II)",
|
|
73068
|
+
url: CORNELL,
|
|
73069
|
+
excerpt: "Form 8995-A line 23: Phase-in range. Enter $50,000 ($100,000 if married filing jointly)."
|
|
73070
|
+
},
|
|
73071
|
+
effectiveFrom: "2025-01-01",
|
|
73072
|
+
effectiveTo: "2026-01-01",
|
|
73073
|
+
output: { type: "money" },
|
|
73074
|
+
formula: iff23(isStatus32("mfj"), money36("10000000"), money36("5000000"))
|
|
73075
|
+
},
|
|
73076
|
+
{
|
|
73077
|
+
id: `${J29}.qbi.phase_in_range`,
|
|
73078
|
+
version: 2,
|
|
73079
|
+
jurisdiction: J29,
|
|
73080
|
+
title: "\xA7 199A phase-in range (TY2026: $75,000, $150,000 joint \u2014 OBBBA \xA7 70105)",
|
|
73081
|
+
citation: {
|
|
73082
|
+
source: "26 U.S.C. \xA7 199A(b)(3)(B), (d)(3) as amended by OBBBA \xA7 70105",
|
|
73083
|
+
section: "\xA7 199A(b)(3)(B)(ii)(II)",
|
|
73084
|
+
url: CORNELL,
|
|
73085
|
+
excerpt: "For taxable years beginning after December 31, 2025, the phase-in range is $75,000 ($150,000 for a joint return)."
|
|
73086
|
+
},
|
|
73087
|
+
effectiveFrom: "2026-01-01",
|
|
73088
|
+
effectiveTo: "2027-01-01",
|
|
73089
|
+
output: { type: "money" },
|
|
73090
|
+
formula: iff23(isStatus32("mfj"), money36("15000000"), money36("7500000"))
|
|
73091
|
+
},
|
|
73092
|
+
rule(`${J29}.qbi.excess_over_threshold`, "Taxable income before the QBI deduction over the \xA7 199A threshold (Form 8995-A line 22)", "\xA7 199A(b)(3)(B)", CORNELL, "Form 8995-A Part III line 22: subtract line 21 (threshold) from line 20 (taxable income before qualified business income deduction). [Zero at or below the threshold.]", "money", max027(sub27(ruleRef33(`${J29}.taxable_income_before_qbi`), ruleRef33(`${J29}.qbi.threshold`))))
|
|
73093
|
+
];
|
|
73094
|
+
function scheduleA(u, amount) {
|
|
73095
|
+
return iff23(
|
|
73096
|
+
{ kind: "not", arg: presentOf(u) },
|
|
73097
|
+
zero26,
|
|
73098
|
+
// no business, no questions
|
|
73099
|
+
iff23(
|
|
73100
|
+
cmp16("eq", excess, zero26),
|
|
73101
|
+
amount,
|
|
73102
|
+
// at or below the threshold the SSTB rules do not apply
|
|
73103
|
+
iff23(
|
|
73104
|
+
and11(cmp16("eq", qbiOf(u), zero26), cmp16("eq", groupOf(u), int15("0"))),
|
|
73105
|
+
zero26,
|
|
73106
|
+
// breaks even and stands alone: nothing to limit, no SSTB question
|
|
73107
|
+
iff23(fact39(u.sstbFact), iff23(cmp16("ge", excess, range), zero26, { kind: "mulDiv", a: amount, b: sub27(range, excess), c: range, round: "half-up" }), amount)
|
|
73108
|
+
)
|
|
73109
|
+
)
|
|
73110
|
+
);
|
|
73111
|
+
}
|
|
73112
|
+
var scheduleALines = [
|
|
73113
|
+
{ line: "sstb_qbi", title: "QBI after the SSTB applicable percentage", amount: qbiOf, formLine: "Schedule A line 11" },
|
|
73114
|
+
{ line: "sstb_w2_wages", title: "W-2 wages after the SSTB applicable percentage", amount: (u) => fact39(u.w2Fact), formLine: "Schedule A line 12" },
|
|
73115
|
+
{ line: "sstb_ubia", title: "UBIA after the SSTB applicable percentage", amount: (u) => fact39(u.ubiaFact), formLine: "Schedule A line 13" }
|
|
73116
|
+
];
|
|
73117
|
+
var scheduleARules = QBI_UNITS.flatMap((u) => scheduleALines.map(({ line: line2, title, amount, formLine }) => rule(id(u, line2), `${title} \u2014 ${u.label} (${formLine})`, "\xA7 199A(d)(3)", CORNELL, `\xA7 199A(d)(3): a specified service trade or business is a qualified trade or business only for the applicable percentage (100% less the excess over the threshold as a percentage of the phase-in range) of its items, and not at all past the range. [${formLine}; a business that is not an SSTB, or a return at or below the threshold, keeps the full amount. Exact ratio where the form rounds the percentage.]`, "money", scheduleA(u, amount(u)))));
|
|
73118
|
+
var aggregationGroupRules = QBI_UNITS.map((u) => rule(id(u, "aggregation_group"), `Aggregation group of ${u.label} (0 = not aggregated)`, "Reg. \xA7 1.199A-4(b)(1)", REG_4, "An individual may aggregate trades or businesses if... (iii) none of the aggregated trades or businesses can be a specified service trade or business. [Asked only above the threshold, for a business on the return, when the return has two or more businesses; an SSTB in a group is refused.]", "int", iff23(and11(cmp16("gt", excess, zero26), presentOf(u), cmp16("ge", ruleRef33(`${J29}.qbi.business_count`), int15("2"))), iff23(cmp16("eq", fact39(u.groupFact), int15("0")), int15("0"), iff23(fact39(u.sstbFact), {
|
|
73119
|
+
kind: "unsupported",
|
|
73120
|
+
reason: `${u.label} is a specified service trade or business, which may not be aggregated (Reg. \xA7 1.199A-4(b)(1)(iii)): set ${u.groupFact} to 0`
|
|
73121
|
+
}, fact39(u.groupFact))), int15("0"))));
|
|
73122
|
+
function aggregated(u, idx, line2) {
|
|
73123
|
+
const own2 = ruleRef33(id(u, line2));
|
|
73124
|
+
const g = groupOf(u);
|
|
73125
|
+
const earlierInGroup = QBI_UNITS.slice(0, idx).map((v) => cmp16("eq", groupOf(v), g));
|
|
73126
|
+
const members2 = add23(...QBI_UNITS.map((v) => iff23(cmp16("eq", groupOf(v), g), ruleRef33(id(v, line2)), zero26)));
|
|
73127
|
+
return iff23(cmp16("eq", g, int15("0")), own2, earlierInGroup.length === 0 ? members2 : iff23({ kind: "or", args: earlierInGroup }, zero26, members2));
|
|
73128
|
+
}
|
|
73129
|
+
var scheduleBLines = [
|
|
73130
|
+
{ from: "sstb_qbi", line: "aggregated_qbi", what: "QBI" },
|
|
73131
|
+
{ from: "sstb_w2_wages", line: "aggregated_w2_wages", what: "W-2 wages" },
|
|
73132
|
+
{ from: "sstb_ubia", line: "aggregated_ubia", what: "UBIA" }
|
|
73133
|
+
];
|
|
73134
|
+
var scheduleBRules = QBI_UNITS.flatMap((u, idx) => scheduleBLines.map(({ from, line: line2, what }) => rule(id(u, line2), `${what} of ${u.label} after aggregation (Schedule B line 4)`, "Reg. \xA7 1.199A-4(b)(1); Schedule B (Form 8995-A) line 4", REG_4, `Schedule B line 4: total the QBI, W-2 wages and UBIA of the aggregated trades or businesses. [The group's totals sit on its first member in the order main, spouse, business2\u2013business6; the other members carry zero. A business that is not aggregated keeps its own ${what}.]`, "money", aggregated(u, idx, from))));
|
|
73135
|
+
var aggQbi = (u) => ruleRef33(id(u, "aggregated_qbi"));
|
|
73136
|
+
var nettingIncome = ruleRef33(`${J29}.qbi.loss_netting.income`);
|
|
73137
|
+
var nettingNetted = ruleRef33(`${J29}.qbi.loss_netting.netted`);
|
|
73138
|
+
var scheduleCRules = [
|
|
73139
|
+
rule(`${J29}.qbi.loss_netting.losses`, "Business losses with the prior-year carryforward (Schedule C line 3, as a positive amount)", "\xA7 199A(c)(2); Reg. \xA7 1.199A-1(d)(2)(iii)", REG_1, "Schedule C line 3: combine the negative amounts on line 1, column (a), and line 2 (qualified business net loss carryforward from prior years).", "money", add23(fact39("qbiLossCarryforward"), ...QBI_UNITS.map((u) => max027(neg2(aggQbi(u)))))),
|
|
73140
|
+
rule(`${J29}.qbi.loss_netting.income`, "Business income (Schedule C line 4)", "Reg. \xA7 1.199A-1(d)(2)(iii)(A)", REG_1, "Schedule C line 4: add the positive amounts on line 1, column (a), for all trades, businesses, or aggregations.", "money", add23(...QBI_UNITS.map((u) => max027(aggQbi(u))))),
|
|
73141
|
+
rule(`${J29}.qbi.loss_netting.netted`, "Losses netted against other businesses' income (Schedule C line 5)", "Reg. \xA7 1.199A-1(d)(2)(iii)(A)", REG_1, "Schedule C line 5: the smaller of the absolute value of line 3 or line 4.", "money", min6(ruleRef33(`${J29}.qbi.loss_netting.losses`), nettingIncome)),
|
|
73142
|
+
...QBI_UNITS.map((u) => rule(id(u, "adjusted_qbi"), `Adjusted QBI of ${u.label} after loss netting (Schedule C line 1(c))`, "Reg. \xA7 1.199A-1(d)(2)(iii)(A)", REG_1, "If the net QBI from any trade or business is negative, it is apportioned among the trades or businesses with positive QBI in proportion to their relative amounts of QBI. [Schedule C line 1(c): this business's QBI less its share of line 5; zero for a business with no QBI or a loss.]", "money", iff23(cmp16("gt", aggQbi(u), zero26), sub27(aggQbi(u), { kind: "mulDiv", a: nettingNetted, b: aggQbi(u), c: nettingIncome, round: "half-up" }), zero26)))
|
|
73143
|
+
];
|
|
73144
|
+
function component(u) {
|
|
73145
|
+
const adj = ruleRef33(id(u, "adjusted_qbi"));
|
|
73146
|
+
const tentative = pct11("20", "100", adj);
|
|
73147
|
+
const w2 = ruleRef33(id(u, "aggregated_w2_wages"));
|
|
73148
|
+
const ubia = ruleRef33(id(u, "aggregated_ubia"));
|
|
73149
|
+
const wageLimit = {
|
|
73150
|
+
// line 10: greater of 50% of W-2 wages, or 25% of W-2 wages + 2.5% of UBIA
|
|
73151
|
+
kind: "max",
|
|
73152
|
+
args: [pct11("50", "100", w2), add23(pct11("25", "100", w2), pct11("25", "1000", ubia))]
|
|
73153
|
+
};
|
|
73154
|
+
return iff23(
|
|
73155
|
+
cmp16("le", adj, zero26),
|
|
73156
|
+
zero26,
|
|
73157
|
+
// no QBI left: its W-2 wages and UBIA do not count (Schedule C instructions)
|
|
73158
|
+
iff23(
|
|
73159
|
+
cmp16("ge", excess, range),
|
|
73160
|
+
min6(tentative, wageLimit),
|
|
73161
|
+
// line 11
|
|
73162
|
+
sub27(
|
|
73163
|
+
// Part III: line 17 − (line 17 − line 18) × line 24, never below the wage limit
|
|
73164
|
+
tentative,
|
|
73165
|
+
{ kind: "mulDiv", a: max027(sub27(tentative, wageLimit)), b: excess, c: range, round: "half-up" }
|
|
73166
|
+
)
|
|
73167
|
+
)
|
|
73168
|
+
);
|
|
73169
|
+
}
|
|
73170
|
+
var partIIRules = QBI_UNITS.map((u) => rule(id(u, "component"), `QBI component of ${u.label} (Form 8995-A line 15)`, "\xA7 199A(b)(2), (b)(3)", CORNELL, "The combined qualified business income amount is the sum of the lesser of 20 percent of the taxpayer's QBI with respect to the qualified trade or business, or the greater of 50 percent of the W-2 wages, or 25 percent of the W-2 wages plus 2.5 percent of the UBIA of qualified property, with respect to the qualified trade or business. [Form 8995-A lines 3\u201313 for this business; within the phase-in range the excess of 20% of QBI over the wage limit is reduced by the excess-over-threshold fraction (Part III). Exact ratio where the form rounds the percentage.]", "money", component(u)));
|
|
73171
|
+
var totalRules = [
|
|
73172
|
+
rule(`${J29}.qbi.active_total`, "QBI from qualified trades or businesses for the $1,000 test of the \xA7 199A(i) minimum deduction", "\xA7 199A(i)(2), (d)(3)", CORNELL, "\xA7 199A(i): a taxpayer whose aggregate QBI with respect to all active qualified trades or businesses is at least $1,000. Draft 2026 Form 8995 instructions, line 16: aggregate all active qualified business income taken into account for purposes of this form. [At or below the threshold, total QBI; above it, each business after Schedule A, so an SSTB past the phase-in range is not a qualified trade or business and one within it counts at its applicable percentage. The prior-year carryforward is its own line on the form and is not active QBI of this year. Material participation is assumed \u2014 disclosed.]", "money", iff23(cmp16("eq", excess, zero26), ruleRef33(`${J29}.qbi.total`), add23(...QBI_UNITS.map((u) => ruleRef33(id(u, "sstb_qbi")))))),
|
|
73173
|
+
rule(`${J29}.qbi.total_component`, "Total QBI component (Form 8995 line 5 at or below the threshold; Form 8995-A line 16 above it)", "\xA7 199A(b)(1)\u2013(2)", CORNELL, "Form 8995: total QBI (line 2) combined with the prior-year carryforward (line 3), times 20% if more than zero. Form 8995-A line 16: add all amounts reported on line 15.", "money", iff23(cmp16("eq", excess, zero26), pct11("20", "100", max027(sub27(ruleRef33(`${J29}.qbi.total`), fact39("qbiLossCarryforward")))), add23(...QBI_UNITS.map((u) => ruleRef33(id(u, "component")))))),
|
|
73174
|
+
rule(`${J29}.qbi.loss_carryforward`, "Qualified business net loss carried to next year, as a positive amount (Form 8995 line 16; Schedule C line 6)", "\xA7 199A(c)(2)", CORNELL, "If the net amount of qualified business income from all qualified trades or businesses during any taxable year is less than zero, such amount shall be treated as a loss from a qualified trade or business in the succeeding taxable year. [Form 8995 line 16 at or below the threshold; Schedule C (Form 8995-A) line 6 above it.]", "money", iff23(cmp16("eq", excess, zero26), max027(sub27(fact39("qbiLossCarryforward"), ruleRef33(`${J29}.qbi.total`))), sub27(ruleRef33(`${J29}.qbi.loss_netting.losses`), nettingNetted)))
|
|
73175
|
+
];
|
|
73176
|
+
var qbiBusinessRules = [
|
|
73177
|
+
...rawQbiRules,
|
|
73178
|
+
...thresholdRules,
|
|
73179
|
+
...scheduleARules,
|
|
73180
|
+
...aggregationGroupRules,
|
|
73181
|
+
...scheduleBRules,
|
|
73182
|
+
...scheduleCRules,
|
|
73183
|
+
...partIIRules,
|
|
73184
|
+
...totalRules
|
|
73185
|
+
];
|
|
73186
|
+
|
|
73187
|
+
// ../corpus-us-federal/dist/rules/qbi.js
|
|
73188
|
+
var fact40 = (factId) => ({ kind: "fact", factId });
|
|
73189
|
+
var money37 = (cents) => ({ kind: "money", cents });
|
|
73190
|
+
var ruleRef34 = (ruleId) => ({ kind: "rule", ruleId });
|
|
73191
|
+
var param23 = (name) => ({ kind: "param", name });
|
|
73192
|
+
var zero27 = money37("0");
|
|
72667
73193
|
var pctOf3 = (num, den, base) => ({
|
|
72668
73194
|
kind: "mulRate",
|
|
72669
73195
|
base,
|
|
72670
73196
|
rate: { num, den },
|
|
72671
73197
|
round: "half-up"
|
|
72672
73198
|
});
|
|
72673
|
-
var qbi = {
|
|
72674
|
-
kind: "max0",
|
|
72675
|
-
arg: {
|
|
72676
|
-
kind: "sub",
|
|
72677
|
-
left: {
|
|
72678
|
-
kind: "add",
|
|
72679
|
-
args: [
|
|
72680
|
-
{
|
|
72681
|
-
kind: "max0",
|
|
72682
|
-
arg: {
|
|
72683
|
-
kind: "sub",
|
|
72684
|
-
left: ruleRef33("us.federal.se_net_profit"),
|
|
72685
|
-
right: {
|
|
72686
|
-
kind: "add",
|
|
72687
|
-
args: [
|
|
72688
|
-
ruleRef33("us.federal.se_tax_half_deduction"),
|
|
72689
|
-
ruleRef33("us.federal.sep_deduction"),
|
|
72690
|
-
ruleRef33("us.federal.sehi_deduction")
|
|
72691
|
-
]
|
|
72692
|
-
}
|
|
72693
|
-
}
|
|
72694
|
-
},
|
|
72695
|
-
fact39("k1OrdinaryBusinessIncome")
|
|
72696
|
-
]
|
|
72697
|
-
},
|
|
72698
|
-
right: fact39("qbiLossOffset")
|
|
72699
|
-
}
|
|
72700
|
-
};
|
|
72701
73199
|
var hasBusinessIncome = {
|
|
72702
73200
|
kind: "or",
|
|
72703
73201
|
args: [
|
|
72704
|
-
{ kind: "cmp", op: "gt", left:
|
|
72705
|
-
{ kind: "cmp", op: "gt", left:
|
|
73202
|
+
{ kind: "cmp", op: "gt", left: ruleRef34("us.federal.se_net_profit"), right: zero27 },
|
|
73203
|
+
{ kind: "cmp", op: "gt", left: fact40("k1OrdinaryBusinessIncome"), right: zero27 }
|
|
72706
73204
|
]
|
|
72707
73205
|
};
|
|
72708
|
-
var taxableBeforeQbi =
|
|
72709
|
-
|
|
72710
|
-
kind: "max",
|
|
72711
|
-
args: [
|
|
72712
|
-
pctOf3("50", "100", w2),
|
|
72713
|
-
{ kind: "add", args: [pctOf3("25", "100", w2), pctOf3("25", "1000", ubia)] }
|
|
72714
|
-
// 2.5%
|
|
72715
|
-
]
|
|
72716
|
-
});
|
|
72717
|
-
function phasedReduction(tentative, wageLimit, excess, band) {
|
|
72718
|
-
return {
|
|
72719
|
-
kind: "sub",
|
|
72720
|
-
left: tentative,
|
|
72721
|
-
right: {
|
|
72722
|
-
kind: "mulDiv",
|
|
72723
|
-
a: { kind: "max0", arg: { kind: "sub", left: tentative, right: wageLimit } },
|
|
72724
|
-
b: excess,
|
|
72725
|
-
c: band,
|
|
72726
|
-
round: "half-up"
|
|
72727
|
-
}
|
|
72728
|
-
};
|
|
72729
|
-
}
|
|
72730
|
-
function qbiRule(version2, effectiveFrom, effectiveTo, yearLabel, threshold2, bandSingleCents, bandJointCents, source, withMinimum) {
|
|
72731
|
-
const band = {
|
|
72732
|
-
kind: "if",
|
|
72733
|
-
cond: isStatus32("mfj"),
|
|
72734
|
-
then: param23("bandJoint"),
|
|
72735
|
-
else: param23("band")
|
|
72736
|
-
};
|
|
72737
|
-
const excess = {
|
|
72738
|
-
kind: "max0",
|
|
72739
|
-
arg: { kind: "sub", left: taxableBeforeQbi, right: threshold2 }
|
|
72740
|
-
};
|
|
72741
|
-
const excessCapped = { kind: "min", args: [excess, band] };
|
|
72742
|
-
const tentative = pctOf3("20", "100", qbi);
|
|
72743
|
-
const w2 = fact39("qbiW2Wages");
|
|
72744
|
-
const ubia = fact39("qbiUBIA");
|
|
72745
|
-
const nonSstb = {
|
|
72746
|
-
kind: "if",
|
|
72747
|
-
cond: { kind: "cmp", op: "ge", left: excess, right: band },
|
|
72748
|
-
then: { kind: "min", args: [tentative, wageLimitOf(w2, ubia)] },
|
|
72749
|
-
else: phasedReduction(tentative, wageLimitOf(w2, ubia), excessCapped, band)
|
|
72750
|
-
};
|
|
72751
|
-
const remaining = { kind: "max0", arg: { kind: "sub", left: band, right: excess } };
|
|
72752
|
-
const scale = (e) => ({
|
|
72753
|
-
kind: "mulDiv",
|
|
72754
|
-
a: e,
|
|
72755
|
-
b: remaining,
|
|
72756
|
-
c: band,
|
|
72757
|
-
round: "half-up"
|
|
72758
|
-
});
|
|
72759
|
-
const sstb = {
|
|
72760
|
-
kind: "if",
|
|
72761
|
-
cond: { kind: "cmp", op: "ge", left: excess, right: band },
|
|
72762
|
-
then: zero26,
|
|
72763
|
-
else: phasedReduction(pctOf3("20", "100", scale(qbi)), wageLimitOf(scale(w2), scale(ubia)), excessCapped, band)
|
|
72764
|
-
};
|
|
72765
|
-
const businessPart = {
|
|
72766
|
-
kind: "if",
|
|
72767
|
-
cond: { kind: "cmp", op: "eq", left: excess, right: zero26 },
|
|
72768
|
-
then: tentative,
|
|
72769
|
-
// at or below the threshold: no SSTB question, no limits
|
|
72770
|
-
else: {
|
|
72771
|
-
// two spouses' Schedule C businesses: above the threshold each business has its
|
|
72772
|
-
// own W-2/UBIA limit and SSTB status (Form 8995-A Part II, one column each)
|
|
72773
|
-
kind: "if",
|
|
72774
|
-
cond: { kind: "cmp", op: "gt", left: ruleRef33("us.federal.se_net_profit.spouse"), right: zero26 },
|
|
72775
|
-
then: {
|
|
72776
|
-
kind: "unsupported",
|
|
72777
|
-
reason: "both spouses have self-employment income and taxable income is over the \xA7 199A threshold: each business then needs its own W-2 wage/UBIA limit and SSTB test (Form 8995-A Part II), and per-business QBI is not modeled yet"
|
|
72778
|
-
},
|
|
72779
|
-
else: { kind: "if", cond: fact39("businessIsSSTB"), then: sstb, else: nonSstb }
|
|
72780
|
-
}
|
|
72781
|
-
};
|
|
73206
|
+
var taxableBeforeQbi = ruleRef34("us.federal.taxable_income_before_qbi");
|
|
73207
|
+
function qbiRule(version2, effectiveFrom, effectiveTo, yearLabel, source, withMinimum) {
|
|
72782
73208
|
const overall = pctOf3("20", "100", {
|
|
72783
73209
|
kind: "max0",
|
|
72784
73210
|
arg: {
|
|
@@ -72786,15 +73212,15 @@ function qbiRule(version2, effectiveFrom, effectiveTo, yearLabel, threshold2, ba
|
|
|
72786
73212
|
left: taxableBeforeQbi,
|
|
72787
73213
|
right: {
|
|
72788
73214
|
kind: "add",
|
|
72789
|
-
args: [
|
|
73215
|
+
args: [ruleRef34("us.federal.schedule_d.preferential_lt_gain"), fact40("qualifiedDividends")]
|
|
72790
73216
|
}
|
|
72791
73217
|
}
|
|
72792
73218
|
});
|
|
72793
|
-
const limited = { kind: "min", args: [
|
|
73219
|
+
const limited = { kind: "min", args: [ruleRef34("us.federal.qbi.total_component"), overall] };
|
|
72794
73220
|
const withFloor = withMinimum ? {
|
|
72795
73221
|
// OBBBA § 70105: $400 minimum when QBI ≥ $1,000 (TY2026+)
|
|
72796
73222
|
kind: "if",
|
|
72797
|
-
cond: { kind: "cmp", op: "ge", left: qbi, right: param23("minQbiFloor") },
|
|
73223
|
+
cond: { kind: "cmp", op: "ge", left: ruleRef34("us.federal.qbi.active_total"), right: param23("minQbiFloor") },
|
|
72798
73224
|
then: { kind: "max", args: [limited, param23("minDeduction")] },
|
|
72799
73225
|
else: limited
|
|
72800
73226
|
} : limited;
|
|
@@ -72802,91 +73228,60 @@ function qbiRule(version2, effectiveFrom, effectiveTo, yearLabel, threshold2, ba
|
|
|
72802
73228
|
id: "us.federal.qbi_deduction",
|
|
72803
73229
|
version: version2,
|
|
72804
73230
|
jurisdiction: "us.federal",
|
|
72805
|
-
title: `Qualified business income deduction (TY${yearLabel};
|
|
73231
|
+
title: `Qualified business income deduction (TY${yearLabel}; per business, with aggregation and loss netting)`,
|
|
72806
73232
|
citation: {
|
|
72807
73233
|
source: `26 U.S.C. \xA7 199A; ${source}`,
|
|
72808
73234
|
section: "\xA7 199A(a)\u2013(d)",
|
|
72809
73235
|
url: "https://www.law.cornell.edu/uscode/text/26/199A",
|
|
72810
|
-
excerpt: `
|
|
73236
|
+
excerpt: `The lesser of the combined qualified business income amount \u2014 20 percent of each business's QBI, limited above the \xA7 199A(e)(2) threshold by that business's W-2 wages and UBIA and phased in over the ${yearLabel === "2025" ? "$50,000 ($100,000 joint) range" : "OBBBA-widened $75,000 ($150,000 joint) range (\xA7 70105, taxable years after 2025)"}, after the SSTB applicable percentage, aggregation and loss netting (us.federal.qbi.total_component) \u2014 or 20 percent of taxable income (without this deduction) less net capital gain.${withMinimum ? " OBBBA \xA7 70105 $400 minimum deduction with at least $1,000 of QBI (active participation assumed \u2014 disclosed)." : ""} [No REIT/PTP component or cooperative patron reduction; W-2 wages and UBIA default to $0, which is conservative; exact ratios where Form 8995-A rounds percentages \u2014 disclosed.]`
|
|
72811
73237
|
},
|
|
72812
73238
|
effectiveFrom,
|
|
72813
73239
|
effectiveTo,
|
|
72814
73240
|
output: { type: "money" },
|
|
72815
|
-
parameters: {
|
|
72816
|
-
|
|
72817
|
-
|
|
72818
|
-
|
|
72819
|
-
|
|
72820
|
-
|
|
72821
|
-
minQbiFloor: { value: "100000", type: "money" }
|
|
72822
|
-
// $1,000
|
|
72823
|
-
} : {}
|
|
72824
|
-
},
|
|
73241
|
+
parameters: withMinimum ? {
|
|
73242
|
+
minDeduction: { value: "40000", type: "money" },
|
|
73243
|
+
// $400
|
|
73244
|
+
minQbiFloor: { value: "100000", type: "money" }
|
|
73245
|
+
// $1,000
|
|
73246
|
+
} : {},
|
|
72825
73247
|
formula: {
|
|
72826
73248
|
kind: "if",
|
|
72827
73249
|
cond: hasBusinessIncome,
|
|
72828
73250
|
then: withFloor,
|
|
72829
|
-
else:
|
|
73251
|
+
else: zero27
|
|
72830
73252
|
}
|
|
72831
73253
|
};
|
|
72832
73254
|
}
|
|
72833
73255
|
var qbiRules = [
|
|
72834
73256
|
qbiRule(
|
|
72835
|
-
|
|
72836
|
-
//
|
|
73257
|
+
13,
|
|
73258
|
+
// v11 computed one business above the threshold and refused two spouses' businesses; v13 sums each business's component (us.federal.qbi.total_component). v9 counted one self-employed person; v7 counted qualifiedDividends in the § 199A(a)(2)/(e)(3) overall limit
|
|
72837
73259
|
"2025-01-01",
|
|
72838
73260
|
"2026-01-01",
|
|
72839
73261
|
"2025",
|
|
72840
|
-
{
|
|
72841
|
-
kind: "if",
|
|
72842
|
-
cond: isStatus32("mfj"),
|
|
72843
|
-
then: money36("39460000"),
|
|
72844
|
-
// $394,600
|
|
72845
|
-
else: money36("19730000")
|
|
72846
|
-
// $197,300 (incl. MFS)
|
|
72847
|
-
},
|
|
72848
|
-
"5000000",
|
|
72849
|
-
"10000000",
|
|
72850
|
-
// $50,000 / $100,000 band (TCJA)
|
|
72851
73262
|
"Rev. Proc. 2024-40 \xA7 2.27",
|
|
72852
73263
|
false
|
|
72853
73264
|
),
|
|
72854
73265
|
qbiRule(
|
|
72855
|
-
|
|
72856
|
-
//
|
|
73266
|
+
14,
|
|
73267
|
+
// v12 computed one business above the threshold and refused two spouses' businesses; v14 sums each business's component. v10 counted one self-employed person; v8 counted qualifiedDividends in the overall limit
|
|
72857
73268
|
"2026-01-01",
|
|
72858
73269
|
"2027-01-01",
|
|
72859
73270
|
"2026",
|
|
72860
|
-
|
|
72861
|
-
kind: "match",
|
|
72862
|
-
on: fact39("filingStatus"),
|
|
72863
|
-
cases: [
|
|
72864
|
-
{ when: "mfj", value: money36("40350000") },
|
|
72865
|
-
// $403,500
|
|
72866
|
-
{ when: "mfs", value: money36("20177500") },
|
|
72867
|
-
// $201,775
|
|
72868
|
-
{ when: "single", value: money36("20175000") },
|
|
72869
|
-
// $201,750
|
|
72870
|
-
{ when: "hoh", value: money36("20175000") },
|
|
72871
|
-
{ when: "qss", value: money36("20175000") }
|
|
72872
|
-
]
|
|
72873
|
-
},
|
|
72874
|
-
"7500000",
|
|
72875
|
-
"15000000",
|
|
72876
|
-
// $75,000 / $150,000 band (OBBBA § 70105)
|
|
72877
|
-
"Rev. Proc. 2025-32 \xA7 4.26; OBBBA \xA7 70105 (band + $400 minimum)",
|
|
73271
|
+
"Rev. Proc. 2025-32 \xA7 4.26; OBBBA \xA7 70105 (range + $400 minimum)",
|
|
72878
73272
|
true
|
|
72879
|
-
)
|
|
73273
|
+
),
|
|
73274
|
+
...qbiBusinessRules
|
|
72880
73275
|
];
|
|
72881
73276
|
|
|
72882
73277
|
// ../corpus-us-federal/dist/rules/self-employment.js
|
|
72883
|
-
var
|
|
72884
|
-
var
|
|
72885
|
-
var
|
|
73278
|
+
var fact41 = (factId) => ({ kind: "fact", factId });
|
|
73279
|
+
var money38 = (cents) => ({ kind: "money", cents });
|
|
73280
|
+
var ruleRef35 = (ruleId) => ({ kind: "rule", ruleId });
|
|
72886
73281
|
var param24 = (name) => ({ kind: "param", name });
|
|
72887
|
-
var
|
|
72888
|
-
var seNetEarnings =
|
|
72889
|
-
var spouseSeNetEarnings =
|
|
73282
|
+
var zero28 = money38("0");
|
|
73283
|
+
var seNetEarnings = ruleRef35("us.federal.se_net_earnings");
|
|
73284
|
+
var spouseSeNetEarnings = ruleRef35("us.federal.se_net_earnings.spouse");
|
|
72890
73285
|
function seTaxRule(person, version2, effectiveFrom, effectiveTo, wageBaseCents, yearLabel) {
|
|
72891
73286
|
const who = person.key === "taxpayer" ? "first spouse (or the single filer): selfEmploymentNetProfit; Schedule SE line 8a uses socialSecurityWages when given, else box-1 wages" : "second self-employed spouse on a joint return: spouseSelfEmploymentNetProfit; Schedule SE line 8a uses spouseSocialSecurityWages";
|
|
72892
73287
|
const wagesNote = person.key === "taxpayer" ? "reduced by W-2 social security wages (Schedule SE line 8a = box 3; approximated by box 1 when socialSecurityWages is not supplied)" : "reduced by THIS spouse's own W-2 social security wages (Schedule SE line 8a = their box 3, spouseSocialSecurityWages)";
|
|
@@ -72930,10 +73325,10 @@ function seTaxRule(person, version2, effectiveFrom, effectiveTo, wageBaseCents,
|
|
|
72930
73325
|
formula: {
|
|
72931
73326
|
kind: "if",
|
|
72932
73327
|
cond: { kind: "cmp", op: "lt", left: person.netEarnings, right: param24("seFloor") },
|
|
72933
|
-
then:
|
|
73328
|
+
then: zero28,
|
|
72934
73329
|
else: {
|
|
72935
73330
|
kind: "if",
|
|
72936
|
-
cond:
|
|
73331
|
+
cond: fact41("useFormulaMethod"),
|
|
72937
73332
|
then: { kind: "add", args: [oasdi, medicare] },
|
|
72938
73333
|
else: {
|
|
72939
73334
|
// printed Schedule SE: lines 10 and 11 each entered in whole dollars
|
|
@@ -72954,19 +73349,19 @@ var taxpayer = {
|
|
|
72954
73349
|
kind: "if",
|
|
72955
73350
|
cond: {
|
|
72956
73351
|
kind: "or",
|
|
72957
|
-
args: [
|
|
73352
|
+
args: [fact41("socialSecurityWagesProvided"), { kind: "cmp", op: "gt", left: fact41("socialSecurityWages"), right: zero28 }]
|
|
72958
73353
|
},
|
|
72959
|
-
then:
|
|
72960
|
-
else:
|
|
73354
|
+
then: fact41("socialSecurityWages"),
|
|
73355
|
+
else: fact41("wages")
|
|
72961
73356
|
}
|
|
72962
73357
|
};
|
|
72963
73358
|
var spouse = {
|
|
72964
73359
|
key: "spouse",
|
|
72965
73360
|
netEarnings: spouseSeNetEarnings,
|
|
72966
|
-
wagesForBase:
|
|
73361
|
+
wagesForBase: fact41("spouseSocialSecurityWages")
|
|
72967
73362
|
};
|
|
72968
73363
|
function halfDeductionRule(person) {
|
|
72969
|
-
const tax =
|
|
73364
|
+
const tax = ruleRef35(`us.federal.se_tax.${person.key}`);
|
|
72970
73365
|
const half3 = { kind: "mulRate", base: tax, rate: { num: "50", den: "100" }, round: "half-up" };
|
|
72971
73366
|
return {
|
|
72972
73367
|
id: `us.federal.se_tax_half_deduction.${person.key}`,
|
|
@@ -72983,7 +73378,7 @@ function halfDeductionRule(person) {
|
|
|
72983
73378
|
output: { type: "money" },
|
|
72984
73379
|
formula: {
|
|
72985
73380
|
kind: "if",
|
|
72986
|
-
cond:
|
|
73381
|
+
cond: fact41("useFormulaMethod"),
|
|
72987
73382
|
then: half3,
|
|
72988
73383
|
else: { kind: "roundToDollar", value: half3, mode: "half-up" }
|
|
72989
73384
|
}
|
|
@@ -73007,9 +73402,9 @@ var selfEmploymentRules = [
|
|
|
73007
73402
|
formula: {
|
|
73008
73403
|
// asked only on a joint return: no other return has a second spouse's Schedule SE
|
|
73009
73404
|
kind: "if",
|
|
73010
|
-
cond: { kind: "cmp", op: "eq", left:
|
|
73011
|
-
then:
|
|
73012
|
-
else:
|
|
73405
|
+
cond: { kind: "cmp", op: "eq", left: fact41("filingStatus"), right: { kind: "enum", value: "mfj" } },
|
|
73406
|
+
then: fact41("spouseSelfEmploymentNetProfit"),
|
|
73407
|
+
else: zero28
|
|
73013
73408
|
}
|
|
73014
73409
|
},
|
|
73015
73410
|
{
|
|
@@ -73027,7 +73422,7 @@ var selfEmploymentRules = [
|
|
|
73027
73422
|
output: { type: "money" },
|
|
73028
73423
|
formula: {
|
|
73029
73424
|
kind: "add",
|
|
73030
|
-
args: [
|
|
73425
|
+
args: [fact41("selfEmploymentNetProfit"), ruleRef35("us.federal.se_net_profit.spouse")]
|
|
73031
73426
|
}
|
|
73032
73427
|
},
|
|
73033
73428
|
{
|
|
@@ -73046,7 +73441,7 @@ var selfEmploymentRules = [
|
|
|
73046
73441
|
output: { type: "money" },
|
|
73047
73442
|
formula: {
|
|
73048
73443
|
kind: "mulRate",
|
|
73049
|
-
base:
|
|
73444
|
+
base: fact41("selfEmploymentNetProfit"),
|
|
73050
73445
|
rate: { num: "9235", den: "10000" },
|
|
73051
73446
|
round: "half-up"
|
|
73052
73447
|
}
|
|
@@ -73066,7 +73461,7 @@ var selfEmploymentRules = [
|
|
|
73066
73461
|
output: { type: "money" },
|
|
73067
73462
|
formula: {
|
|
73068
73463
|
kind: "mulRate",
|
|
73069
|
-
base:
|
|
73464
|
+
base: ruleRef35("us.federal.se_net_profit.spouse"),
|
|
73070
73465
|
rate: { num: "9235", den: "10000" },
|
|
73071
73466
|
round: "half-up"
|
|
73072
73467
|
}
|
|
@@ -73095,7 +73490,7 @@ var selfEmploymentRules = [
|
|
|
73095
73490
|
output: { type: "money" },
|
|
73096
73491
|
formula: {
|
|
73097
73492
|
kind: "add",
|
|
73098
|
-
args: [
|
|
73493
|
+
args: [ruleRef35("us.federal.se_tax.taxpayer"), ruleRef35("us.federal.se_tax.spouse")]
|
|
73099
73494
|
}
|
|
73100
73495
|
},
|
|
73101
73496
|
halfDeductionRule(taxpayer),
|
|
@@ -73117,25 +73512,25 @@ var selfEmploymentRules = [
|
|
|
73117
73512
|
formula: {
|
|
73118
73513
|
kind: "add",
|
|
73119
73514
|
args: [
|
|
73120
|
-
|
|
73121
|
-
|
|
73515
|
+
ruleRef35("us.federal.se_tax_half_deduction.taxpayer"),
|
|
73516
|
+
ruleRef35("us.federal.se_tax_half_deduction.spouse")
|
|
73122
73517
|
]
|
|
73123
73518
|
}
|
|
73124
73519
|
}
|
|
73125
73520
|
];
|
|
73126
73521
|
|
|
73127
73522
|
// ../corpus-us-federal/dist/rules/senior-deduction.js
|
|
73128
|
-
var
|
|
73129
|
-
var
|
|
73130
|
-
var
|
|
73523
|
+
var fact42 = (factId) => ({ kind: "fact", factId });
|
|
73524
|
+
var money39 = (cents) => ({ kind: "money", cents });
|
|
73525
|
+
var ruleRef36 = (ruleId) => ({ kind: "rule", ruleId });
|
|
73131
73526
|
var param25 = (name) => ({ kind: "param", name });
|
|
73132
73527
|
var isStatus33 = (status) => ({
|
|
73133
73528
|
kind: "cmp",
|
|
73134
73529
|
op: "eq",
|
|
73135
|
-
left:
|
|
73530
|
+
left: fact42("filingStatus"),
|
|
73136
73531
|
right: { kind: "enum", value: status }
|
|
73137
73532
|
});
|
|
73138
|
-
var
|
|
73533
|
+
var zero29 = money39("0");
|
|
73139
73534
|
function perSeniorNet() {
|
|
73140
73535
|
return {
|
|
73141
73536
|
kind: "max0",
|
|
@@ -73148,8 +73543,8 @@ function perSeniorNet() {
|
|
|
73148
73543
|
kind: "max0",
|
|
73149
73544
|
arg: {
|
|
73150
73545
|
kind: "sub",
|
|
73151
|
-
left:
|
|
73152
|
-
right:
|
|
73546
|
+
left: ruleRef36("us.federal.agi"),
|
|
73547
|
+
right: ruleRef36("us.federal.senior_deduction.magi_threshold")
|
|
73153
73548
|
}
|
|
73154
73549
|
},
|
|
73155
73550
|
rate: { num: "6", den: "100" },
|
|
@@ -73186,17 +73581,17 @@ var seniorDeductionRules = [
|
|
|
73186
73581
|
// § 151(d)(5)(C)(v): married taxpayers must file jointly — MFS gets $0.
|
|
73187
73582
|
kind: "if",
|
|
73188
73583
|
cond: isStatus33("mfs"),
|
|
73189
|
-
then:
|
|
73584
|
+
then: zero29,
|
|
73190
73585
|
else: {
|
|
73191
73586
|
// Only compute (and only demand the threshold) when a senior exists.
|
|
73192
73587
|
kind: "if",
|
|
73193
73588
|
cond: {
|
|
73194
73589
|
kind: "or",
|
|
73195
73590
|
args: [
|
|
73196
|
-
|
|
73591
|
+
fact42("isAge65OrOlder"),
|
|
73197
73592
|
{
|
|
73198
73593
|
kind: "and",
|
|
73199
|
-
args: [isStatus33("mfj"),
|
|
73594
|
+
args: [isStatus33("mfj"), fact42("spouseIsAge65OrOlder")]
|
|
73200
73595
|
}
|
|
73201
73596
|
]
|
|
73202
73597
|
},
|
|
@@ -73208,22 +73603,22 @@ var seniorDeductionRules = [
|
|
|
73208
73603
|
args: [
|
|
73209
73604
|
{
|
|
73210
73605
|
kind: "if",
|
|
73211
|
-
cond:
|
|
73606
|
+
cond: fact42("isAge65OrOlder"),
|
|
73212
73607
|
then: perSeniorNet(),
|
|
73213
|
-
else:
|
|
73608
|
+
else: zero29
|
|
73214
73609
|
},
|
|
73215
73610
|
{
|
|
73216
73611
|
kind: "if",
|
|
73217
73612
|
cond: {
|
|
73218
73613
|
kind: "and",
|
|
73219
|
-
args: [isStatus33("mfj"),
|
|
73614
|
+
args: [isStatus33("mfj"), fact42("spouseIsAge65OrOlder")]
|
|
73220
73615
|
},
|
|
73221
73616
|
then: perSeniorNet(),
|
|
73222
|
-
else:
|
|
73617
|
+
else: zero29
|
|
73223
73618
|
}
|
|
73224
73619
|
]
|
|
73225
73620
|
},
|
|
73226
|
-
else:
|
|
73621
|
+
else: zero29
|
|
73227
73622
|
}
|
|
73228
73623
|
}
|
|
73229
73624
|
},
|
|
@@ -73243,17 +73638,17 @@ var seniorDeductionRules = [
|
|
|
73243
73638
|
output: { type: "money" },
|
|
73244
73639
|
formula: {
|
|
73245
73640
|
kind: "match",
|
|
73246
|
-
on:
|
|
73641
|
+
on: fact42("filingStatus"),
|
|
73247
73642
|
cases: [
|
|
73248
73643
|
// $150,000 only "in the case of a joint return"; QSS is not a joint
|
|
73249
73644
|
// return. MFS is excluded from the deduction entirely (never reached).
|
|
73250
|
-
{ when: "mfj", value:
|
|
73645
|
+
{ when: "mfj", value: money39("15000000") },
|
|
73251
73646
|
// $150,000
|
|
73252
|
-
{ when: "single", value:
|
|
73647
|
+
{ when: "single", value: money39("7500000") },
|
|
73253
73648
|
// $75,000
|
|
73254
|
-
{ when: "hoh", value:
|
|
73649
|
+
{ when: "hoh", value: money39("7500000") },
|
|
73255
73650
|
// $75,000
|
|
73256
|
-
{ when: "qss", value:
|
|
73651
|
+
{ when: "qss", value: money39("7500000") }
|
|
73257
73652
|
// $75,000
|
|
73258
73653
|
]
|
|
73259
73654
|
}
|
|
@@ -73261,11 +73656,11 @@ var seniorDeductionRules = [
|
|
|
73261
73656
|
];
|
|
73262
73657
|
|
|
73263
73658
|
// ../corpus-us-federal/dist/rules/social-security.js
|
|
73264
|
-
var
|
|
73265
|
-
var
|
|
73266
|
-
var
|
|
73659
|
+
var fact43 = (factId) => ({ kind: "fact", factId });
|
|
73660
|
+
var money40 = (cents) => ({ kind: "money", cents });
|
|
73661
|
+
var ruleRef37 = (ruleId) => ({ kind: "rule", ruleId });
|
|
73267
73662
|
var param26 = (name) => ({ kind: "param", name });
|
|
73268
|
-
var
|
|
73663
|
+
var pct12 = (num, base) => ({
|
|
73269
73664
|
kind: "mulRate",
|
|
73270
73665
|
base,
|
|
73271
73666
|
rate: { num, den: "100" },
|
|
@@ -73278,53 +73673,53 @@ var magiBase = {
|
|
|
73278
73673
|
left: {
|
|
73279
73674
|
kind: "add",
|
|
73280
73675
|
args: [
|
|
73281
|
-
|
|
73282
|
-
|
|
73283
|
-
|
|
73676
|
+
fact43("wages"),
|
|
73677
|
+
fact43("taxableInterest"),
|
|
73678
|
+
fact43("taxExemptInterest"),
|
|
73284
73679
|
// § 86(b)(2)(B): "increased by the amount of interest… exempt from tax"
|
|
73285
|
-
|
|
73286
|
-
|
|
73287
|
-
|
|
73288
|
-
|
|
73289
|
-
|
|
73290
|
-
|
|
73291
|
-
|
|
73292
|
-
|
|
73293
|
-
|
|
73294
|
-
|
|
73295
|
-
|
|
73296
|
-
|
|
73297
|
-
|
|
73680
|
+
ruleRef37("us.federal.schedule_d.preferential_lt_gain"),
|
|
73681
|
+
fact43("qualifiedDividends"),
|
|
73682
|
+
ruleRef37("us.federal.schedule_d.ordinary_st_gain"),
|
|
73683
|
+
fact43("ordinaryDividends"),
|
|
73684
|
+
ruleRef37("us.federal.se_net_profit"),
|
|
73685
|
+
fact43("k1OrdinaryBusinessIncome"),
|
|
73686
|
+
fact43("taxableIraDistributions"),
|
|
73687
|
+
fact43("taxablePensionsAndAnnuities"),
|
|
73688
|
+
ruleRef37("us.federal.pension.simplified_method_taxable"),
|
|
73689
|
+
fact43("unemploymentCompensation"),
|
|
73690
|
+
fact43("otherOrdinaryIncome"),
|
|
73691
|
+
fact43("scheduleENetIncome"),
|
|
73692
|
+
ruleRef37("us.federal.rental.net_income")
|
|
73298
73693
|
]
|
|
73299
73694
|
},
|
|
73300
73695
|
right: {
|
|
73301
73696
|
kind: "add",
|
|
73302
73697
|
args: [
|
|
73303
|
-
|
|
73304
|
-
|
|
73698
|
+
ruleRef37("us.federal.capital_loss_ordinary_offset"),
|
|
73699
|
+
fact43("nonpassiveScheduleELoss")
|
|
73305
73700
|
]
|
|
73306
73701
|
}
|
|
73307
73702
|
},
|
|
73308
73703
|
right: {
|
|
73309
73704
|
kind: "add",
|
|
73310
73705
|
args: [
|
|
73311
|
-
|
|
73312
|
-
|
|
73706
|
+
ruleRef37("us.federal.above_the_line_adjustments"),
|
|
73707
|
+
ruleRef37("us.federal.ira_deduction")
|
|
73313
73708
|
]
|
|
73314
73709
|
}
|
|
73315
73710
|
};
|
|
73316
|
-
var ss =
|
|
73317
|
-
var provisional = { kind: "add", args: [magiBase,
|
|
73711
|
+
var ss = fact43("socialSecurityBenefits");
|
|
73712
|
+
var provisional = { kind: "add", args: [magiBase, pct12("50", ss)] };
|
|
73318
73713
|
var isMfs10 = {
|
|
73319
73714
|
kind: "cmp",
|
|
73320
73715
|
op: "eq",
|
|
73321
|
-
left:
|
|
73716
|
+
left: fact43("filingStatus"),
|
|
73322
73717
|
right: { kind: "enum", value: "mfs" }
|
|
73323
73718
|
};
|
|
73324
73719
|
var isMfj6 = {
|
|
73325
73720
|
kind: "cmp",
|
|
73326
73721
|
op: "eq",
|
|
73327
|
-
left:
|
|
73722
|
+
left: fact43("filingStatus"),
|
|
73328
73723
|
right: { kind: "enum", value: "mfj" }
|
|
73329
73724
|
};
|
|
73330
73725
|
var byJoint = (joint, other) => ({
|
|
@@ -73365,25 +73760,25 @@ var socialSecurityRules = [
|
|
|
73365
73760
|
},
|
|
73366
73761
|
formula: {
|
|
73367
73762
|
kind: "if",
|
|
73368
|
-
cond: { kind: "cmp", op: "eq", left: ss, right:
|
|
73369
|
-
then:
|
|
73763
|
+
cond: { kind: "cmp", op: "eq", left: ss, right: money40("0") },
|
|
73764
|
+
then: money40("0"),
|
|
73370
73765
|
else: {
|
|
73371
73766
|
kind: "if",
|
|
73372
73767
|
// § 86(c)(1)(C)(ii): the $0 base applies to an MFS filer who did NOT live apart from the
|
|
73373
73768
|
// spouse at all times during the year; one who did is treated as unmarried ($25,000/$34,000)
|
|
73374
|
-
cond: { kind: "and", args: [isMfs10, { kind: "not", arg:
|
|
73769
|
+
cond: { kind: "and", args: [isMfs10, { kind: "not", arg: fact43("mfsLivedApartAllYear") }] },
|
|
73375
73770
|
then: {
|
|
73376
73771
|
kind: "min",
|
|
73377
|
-
args: [
|
|
73772
|
+
args: [pct12("85", ss), pct12("85", { kind: "max0", arg: provisional })]
|
|
73378
73773
|
},
|
|
73379
73774
|
else: {
|
|
73380
73775
|
kind: "min",
|
|
73381
73776
|
args: [
|
|
73382
|
-
|
|
73777
|
+
pct12("85", ss),
|
|
73383
73778
|
{
|
|
73384
73779
|
kind: "add",
|
|
73385
73780
|
args: [
|
|
73386
|
-
|
|
73781
|
+
pct12("85", {
|
|
73387
73782
|
kind: "max0",
|
|
73388
73783
|
arg: {
|
|
73389
73784
|
kind: "sub",
|
|
@@ -73397,8 +73792,8 @@ var socialSecurityRules = [
|
|
|
73397
73792
|
{
|
|
73398
73793
|
kind: "min",
|
|
73399
73794
|
args: [
|
|
73400
|
-
|
|
73401
|
-
|
|
73795
|
+
pct12("50", ss),
|
|
73796
|
+
pct12("50", {
|
|
73402
73797
|
kind: "max0",
|
|
73403
73798
|
arg: {
|
|
73404
73799
|
kind: "sub",
|
|
@@ -73421,14 +73816,14 @@ var socialSecurityRules = [
|
|
|
73421
73816
|
];
|
|
73422
73817
|
|
|
73423
73818
|
// ../corpus-us-federal/dist/rules/standard-deduction.js
|
|
73424
|
-
var
|
|
73425
|
-
var
|
|
73426
|
-
var
|
|
73427
|
-
var
|
|
73819
|
+
var J30 = "us.federal";
|
|
73820
|
+
var fact44 = (factId) => ({ kind: "fact", factId });
|
|
73821
|
+
var money41 = (cents) => ({ kind: "money", cents });
|
|
73822
|
+
var ruleRef38 = (ruleId) => ({ kind: "rule", ruleId });
|
|
73428
73823
|
var isStatus34 = (status) => ({
|
|
73429
73824
|
kind: "cmp",
|
|
73430
73825
|
op: "eq",
|
|
73431
|
-
left:
|
|
73826
|
+
left: fact44("filingStatus"),
|
|
73432
73827
|
right: { kind: "enum", value: status }
|
|
73433
73828
|
});
|
|
73434
73829
|
var standardDeductionRules = [
|
|
@@ -73436,7 +73831,7 @@ var standardDeductionRules = [
|
|
|
73436
73831
|
id: "us.federal.standard_deduction.base_amount",
|
|
73437
73832
|
version: 2,
|
|
73438
73833
|
// v1 held pre-OBBBA Rev. Proc. 2024-40 amounts ($15,000/$30,000/$22,500)
|
|
73439
|
-
jurisdiction:
|
|
73834
|
+
jurisdiction: J30,
|
|
73440
73835
|
title: "Basic standard deduction amount by filing status (TY2025, as amended by OBBBA)",
|
|
73441
73836
|
citation: {
|
|
73442
73837
|
source: "26 U.S.C. \xA7 63(c), as amended by Pub. L. 119-21 (OBBBA) \xA7 70102",
|
|
@@ -73449,17 +73844,17 @@ var standardDeductionRules = [
|
|
|
73449
73844
|
output: { type: "money" },
|
|
73450
73845
|
formula: {
|
|
73451
73846
|
kind: "match",
|
|
73452
|
-
on:
|
|
73847
|
+
on: fact44("filingStatus"),
|
|
73453
73848
|
cases: [
|
|
73454
|
-
{ when: "single", value:
|
|
73849
|
+
{ when: "single", value: money41("1575000") },
|
|
73455
73850
|
// $15,750
|
|
73456
|
-
{ when: "mfs", value:
|
|
73851
|
+
{ when: "mfs", value: money41("1575000") },
|
|
73457
73852
|
// $15,750 (same as single)
|
|
73458
|
-
{ when: "mfj", value:
|
|
73853
|
+
{ when: "mfj", value: money41("3150000") },
|
|
73459
73854
|
// $31,500
|
|
73460
|
-
{ when: "qss", value:
|
|
73855
|
+
{ when: "qss", value: money41("3150000") },
|
|
73461
73856
|
// $31,500 (§ 1(j)(2)(A): "…and Surviving Spouses")
|
|
73462
|
-
{ when: "hoh", value:
|
|
73857
|
+
{ when: "hoh", value: money41("2362500") }
|
|
73463
73858
|
// $23,625
|
|
73464
73859
|
]
|
|
73465
73860
|
}
|
|
@@ -73467,7 +73862,7 @@ var standardDeductionRules = [
|
|
|
73467
73862
|
{
|
|
73468
73863
|
id: "us.federal.standard_deduction.base_amount",
|
|
73469
73864
|
version: 3,
|
|
73470
|
-
jurisdiction:
|
|
73865
|
+
jurisdiction: J30,
|
|
73471
73866
|
title: "Basic standard deduction amount by filing status (TY2026)",
|
|
73472
73867
|
citation: {
|
|
73473
73868
|
source: "26 U.S.C. \xA7 63(c); Rev. Proc. 2025-32",
|
|
@@ -73480,17 +73875,17 @@ var standardDeductionRules = [
|
|
|
73480
73875
|
output: { type: "money" },
|
|
73481
73876
|
formula: {
|
|
73482
73877
|
kind: "match",
|
|
73483
|
-
on:
|
|
73878
|
+
on: fact44("filingStatus"),
|
|
73484
73879
|
cases: [
|
|
73485
|
-
{ when: "single", value:
|
|
73880
|
+
{ when: "single", value: money41("1610000") },
|
|
73486
73881
|
// $16,100
|
|
73487
|
-
{ when: "mfs", value:
|
|
73882
|
+
{ when: "mfs", value: money41("1610000") },
|
|
73488
73883
|
// $16,100 ("single or married filing separately")
|
|
73489
|
-
{ when: "mfj", value:
|
|
73884
|
+
{ when: "mfj", value: money41("3220000") },
|
|
73490
73885
|
// $32,200
|
|
73491
|
-
{ when: "qss", value:
|
|
73886
|
+
{ when: "qss", value: money41("3220000") },
|
|
73492
73887
|
// $32,200 (surviving spouse)
|
|
73493
|
-
{ when: "hoh", value:
|
|
73888
|
+
{ when: "hoh", value: money41("2415000") }
|
|
73494
73889
|
// $24,150
|
|
73495
73890
|
]
|
|
73496
73891
|
}
|
|
@@ -73498,7 +73893,7 @@ var standardDeductionRules = [
|
|
|
73498
73893
|
{
|
|
73499
73894
|
id: "us.federal.standard_deduction.base",
|
|
73500
73895
|
version: 1,
|
|
73501
|
-
jurisdiction:
|
|
73896
|
+
jurisdiction: J30,
|
|
73502
73897
|
title: "Basic standard deduction",
|
|
73503
73898
|
citation: {
|
|
73504
73899
|
source: "26 U.S.C. \xA7 63(c)(2)",
|
|
@@ -73509,12 +73904,12 @@ var standardDeductionRules = [
|
|
|
73509
73904
|
effectiveFrom: "2025-01-01",
|
|
73510
73905
|
// structural: open-ended
|
|
73511
73906
|
output: { type: "money" },
|
|
73512
|
-
formula:
|
|
73907
|
+
formula: ruleRef38("us.federal.standard_deduction.base_amount")
|
|
73513
73908
|
},
|
|
73514
73909
|
{
|
|
73515
73910
|
id: "us.federal.standard_deduction.dependent_limit",
|
|
73516
73911
|
version: 1,
|
|
73517
|
-
jurisdiction:
|
|
73912
|
+
jurisdiction: J30,
|
|
73518
73913
|
title: "Limitation on basic standard deduction of a dependent",
|
|
73519
73914
|
citation: {
|
|
73520
73915
|
source: "26 U.S.C. \xA7 63(c)(5); Rev. Proc. 2024-40 \xA7 2.15(2); Rev. Proc. 2025-32 \xA7 4.14(2)",
|
|
@@ -73526,19 +73921,19 @@ var standardDeductionRules = [
|
|
|
73526
73921
|
effectiveTo: "2027-01-01",
|
|
73527
73922
|
// same dollar amounts apply in 2025 and 2026
|
|
73528
73923
|
output: { type: "money" },
|
|
73529
|
-
applicability:
|
|
73924
|
+
applicability: fact44("isClaimedAsDependent"),
|
|
73530
73925
|
// min(normal base amount, max($1,350, earned income + $450))
|
|
73531
73926
|
// simplified: earned income approximated as wages
|
|
73532
73927
|
formula: {
|
|
73533
73928
|
kind: "min",
|
|
73534
73929
|
args: [
|
|
73535
|
-
|
|
73930
|
+
ruleRef38("us.federal.standard_deduction.base_amount"),
|
|
73536
73931
|
{
|
|
73537
73932
|
kind: "max",
|
|
73538
73933
|
args: [
|
|
73539
|
-
|
|
73934
|
+
money41("135000"),
|
|
73540
73935
|
// $1,350
|
|
73541
|
-
{ kind: "add", args: [
|
|
73936
|
+
{ kind: "add", args: [fact44("wages"), money41("45000")] }
|
|
73542
73937
|
// + $450
|
|
73543
73938
|
]
|
|
73544
73939
|
}
|
|
@@ -73549,7 +73944,7 @@ var standardDeductionRules = [
|
|
|
73549
73944
|
{
|
|
73550
73945
|
id: "us.federal.standard_deduction.mfs_spouse_itemizes",
|
|
73551
73946
|
version: 1,
|
|
73552
|
-
jurisdiction:
|
|
73947
|
+
jurisdiction: J30,
|
|
73553
73948
|
title: "MFS standard deduction is zero when the spouse itemizes",
|
|
73554
73949
|
citation: {
|
|
73555
73950
|
source: "26 U.S.C. \xA7 63(c)(6)(A)",
|
|
@@ -73565,10 +73960,10 @@ var standardDeductionRules = [
|
|
|
73565
73960
|
applicability: {
|
|
73566
73961
|
kind: "if",
|
|
73567
73962
|
cond: isStatus34("mfs"),
|
|
73568
|
-
then:
|
|
73963
|
+
then: fact44("spouseItemizes"),
|
|
73569
73964
|
else: { kind: "bool", value: false }
|
|
73570
73965
|
},
|
|
73571
|
-
formula:
|
|
73966
|
+
formula: money41("0"),
|
|
73572
73967
|
// § 63(c)(6) zeroes the ENTIRE standard deduction (basic + additional),
|
|
73573
73968
|
// so this overrides the sum rule, not just the basic component.
|
|
73574
73969
|
overrides: { ruleId: "us.federal.standard_deduction", priority: 10 }
|
|
@@ -73588,7 +73983,7 @@ var standardDeductionRules = [
|
|
|
73588
73983
|
{
|
|
73589
73984
|
id: "us.federal.standard_deduction",
|
|
73590
73985
|
version: 1,
|
|
73591
|
-
jurisdiction:
|
|
73986
|
+
jurisdiction: J30,
|
|
73592
73987
|
title: "Standard deduction",
|
|
73593
73988
|
citation: {
|
|
73594
73989
|
source: "26 U.S.C. \xA7 63(c)(1)",
|
|
@@ -73602,8 +73997,8 @@ var standardDeductionRules = [
|
|
|
73602
73997
|
formula: {
|
|
73603
73998
|
kind: "add",
|
|
73604
73999
|
args: [
|
|
73605
|
-
|
|
73606
|
-
|
|
74000
|
+
ruleRef38("us.federal.standard_deduction.base"),
|
|
74001
|
+
ruleRef38("us.federal.standard_deduction.additional")
|
|
73607
74002
|
]
|
|
73608
74003
|
}
|
|
73609
74004
|
}
|
|
@@ -73611,7 +74006,7 @@ var standardDeductionRules = [
|
|
|
73611
74006
|
function additionalRule(version2, effectiveFrom, effectiveTo, marriedCents, unmarriedCents, label) {
|
|
73612
74007
|
const perStatusAmount = {
|
|
73613
74008
|
kind: "match",
|
|
73614
|
-
on:
|
|
74009
|
+
on: fact44("filingStatus"),
|
|
73615
74010
|
cases: [
|
|
73616
74011
|
// the higher amount is for "unmarried AND not a surviving spouse" —
|
|
73617
74012
|
// MFS and QSS get the married amount (read from both Rev. Procs.)
|
|
@@ -73626,12 +74021,12 @@ function additionalRule(version2, effectiveFrom, effectiveTo, marriedCents, unma
|
|
|
73626
74021
|
kind: "if",
|
|
73627
74022
|
cond,
|
|
73628
74023
|
then: perStatusAmount,
|
|
73629
|
-
else:
|
|
74024
|
+
else: money41("0")
|
|
73630
74025
|
});
|
|
73631
74026
|
return {
|
|
73632
74027
|
id: "us.federal.standard_deduction.additional",
|
|
73633
74028
|
version: version2,
|
|
73634
|
-
jurisdiction:
|
|
74029
|
+
jurisdiction: J30,
|
|
73635
74030
|
title: `Additional standard deduction for the aged and blind (TY${label.year})`,
|
|
73636
74031
|
citation: {
|
|
73637
74032
|
source: `26 U.S.C. \xA7 63(f); ${label.sourceRevProc}`,
|
|
@@ -73649,15 +74044,15 @@ function additionalRule(version2, effectiveFrom, effectiveTo, marriedCents, unma
|
|
|
73649
74044
|
formula: {
|
|
73650
74045
|
kind: "add",
|
|
73651
74046
|
args: [
|
|
73652
|
-
addIf(
|
|
73653
|
-
addIf(
|
|
74047
|
+
addIf(fact44("isAge65OrOlder")),
|
|
74048
|
+
addIf(fact44("isBlind")),
|
|
73654
74049
|
addIf({
|
|
73655
74050
|
kind: "and",
|
|
73656
|
-
args: [isStatus34("mfj"),
|
|
74051
|
+
args: [isStatus34("mfj"), fact44("spouseIsAge65OrOlder")]
|
|
73657
74052
|
}),
|
|
73658
74053
|
addIf({
|
|
73659
74054
|
kind: "and",
|
|
73660
|
-
args: [isStatus34("mfj"),
|
|
74055
|
+
args: [isStatus34("mfj"), fact44("spouseIsBlind")]
|
|
73661
74056
|
})
|
|
73662
74057
|
]
|
|
73663
74058
|
}
|
|
@@ -73665,12 +74060,12 @@ function additionalRule(version2, effectiveFrom, effectiveTo, marriedCents, unma
|
|
|
73665
74060
|
}
|
|
73666
74061
|
|
|
73667
74062
|
// ../corpus-us-federal/dist/rules/tips-eligibility.js
|
|
73668
|
-
var
|
|
74063
|
+
var fact45 = (factId) => ({ kind: "fact", factId });
|
|
73669
74064
|
var boolLit = (value) => ({ kind: "bool", value });
|
|
73670
74065
|
var isStatus35 = (status) => ({
|
|
73671
74066
|
kind: "cmp",
|
|
73672
74067
|
op: "eq",
|
|
73673
|
-
left:
|
|
74068
|
+
left: fact45("filingStatus"),
|
|
73674
74069
|
right: { kind: "enum", value: status }
|
|
73675
74070
|
});
|
|
73676
74071
|
var WINDOW = { effectiveFrom: "2025-01-01", effectiveTo: "2029-01-01" };
|
|
@@ -73690,7 +74085,7 @@ var tipsEligibilityRules = [
|
|
|
73690
74085
|
output: { type: "bool" },
|
|
73691
74086
|
formula: {
|
|
73692
74087
|
kind: "match",
|
|
73693
|
-
on:
|
|
74088
|
+
on: fact45("occupation"),
|
|
73694
74089
|
cases: [
|
|
73695
74090
|
...TIPPED_OCCUPATIONS.map((o) => ({ when: o.slug, value: boolLit(true) })),
|
|
73696
74091
|
{ when: "other", value: boolLit(false) }
|
|
@@ -73717,23 +74112,23 @@ var tipsEligibilityRules = [
|
|
|
73717
74112
|
args: [
|
|
73718
74113
|
{ kind: "not", arg: isStatus35("mfs") },
|
|
73719
74114
|
{ kind: "rule", ruleId: "us.federal.eligible.tips_occupation" },
|
|
73720
|
-
|
|
73721
|
-
{ kind: "not", arg:
|
|
74115
|
+
fact45("tipsWereVoluntary"),
|
|
74116
|
+
{ kind: "not", arg: fact45("employerIsSSTB") }
|
|
73722
74117
|
]
|
|
73723
74118
|
}
|
|
73724
74119
|
}
|
|
73725
74120
|
];
|
|
73726
74121
|
|
|
73727
74122
|
// ../corpus-us-federal/dist/rules/tips-overtime.js
|
|
73728
|
-
var
|
|
73729
|
-
var
|
|
73730
|
-
var
|
|
74123
|
+
var fact46 = (factId) => ({ kind: "fact", factId });
|
|
74124
|
+
var money42 = (cents) => ({ kind: "money", cents });
|
|
74125
|
+
var ruleRef39 = (ruleId) => ({ kind: "rule", ruleId });
|
|
73731
74126
|
var param27 = (name) => ({ kind: "param", name });
|
|
73732
|
-
var
|
|
74127
|
+
var zero30 = money42("0");
|
|
73733
74128
|
var isStatus36 = (status) => ({
|
|
73734
74129
|
kind: "cmp",
|
|
73735
74130
|
op: "eq",
|
|
73736
|
-
left:
|
|
74131
|
+
left: fact46("filingStatus"),
|
|
73737
74132
|
right: { kind: "enum", value: status }
|
|
73738
74133
|
});
|
|
73739
74134
|
function cappedPhasedDeduction(qualifiedFactId, cap, ineligible = isStatus36("mfs")) {
|
|
@@ -73741,22 +74136,22 @@ function cappedPhasedDeduction(qualifiedFactId, cap, ineligible = isStatus36("mf
|
|
|
73741
74136
|
kind: "if",
|
|
73742
74137
|
// LAZY FIRST: with no qualified amount, no eligibility facts are ever
|
|
73743
74138
|
// demanded — a taxpayer without tips is never asked their occupation
|
|
73744
|
-
cond: { kind: "cmp", op: "gt", left:
|
|
74139
|
+
cond: { kind: "cmp", op: "gt", left: fact46(qualifiedFactId), right: zero30 },
|
|
73745
74140
|
then: {
|
|
73746
74141
|
kind: "if",
|
|
73747
74142
|
cond: ineligible,
|
|
73748
|
-
then:
|
|
74143
|
+
then: zero30,
|
|
73749
74144
|
else: {
|
|
73750
74145
|
kind: "max0",
|
|
73751
74146
|
arg: {
|
|
73752
74147
|
kind: "sub",
|
|
73753
74148
|
left: {
|
|
73754
74149
|
kind: "min",
|
|
73755
|
-
args: [
|
|
74150
|
+
args: [fact46(qualifiedFactId), cap]
|
|
73756
74151
|
},
|
|
73757
74152
|
right: {
|
|
73758
74153
|
kind: "mulInt",
|
|
73759
|
-
base:
|
|
74154
|
+
base: money42("10000"),
|
|
73760
74155
|
// $100 per step
|
|
73761
74156
|
count: {
|
|
73762
74157
|
kind: "stepUnits",
|
|
@@ -73764,7 +74159,7 @@ function cappedPhasedDeduction(qualifiedFactId, cap, ineligible = isStatus36("mf
|
|
|
73764
74159
|
kind: "max0",
|
|
73765
74160
|
arg: {
|
|
73766
74161
|
kind: "sub",
|
|
73767
|
-
left:
|
|
74162
|
+
left: ruleRef39("us.federal.agi"),
|
|
73768
74163
|
right: {
|
|
73769
74164
|
kind: "if",
|
|
73770
74165
|
cond: isStatus36("mfj"),
|
|
@@ -73782,7 +74177,7 @@ function cappedPhasedDeduction(qualifiedFactId, cap, ineligible = isStatus36("mf
|
|
|
73782
74177
|
}
|
|
73783
74178
|
}
|
|
73784
74179
|
},
|
|
73785
|
-
else:
|
|
74180
|
+
else: zero30
|
|
73786
74181
|
};
|
|
73787
74182
|
}
|
|
73788
74183
|
var WINDOW2 = { effectiveFrom: "2025-01-01", effectiveTo: "2029-01-01" };
|
|
@@ -73849,7 +74244,7 @@ var tipsOvertimeRules = [
|
|
|
73849
74244
|
// ../corpus-us-federal/dist/index.js
|
|
73850
74245
|
var corpusInput = {
|
|
73851
74246
|
name: "@invaro/opentax-corpus-us-federal",
|
|
73852
|
-
version: "0.
|
|
74247
|
+
version: "0.43.0",
|
|
73853
74248
|
rules: [
|
|
73854
74249
|
...corporateRules,
|
|
73855
74250
|
...corporate1120Rules,
|
|
@@ -74013,8 +74408,8 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74013
74408
|
const notes = [];
|
|
74014
74409
|
const missing = [];
|
|
74015
74410
|
const unsupported = [];
|
|
74016
|
-
const
|
|
74017
|
-
sums[
|
|
74411
|
+
const add24 = (id2, c2) => {
|
|
74412
|
+
sums[id2] = (sums[id2] ?? 0n) + c2;
|
|
74018
74413
|
};
|
|
74019
74414
|
const born65Cutoff = (dobStr) => ageAtYearEnd(dobStr, taxYear) >= 65;
|
|
74020
74415
|
if (docs.taxpayerDateOfBirth) {
|
|
@@ -74042,7 +74437,7 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74042
74437
|
if (allTagged) {
|
|
74043
74438
|
const own2 = w2s.filter((w) => w.recipient === earner);
|
|
74044
74439
|
const ssw = own2.reduce((t, w) => t + toCents(w.box3 ?? w.box1), 0n);
|
|
74045
|
-
|
|
74440
|
+
add24("socialSecurityWages", ssw);
|
|
74046
74441
|
bools.socialSecurityWagesProvided = true;
|
|
74047
74442
|
notes.push(`Schedule SE line 8a: ${own2.length} W-2(s) belong to the ${earner} (the SE earner) \u2014 social security wages $${dollars5(ssw)} coordinate the OASDI wage base${own2.some((w) => w.box3 === void 0) ? " (box 1 used where box 3 was not transcribed)" : ""}; the other spouse's W-2 does not`);
|
|
74048
74443
|
} else if (joint || multiW2) {
|
|
@@ -74054,10 +74449,10 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74054
74449
|
let w2Box1Cents = (docs.w2s ?? []).length ? 0n : void 0;
|
|
74055
74450
|
let ssTaxWithheld = 0n;
|
|
74056
74451
|
for (const [i, w] of (docs.w2s ?? []).entries()) {
|
|
74057
|
-
|
|
74452
|
+
add24("wages", toCents(w.box1));
|
|
74058
74453
|
w2Box1Cents = (w2Box1Cents ?? 0n) + toCents(w.box1);
|
|
74059
74454
|
if (w.box2 !== void 0)
|
|
74060
|
-
|
|
74455
|
+
add24("federalTaxWithheld", toCents(w.box2));
|
|
74061
74456
|
else {
|
|
74062
74457
|
missing.push(`documents.w2s[${i}].box2`);
|
|
74063
74458
|
notes.push(`W-2 #${i + 1}: box 2 NOT transcribed \u2014 federal income tax withheld treated as $0 for this W-2; pass box2 (0 if the box is blank) to confirm, or set strict: true to refuse instead`);
|
|
@@ -74065,19 +74460,19 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74065
74460
|
if (w.box4 !== void 0)
|
|
74066
74461
|
ssTaxWithheld += toCents(w.box4);
|
|
74067
74462
|
if (w.box3 !== void 0 && !multiW2 && !allTagged && !joint && !ctx.socialSecurityWagesSupplied) {
|
|
74068
|
-
|
|
74463
|
+
add24("socialSecurityWages", toCents(w.box3));
|
|
74069
74464
|
if (hasSE)
|
|
74070
74465
|
bools.socialSecurityWagesProvided = true;
|
|
74071
74466
|
}
|
|
74072
74467
|
if (w.box5 !== void 0) {
|
|
74073
74468
|
const b5 = toCents(w.box5);
|
|
74074
|
-
|
|
74469
|
+
add24("medicareWages", b5);
|
|
74075
74470
|
if (w.box6 !== void 0 && b5 > 20000000n) {
|
|
74076
74471
|
const regular = (b5 * 145n + 5000n) / 10000n;
|
|
74077
|
-
const
|
|
74078
|
-
if (
|
|
74079
|
-
|
|
74080
|
-
notes.push(`W-2 #${i + 1}: Form 8959 Part IV \u2014 box 6 exceeds 1.45% of box 5 by $${dollars5(
|
|
74472
|
+
const excess2 = toCents(w.box6) - regular;
|
|
74473
|
+
if (excess2 > 0n) {
|
|
74474
|
+
add24("federalTaxWithheld", excess2);
|
|
74475
|
+
notes.push(`W-2 #${i + 1}: Form 8959 Part IV \u2014 box 6 exceeds 1.45% of box 5 by $${dollars5(excess2)}; added to withholding`);
|
|
74081
74476
|
}
|
|
74082
74477
|
}
|
|
74083
74478
|
}
|
|
@@ -74102,9 +74497,9 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74102
74497
|
for (const [who, p] of byPerson) {
|
|
74103
74498
|
if (p.n < 2 || max2 === void 0 || p.withheld <= max2)
|
|
74104
74499
|
continue;
|
|
74105
|
-
const
|
|
74106
|
-
excessTotal +=
|
|
74107
|
-
notes.push(`W-2 box 4 total $${dollars5(p.withheld)} across ${p.n} employers (${who}) exceeds the ${taxYear} maximum $${dollars5(max2)} by $${dollars5(
|
|
74500
|
+
const excess2 = p.withheld - max2;
|
|
74501
|
+
excessTotal += excess2;
|
|
74502
|
+
notes.push(`W-2 box 4 total $${dollars5(p.withheld)} across ${p.n} employers (${who}) exceeds the ${taxYear} maximum $${dollars5(max2)} by $${dollars5(excess2)} \u2014 the Schedule 3 line 11 excess social security withholding credit is NOT computed by this engine; the completed return must claim it (see \`incomplete\`)`);
|
|
74108
74503
|
}
|
|
74109
74504
|
if (excessTotal > 0n) {
|
|
74110
74505
|
unsupported.push({
|
|
@@ -74127,7 +74522,7 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74127
74522
|
const PENALTY_EXEMPT_CODES = /* @__PURE__ */ new Set(["2", "3", "4", "7", "G", "H", "Q", "T", "C"]);
|
|
74128
74523
|
for (const [i, r] of (docs.f1099rs ?? []).entries()) {
|
|
74129
74524
|
if (r.box4 !== void 0)
|
|
74130
|
-
|
|
74525
|
+
add24("federalTaxWithheld", toCents(r.box4));
|
|
74131
74526
|
const taxable3 = toCents(r.box2a);
|
|
74132
74527
|
if (r.rolledOver || r.box7.toUpperCase().includes("G") && taxable3 === 0n) {
|
|
74133
74528
|
notes.push(`1099-R #${i + 1}: treated as ROLLOVER (${r.rolledOver ? "interview-confirmed" : "code G"}) \u2014 gross on 4a/5a only, $0 taxable`);
|
|
@@ -74137,65 +74532,65 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74137
74532
|
notes.push(`1099-R #${i + 1}: code G with box 2a $${dollars5(taxable3)} \u2014 a direct rollover to a ROTH (conversion): box 2a is taxable on line ${r.iraSepSimple ? "4b" : "5b"}, the balance is the rollover`);
|
|
74138
74533
|
}
|
|
74139
74534
|
if (r.disabilityBeforeRetirementAge) {
|
|
74140
|
-
|
|
74141
|
-
|
|
74535
|
+
add24("wages", taxable3);
|
|
74536
|
+
add24("scheduleRDisabilityIncome", taxable3);
|
|
74142
74537
|
notes.push(`1099-R #${i + 1}: code-3 disability before minimum retirement age \u2014 $${dollars5(taxable3)} reported as WAGES (Pub. 525, Form 1040 line 1h \u2014 NOT line 1a, which is W-2 box 1 only) and counted as \xA7 22 disability income`);
|
|
74143
74538
|
continue;
|
|
74144
74539
|
}
|
|
74145
74540
|
if (r.iraSepSimple)
|
|
74146
|
-
|
|
74541
|
+
add24("taxableIraDistributions", taxable3);
|
|
74147
74542
|
else
|
|
74148
|
-
|
|
74543
|
+
add24("taxablePensionsAndAnnuities", taxable3);
|
|
74149
74544
|
const dobStr = r.recipient === "spouse" ? docs.spouseDateOfBirth : docs.taxpayerDateOfBirth;
|
|
74150
74545
|
const code = r.box7.toUpperCase();
|
|
74151
74546
|
if ([...code].some((c2) => c2 === "1")) {
|
|
74152
74547
|
if (dobStr && ageYearsExact(dobStr, taxYear) >= 59.5) {
|
|
74153
74548
|
notes.push(`1099-R #${i + 1}: payer code 1 (early) but the ${r.recipient ?? "taxpayer"} is over 59\xBD \u2014 no \xA7 72(t) penalty (age controls, not the box code)`);
|
|
74154
74549
|
} else if ([...code].every((c2) => !PENALTY_EXEMPT_CODES.has(c2))) {
|
|
74155
|
-
|
|
74550
|
+
add24("earlyDistributionSubjectToPenalty", taxable3);
|
|
74156
74551
|
notes.push(`1099-R #${i + 1}: code 1 and no age exception established \u2014 $${dollars5(taxable3)} subject to the 10% \xA7 72(t) tax`);
|
|
74157
74552
|
}
|
|
74158
74553
|
}
|
|
74159
74554
|
}
|
|
74160
74555
|
for (const s of docs.ssa1099s ?? []) {
|
|
74161
|
-
|
|
74556
|
+
add24("socialSecurityBenefits", toCents(s.box5));
|
|
74162
74557
|
if (s.box6 !== void 0)
|
|
74163
|
-
|
|
74558
|
+
add24("federalTaxWithheld", toCents(s.box6));
|
|
74164
74559
|
}
|
|
74165
74560
|
let seGross = 0n;
|
|
74166
74561
|
for (const n of docs.f1099necs ?? []) {
|
|
74167
74562
|
seGross += toCents(n.box1);
|
|
74168
74563
|
if (n.box4 !== void 0)
|
|
74169
|
-
|
|
74564
|
+
add24("federalTaxWithheld", toCents(n.box4));
|
|
74170
74565
|
}
|
|
74171
74566
|
for (const k of docs.f1099ks ?? []) {
|
|
74172
74567
|
seGross += toCents(k.box1a);
|
|
74173
74568
|
if (k.box4 !== void 0)
|
|
74174
|
-
|
|
74569
|
+
add24("federalTaxWithheld", toCents(k.box4));
|
|
74175
74570
|
}
|
|
74176
74571
|
if (seGross > 0n || docs.scheduleCExpensesTotal !== void 0) {
|
|
74177
74572
|
const expenses = docs.scheduleCExpensesTotal !== void 0 ? toCents(docs.scheduleCExpensesTotal) : 0n;
|
|
74178
74573
|
const net = seGross - expenses;
|
|
74179
74574
|
if (net >= 0n) {
|
|
74180
74575
|
if (net > 0n)
|
|
74181
|
-
|
|
74576
|
+
add24("selfEmploymentNetProfit", net);
|
|
74182
74577
|
notes.push(`Schedule C: $${dollars5(seGross)} gross (1099-NEC/K) \u2212 $${dollars5(expenses)} expenses = $${dollars5(net)} net profit \u2192 SE tax + QBI machinery engage on it`);
|
|
74183
74578
|
} else {
|
|
74184
|
-
|
|
74579
|
+
add24("scheduleCNetLoss", -net);
|
|
74185
74580
|
notes.push(`Schedule C: expenses exceed 1099-NEC/K gross by $${dollars5(-net)} \u2014 recorded as scheduleCNetLoss`);
|
|
74186
74581
|
}
|
|
74187
74582
|
}
|
|
74188
74583
|
for (const [i, t] of (docs.f1099ints ?? []).entries()) {
|
|
74189
74584
|
if (t.box1 !== void 0)
|
|
74190
|
-
|
|
74585
|
+
add24("taxableInterest", toCents(t.box1));
|
|
74191
74586
|
if (t.box3 !== void 0 && toCents(t.box3) > 0n) {
|
|
74192
|
-
|
|
74587
|
+
add24("taxableInterest", toCents(t.box3));
|
|
74193
74588
|
notes.push(`1099-INT #${i + 1}: box 3 Treasury interest $${dollars5(toCents(t.box3))} is federally taxable (state returns exempt it \u2014 the state composers handle that subtraction)`);
|
|
74194
74589
|
}
|
|
74195
74590
|
if (t.box8 !== void 0)
|
|
74196
|
-
|
|
74591
|
+
add24("taxExemptInterest", toCents(t.box8));
|
|
74197
74592
|
if (t.box4 !== void 0)
|
|
74198
|
-
|
|
74593
|
+
add24("federalTaxWithheld", toCents(t.box4));
|
|
74199
74594
|
}
|
|
74200
74595
|
for (const [i, d3] of (docs.f1099divs ?? []).entries()) {
|
|
74201
74596
|
const total = toCents(d3.box1a);
|
|
@@ -74204,15 +74599,15 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74204
74599
|
throw new Error(`1099-DIV #${i + 1}: box 1b (qualified, $${dollars5(qualified2)}) exceeds box 1a (total, $${dollars5(total)}) \u2014 transcription error`);
|
|
74205
74600
|
}
|
|
74206
74601
|
if (qualified2 > 0n)
|
|
74207
|
-
|
|
74602
|
+
add24("qualifiedDividends", qualified2);
|
|
74208
74603
|
if (total - qualified2 > 0n)
|
|
74209
|
-
|
|
74604
|
+
add24("ordinaryDividends", total - qualified2);
|
|
74210
74605
|
if (d3.box2a !== void 0 && toCents(d3.box2a) > 0n) {
|
|
74211
|
-
|
|
74606
|
+
add24("__ltProceeds", toCents(d3.box2a));
|
|
74212
74607
|
notes.push(`1099-DIV #${i + 1}: box 2a capital gain distributions $${dollars5(toCents(d3.box2a))} \u2014 long-term by statute (\xA7 852(b)(3)(B)), joined to the Schedule D long-term bucket`);
|
|
74213
74608
|
}
|
|
74214
74609
|
if (d3.box4 !== void 0)
|
|
74215
|
-
|
|
74610
|
+
add24("federalTaxWithheld", toCents(d3.box4));
|
|
74216
74611
|
}
|
|
74217
74612
|
let stNet = 0n;
|
|
74218
74613
|
let ltNet = sums.__ltProceeds ?? 0n;
|
|
@@ -74227,24 +74622,24 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74227
74622
|
else
|
|
74228
74623
|
ltNet += lot;
|
|
74229
74624
|
if (b.box4 !== void 0)
|
|
74230
|
-
|
|
74625
|
+
add24("federalTaxWithheld", toCents(b.box4));
|
|
74231
74626
|
}
|
|
74232
74627
|
if (sawB) {
|
|
74233
74628
|
if (stNet > 0n)
|
|
74234
|
-
|
|
74629
|
+
add24("shortTermCapitalGains", stNet);
|
|
74235
74630
|
else if (stNet < 0n)
|
|
74236
|
-
|
|
74631
|
+
add24("shortTermCapitalLoss", -stNet);
|
|
74237
74632
|
if (ltNet > 0n)
|
|
74238
|
-
|
|
74633
|
+
add24("longTermCapitalGains", ltNet);
|
|
74239
74634
|
else if (ltNet < 0n)
|
|
74240
|
-
|
|
74635
|
+
add24("longTermCapitalLoss", -ltNet);
|
|
74241
74636
|
notes.push(`Schedule D buckets from 1099-B/DIV: short-term net $${dollars5(stNet)}, long-term net $${dollars5(ltNet)} \u2014 the \xA7 1222 netting rules combine them (character preserved, \xA7 1211(b) caps any overall loss)`);
|
|
74242
74637
|
}
|
|
74243
74638
|
for (const [i, g] of (docs.f1099gs ?? []).entries()) {
|
|
74244
74639
|
if (g.box1 !== void 0)
|
|
74245
|
-
|
|
74640
|
+
add24("unemploymentCompensation", toCents(g.box1));
|
|
74246
74641
|
if (g.box4 !== void 0)
|
|
74247
|
-
|
|
74642
|
+
add24("federalTaxWithheld", toCents(g.box4));
|
|
74248
74643
|
if (g.box2 !== void 0 && toCents(g.box2) > 0n) {
|
|
74249
74644
|
notes.push(`1099-G #${i + 1}: box 2 state refund $${dollars5(toCents(g.box2))} NOT auto-included \u2014 taxable only to the extent the prior-year SALT deduction produced a benefit (\xA7 111); add it to otherOrdinaryIncome yourself if it did`);
|
|
74250
74645
|
}
|
|
@@ -74282,23 +74677,23 @@ function compileDocuments(docs, asOf, ctx = {}) {
|
|
|
74282
74677
|
}
|
|
74283
74678
|
}
|
|
74284
74679
|
const facts2 = { ...bools };
|
|
74285
|
-
for (const [
|
|
74286
|
-
facts2[
|
|
74287
|
-
for (const [
|
|
74288
|
-
facts2[
|
|
74680
|
+
for (const [id2, c2] of Object.entries(sums))
|
|
74681
|
+
facts2[id2] = dollars5(c2);
|
|
74682
|
+
for (const [id2, n] of Object.entries(ints))
|
|
74683
|
+
facts2[id2] = n;
|
|
74289
74684
|
return { facts: facts2, notes, w2Box1Cents, missing, unsupported };
|
|
74290
74685
|
}
|
|
74291
74686
|
|
|
74292
74687
|
// dist/schema.js
|
|
74293
74688
|
var corpus = getCorpus();
|
|
74294
|
-
var
|
|
74689
|
+
var money43 = external_exports.union([external_exports.number(), external_exports.string()]).describe('dollars, e.g. 50000 or "1234.56"');
|
|
74295
74690
|
function zodForFact(f) {
|
|
74296
74691
|
if (f.id === "occupation") {
|
|
74297
74692
|
return external_exports.string().describe('tipped occupation, fuzzy-matched to the Treasury Tipped Occupation list (Treas. Reg. \xA7 1.224-1) \u2014 e.g. "bartender", "nanny" \u2014 or "other" if genuinely unlisted. Only needed when qualifiedTips > 0.');
|
|
74298
74693
|
}
|
|
74299
74694
|
switch (f.type) {
|
|
74300
74695
|
case "money":
|
|
74301
|
-
return
|
|
74696
|
+
return money43.describe(f.description);
|
|
74302
74697
|
case "bool":
|
|
74303
74698
|
return external_exports.boolean().describe(f.description);
|
|
74304
74699
|
case "int":
|
|
@@ -74328,12 +74723,12 @@ var DEPENDENT_EXTRAS = /* @__PURE__ */ new Set([
|
|
|
74328
74723
|
"taxpayerIsCustodialParent",
|
|
74329
74724
|
"custodialParentReleasedClaim"
|
|
74330
74725
|
]);
|
|
74331
|
-
function domainOf(
|
|
74332
|
-
if (
|
|
74726
|
+
function domainOf(id2) {
|
|
74727
|
+
if (id2.startsWith("corp") || id2.startsWith("sCorp") || BUSINESS_EXTRAS.has(id2))
|
|
74333
74728
|
return "business";
|
|
74334
|
-
if (
|
|
74729
|
+
if (id2.startsWith("fiduciary"))
|
|
74335
74730
|
return "fiduciary";
|
|
74336
|
-
if (/^dep[A-Z]/.test(
|
|
74731
|
+
if (/^dep[A-Z]/.test(id2) || DEPENDENT_EXTRAS.has(id2))
|
|
74337
74732
|
return "dependent";
|
|
74338
74733
|
return "individual";
|
|
74339
74734
|
}
|
|
@@ -74417,6 +74812,12 @@ var INDIVIDUAL_GROUPS = {
|
|
|
74417
74812
|
"qbiW2Wages",
|
|
74418
74813
|
"qbiUBIA",
|
|
74419
74814
|
"businessIsSSTB",
|
|
74815
|
+
"qbiAggregationGroup",
|
|
74816
|
+
"spouseQbiW2Wages",
|
|
74817
|
+
"spouseQbiUBIA",
|
|
74818
|
+
"spouseBusinessIsSSTB",
|
|
74819
|
+
"spouseQbiAggregationGroup",
|
|
74820
|
+
"qbiLossCarryforward",
|
|
74420
74821
|
"sepContribution",
|
|
74421
74822
|
"selfEmployedHealthPremiums",
|
|
74422
74823
|
"homeOfficeSquareFeet",
|
|
@@ -74517,6 +74918,34 @@ var INDIVIDUAL_GROUPS = {
|
|
|
74517
74918
|
"qsbsAcquiredAfterSept2010",
|
|
74518
74919
|
"qsbsHoldingPeriodYears"
|
|
74519
74920
|
],
|
|
74921
|
+
qbi_businesses: [
|
|
74922
|
+
"qbiAdditionalBusinesses",
|
|
74923
|
+
"qbiBusiness2Income",
|
|
74924
|
+
"qbiBusiness2W2Wages",
|
|
74925
|
+
"qbiBusiness2UBIA",
|
|
74926
|
+
"qbiBusiness2IsSSTB",
|
|
74927
|
+
"qbiBusiness2AggregationGroup",
|
|
74928
|
+
"qbiBusiness3Income",
|
|
74929
|
+
"qbiBusiness3W2Wages",
|
|
74930
|
+
"qbiBusiness3UBIA",
|
|
74931
|
+
"qbiBusiness3IsSSTB",
|
|
74932
|
+
"qbiBusiness3AggregationGroup",
|
|
74933
|
+
"qbiBusiness4Income",
|
|
74934
|
+
"qbiBusiness4W2Wages",
|
|
74935
|
+
"qbiBusiness4UBIA",
|
|
74936
|
+
"qbiBusiness4IsSSTB",
|
|
74937
|
+
"qbiBusiness4AggregationGroup",
|
|
74938
|
+
"qbiBusiness5Income",
|
|
74939
|
+
"qbiBusiness5W2Wages",
|
|
74940
|
+
"qbiBusiness5UBIA",
|
|
74941
|
+
"qbiBusiness5IsSSTB",
|
|
74942
|
+
"qbiBusiness5AggregationGroup",
|
|
74943
|
+
"qbiBusiness6Income",
|
|
74944
|
+
"qbiBusiness6W2Wages",
|
|
74945
|
+
"qbiBusiness6UBIA",
|
|
74946
|
+
"qbiBusiness6IsSSTB",
|
|
74947
|
+
"qbiBusiness6AggregationGroup"
|
|
74948
|
+
],
|
|
74520
74949
|
rentals_passive: [
|
|
74521
74950
|
"scheduleENetIncome",
|
|
74522
74951
|
"passiveActivityIncome",
|
|
@@ -75082,11 +75511,11 @@ var GROUP_NAMES = new Set(Object.keys(INDIVIDUAL_GROUPS));
|
|
|
75082
75511
|
var factById = new Map(corpus.facts.map((f) => [f.id, f]));
|
|
75083
75512
|
function shapeFor(ids) {
|
|
75084
75513
|
const shape = {};
|
|
75085
|
-
for (const
|
|
75086
|
-
const f = factById.get(
|
|
75514
|
+
for (const id2 of ids) {
|
|
75515
|
+
const f = factById.get(id2);
|
|
75087
75516
|
if (!f)
|
|
75088
75517
|
continue;
|
|
75089
|
-
shape[
|
|
75518
|
+
shape[id2] = zodForFact(f).optional();
|
|
75090
75519
|
}
|
|
75091
75520
|
return shape;
|
|
75092
75521
|
}
|
|
@@ -75099,6 +75528,7 @@ var GROUP_DESCRIPTIONS = {
|
|
|
75099
75528
|
tips_overtime: "\xA7 224 tips and \xA7 225 overtime deductions (OBBBA)",
|
|
75100
75529
|
retirement: "social security, IRA/pension distributions, early-distribution penalty",
|
|
75101
75530
|
self_employment: "Schedule C / K-1, QBI inputs, SE deductions, home office",
|
|
75531
|
+
qbi_businesses: "\xA7 199A per business (Form 8995-A): up to five businesses listed separately from the main one, each with its own QBI, W-2 wages, UBIA, SSTB status and aggregation group",
|
|
75102
75532
|
adjustments: "IRA/HSA contributions, student-loan and car-loan interest",
|
|
75103
75533
|
itemized: "Schedule A: SALT, mortgage, medical, charitable",
|
|
75104
75534
|
credits: "CTC/ODC counts, dependent care, saver's, adoption, education",
|
|
@@ -75261,11 +75691,11 @@ function buildFactsValidated(factsArg, defaultTarget) {
|
|
|
75261
75691
|
compiled.facts.wages = 0;
|
|
75262
75692
|
documentNotes.push("no W-2 in the documents block: wages $0 (Form 1040 line 1a)");
|
|
75263
75693
|
}
|
|
75264
|
-
for (const [
|
|
75265
|
-
if (
|
|
75266
|
-
throw new Error(`fact "${
|
|
75694
|
+
for (const [id2, v] of Object.entries(compiled.facts)) {
|
|
75695
|
+
if (id2 in flat) {
|
|
75696
|
+
throw new Error(`fact "${id2}" was derived from the documents block AND passed directly \u2014 remove the direct value (the compiled document value is authoritative; to override, drop the document entry and disclose)`);
|
|
75267
75697
|
}
|
|
75268
|
-
flat[
|
|
75698
|
+
flat[id2] = v;
|
|
75269
75699
|
}
|
|
75270
75700
|
}
|
|
75271
75701
|
if ("otherEarnedIncome" in flat) {
|
|
@@ -75329,12 +75759,12 @@ var fmt2 = (cents) => {
|
|
|
75329
75759
|
dollars6 += "," + digits.slice(i, i + 3);
|
|
75330
75760
|
return `${sign}$${dollars6}.${(abs % 100n).toString().padStart(2, "0")}`;
|
|
75331
75761
|
};
|
|
75332
|
-
function ruleDependencies(
|
|
75762
|
+
function ruleDependencies(rule2) {
|
|
75333
75763
|
const rules = /* @__PURE__ */ new Set();
|
|
75334
75764
|
const facts2 = /* @__PURE__ */ new Set();
|
|
75335
|
-
const roots = [
|
|
75336
|
-
if (
|
|
75337
|
-
roots.push(
|
|
75765
|
+
const roots = [rule2.formula];
|
|
75766
|
+
if (rule2.applicability)
|
|
75767
|
+
roots.push(rule2.applicability);
|
|
75338
75768
|
for (const root of roots) {
|
|
75339
75769
|
walkExpr(root, (e) => {
|
|
75340
75770
|
if (e.kind === "rule")
|
|
@@ -75366,33 +75796,33 @@ var FORM_5695_FACTS = [
|
|
|
75366
75796
|
"heatPumpBiomassCosts"
|
|
75367
75797
|
];
|
|
75368
75798
|
function composeForm5695(facts2, asOf, get) {
|
|
75369
|
-
const present = FORM_5695_FACTS.some((
|
|
75370
|
-
const f = facts2[
|
|
75799
|
+
const present = FORM_5695_FACTS.some((id2) => {
|
|
75800
|
+
const f = facts2[id2];
|
|
75371
75801
|
return f !== void 0 && f.type !== "bool" && BigInt(String(f.value)) !== 0n;
|
|
75372
75802
|
});
|
|
75373
75803
|
if (!present)
|
|
75374
75804
|
return null;
|
|
75375
75805
|
const rd26 = (c2) => {
|
|
75376
|
-
const
|
|
75377
|
-
const abs =
|
|
75806
|
+
const neg3 = c2 < 0n;
|
|
75807
|
+
const abs = neg3 ? -c2 : c2;
|
|
75378
75808
|
const r = (abs + 50n) / 100n * 100n;
|
|
75379
|
-
return
|
|
75809
|
+
return neg3 ? -r : r;
|
|
75380
75810
|
};
|
|
75381
75811
|
const d3 = (c2) => fmt2(rd26(c2));
|
|
75382
|
-
const
|
|
75383
|
-
const f = facts2[
|
|
75812
|
+
const money44 = (id2) => {
|
|
75813
|
+
const f = facts2[id2];
|
|
75384
75814
|
return f && f.type === "money" ? BigInt(String(f.value)) : 0n;
|
|
75385
75815
|
};
|
|
75386
75816
|
const E = (s) => get(`us.federal.energy.${s}`);
|
|
75387
75817
|
const year = asOf.slice(0, 4);
|
|
75388
75818
|
if (year !== "2025") {
|
|
75389
75819
|
const costs = {};
|
|
75390
|
-
for (const
|
|
75391
|
-
if (
|
|
75820
|
+
for (const id2 of FORM_5695_FACTS) {
|
|
75821
|
+
if (id2 === "fuelCellHalfKilowatts" || id2 === "residentialCleanEnergyCarryforward")
|
|
75392
75822
|
continue;
|
|
75393
|
-
const c2 =
|
|
75823
|
+
const c2 = money44(id2);
|
|
75394
75824
|
if (c2 !== 0n)
|
|
75395
|
-
costs[
|
|
75825
|
+
costs[id2] = d3(c2);
|
|
75396
75826
|
}
|
|
75397
75827
|
return {
|
|
75398
75828
|
"12_carryforward_from_prior_year": d3(E("clean.line12")),
|
|
@@ -75406,14 +75836,14 @@ function composeForm5695(facts2, asOf, get) {
|
|
|
75406
75836
|
};
|
|
75407
75837
|
}
|
|
75408
75838
|
return {
|
|
75409
|
-
"1_solar_electric": d3(
|
|
75410
|
-
"2_solar_water_heating": d3(
|
|
75411
|
-
"3_small_wind": d3(
|
|
75412
|
-
"4_geothermal_heat_pump": d3(
|
|
75413
|
-
"5b_battery_storage": d3(
|
|
75839
|
+
"1_solar_electric": d3(money44("solarElectricCosts")),
|
|
75840
|
+
"2_solar_water_heating": d3(money44("solarWaterHeatingCosts")),
|
|
75841
|
+
"3_small_wind": d3(money44("smallWindEnergyCosts")),
|
|
75842
|
+
"4_geothermal_heat_pump": d3(money44("geothermalHeatPumpCosts")),
|
|
75843
|
+
"5b_battery_storage": d3(money44("batteryStorageCosts")),
|
|
75414
75844
|
"6a_total": d3(E("clean.line6a")),
|
|
75415
75845
|
"6b_30_percent": d3(E("clean.line6b")),
|
|
75416
|
-
"8_fuel_cell_costs": d3(
|
|
75846
|
+
"8_fuel_cell_costs": d3(money44("fuelCellPropertyCosts")),
|
|
75417
75847
|
"9_30_percent": d3(E("clean.line9")),
|
|
75418
75848
|
"10_kilowatt_capacity_x_1000": d3(E("clean.line10")),
|
|
75419
75849
|
"11_smaller_of_9_or_10": d3(E("clean.line11")),
|
|
@@ -75422,28 +75852,28 @@ function composeForm5695(facts2, asOf, get) {
|
|
|
75422
75852
|
"14_limitation": d3(E("clean.line14")),
|
|
75423
75853
|
"15_residential_clean_energy_credit": d3(E("clean_energy_credit")),
|
|
75424
75854
|
"16_carryforward_to_next_year": d3(E("clean.carryforward")),
|
|
75425
|
-
"18a_insulation_air_sealing": d3(
|
|
75855
|
+
"18a_insulation_air_sealing": d3(money44("insulationAirSealingCosts")),
|
|
75426
75856
|
"18b_30_percent_max_1200": d3(E("improvement.line18b")),
|
|
75427
|
-
"19a_most_expensive_door": d3(
|
|
75857
|
+
"19a_most_expensive_door": d3(money44("exteriorDoorMostExpensiveCost")),
|
|
75428
75858
|
"19c_30_percent_max_250": d3(E("improvement.line19c")),
|
|
75429
|
-
"19f_other_doors": d3(
|
|
75859
|
+
"19f_other_doors": d3(money44("exteriorDoorOtherCosts")),
|
|
75430
75860
|
"19g_30_percent": d3(E("improvement.line19g")),
|
|
75431
75861
|
"19h_doors_max_500": d3(E("improvement.line19h")),
|
|
75432
|
-
"20c_windows_skylights": d3(
|
|
75862
|
+
"20c_windows_skylights": d3(money44("windowsSkylightsCosts")),
|
|
75433
75863
|
"20d_30_percent_max_600": d3(E("improvement.line20d")),
|
|
75434
|
-
"22c_central_air_conditioners": d3(
|
|
75864
|
+
"22c_central_air_conditioners": d3(money44("centralAirConditionerCosts")),
|
|
75435
75865
|
"22d_30_percent_max_600": d3(E("improvement.line22d")),
|
|
75436
|
-
"23c_gas_oil_water_heaters": d3(
|
|
75866
|
+
"23c_gas_oil_water_heaters": d3(money44("gasOilWaterHeaterCosts")),
|
|
75437
75867
|
"23d_30_percent_max_600": d3(E("improvement.line23d")),
|
|
75438
|
-
"24c_gas_oil_furnaces_boilers": d3(
|
|
75868
|
+
"24c_gas_oil_furnaces_boilers": d3(money44("gasOilFurnaceBoilerCosts")),
|
|
75439
75869
|
"24d_30_percent_max_600": d3(E("improvement.line24d")),
|
|
75440
|
-
"25c_enabling_property": d3(
|
|
75870
|
+
"25c_enabling_property": d3(money44("electricalPanelCosts")),
|
|
75441
75871
|
"25e_30_percent_max_600": d3(E("improvement.line25e")),
|
|
75442
|
-
"26b_home_energy_audit": d3(
|
|
75872
|
+
"26b_home_energy_audit": d3(money44("homeEnergyAuditCosts")),
|
|
75443
75873
|
"26c_30_percent_max_150": d3(E("improvement.line26c")),
|
|
75444
75874
|
"27_total": d3(E("improvement.line27")),
|
|
75445
75875
|
"28_smaller_of_27_or_1200": d3(E("improvement.line28")),
|
|
75446
|
-
"29g_heat_pumps_biomass": d3(
|
|
75876
|
+
"29g_heat_pumps_biomass": d3(money44("heatPumpBiomassCosts")),
|
|
75447
75877
|
"29h_30_percent_max_2000": d3(E("improvement.line29h")),
|
|
75448
75878
|
"30_total": d3(E("improvement.line30")),
|
|
75449
75879
|
"31_limitation": d3(E("improvement.line31")),
|
|
@@ -75615,22 +76045,22 @@ function createServer(options = {}) {
|
|
|
75615
76045
|
if (args.strict === true && incomplete.length)
|
|
75616
76046
|
throw new IncompleteReturnError(incomplete);
|
|
75617
76047
|
const rd26 = (c2) => {
|
|
75618
|
-
const
|
|
75619
|
-
const abs =
|
|
76048
|
+
const neg3 = c2 < 0n;
|
|
76049
|
+
const abs = neg3 ? -c2 : c2;
|
|
75620
76050
|
const r = (abs + 50n) / 100n * 100n;
|
|
75621
|
-
return
|
|
76051
|
+
return neg3 ? -r : r;
|
|
75622
76052
|
};
|
|
75623
76053
|
const facts2 = {};
|
|
75624
76054
|
let roundedInputs = 0;
|
|
75625
|
-
for (const [
|
|
76055
|
+
for (const [id2, v] of Object.entries(built.facts)) {
|
|
75626
76056
|
if (v.type === "money") {
|
|
75627
76057
|
const cents = BigInt(v.value);
|
|
75628
76058
|
const r = rd26(cents);
|
|
75629
76059
|
if (r !== cents)
|
|
75630
76060
|
roundedInputs += 1;
|
|
75631
|
-
facts2[
|
|
76061
|
+
facts2[id2] = { type: "money", value: r.toString() };
|
|
75632
76062
|
} else
|
|
75633
|
-
facts2[
|
|
76063
|
+
facts2[id2] = v;
|
|
75634
76064
|
}
|
|
75635
76065
|
const w2Box1Cents = built.w2Box1Cents === void 0 ? void 0 : rd26(built.w2Box1Cents);
|
|
75636
76066
|
if (roundedInputs > 0) {
|
|
@@ -75728,7 +76158,7 @@ function createServer(options = {}) {
|
|
|
75728
76158
|
description: `Verify a claimed tax amount (yours, a user's, or another tool's) against the law. Returns verdict 'verified' or 'refuted' with the correct value. Use this as a self-check before presenting any tax number. Put asOf (and target, if any) INSIDE the facts object \u2014 e.g. facts: {..., "asOf": "2025-12-31"} \u2014 otherwise the claim is checked under today's law.`,
|
|
75729
76159
|
inputSchema: legacyJsonSchema(external_exports.object({
|
|
75730
76160
|
facts: factsObjectParam,
|
|
75731
|
-
claimedAmount:
|
|
76161
|
+
claimedAmount: money43.describe("the amount to verify (negative = refund)"),
|
|
75732
76162
|
toleranceDollars: external_exports.number().min(0).optional().describe("default 1")
|
|
75733
76163
|
}).strict())
|
|
75734
76164
|
}, async (args) => {
|
|
@@ -75778,7 +76208,7 @@ function createServer(options = {}) {
|
|
|
75778
76208
|
}, async ({ ruleId, asOf }) => {
|
|
75779
76209
|
const versions2 = corpus.byId.get(ruleId);
|
|
75780
76210
|
if (!versions2) {
|
|
75781
|
-
const near = [...corpus.byId.keys()].filter((
|
|
76211
|
+
const near = [...corpus.byId.keys()].filter((id2) => id2.includes(ruleId));
|
|
75782
76212
|
return fail(new Error(`unknown rule "${ruleId}"${near.length ? ` \u2014 did you mean: ${near.slice(0, 5).join(", ")}` : ""}`));
|
|
75783
76213
|
}
|
|
75784
76214
|
const shown = asOf ? versions2.filter((r) => r.effectiveFrom <= asOf && (r.effectiveTo === void 0 || asOf < r.effectiveTo)) : versions2;
|
|
@@ -75917,7 +76347,7 @@ function createServer(options = {}) {
|
|
|
75917
76347
|
description: "Fact-check a claimed dollar amount about tax law ('the 2026 MFJ standard deduction is $32,200', 'CTC is $2,000 per child') against the corpus. Returns verified / refuted (with the correct value and citation) / unknown. Never states a verdict it cannot ground.",
|
|
75918
76348
|
inputSchema: legacyJsonSchema(external_exports.object({
|
|
75919
76349
|
query: external_exports.string().max(2e3).describe("what the amount is, e.g. 'standard deduction'"),
|
|
75920
|
-
claimedAmount:
|
|
76350
|
+
claimedAmount: money43,
|
|
75921
76351
|
filingStatus: external_exports.enum(["single", "mfj", "mfs", "hoh", "qss"]).optional(),
|
|
75922
76352
|
asOf: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional()
|
|
75923
76353
|
}).strict())
|