@mudraforge/statutory 2.13.0 → 2.14.0
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/CHANGELOG.md +15 -0
- package/README.md +6 -0
- package/package.json +1 -4
- package/src/calculators.js +139 -3
- package/src/constants.js +1 -1
- package/types/index.d.ts +95 -0
- package/conformance/README.md +0 -54
- package/conformance/fixtures/invalid_malformed_temporal_dates.json +0 -10
- package/conformance/fixtures/invalid_missing_effective_period.json +0 -6
- package/conformance/fixtures/invalid_missing_section_code.json +0 -9
- package/conformance/fixtures/valid_circular_frontmatter.md +0 -16
- package/conformance/fixtures/valid_full_section.json +0 -35
- package/conformance/fixtures/valid_minimal_section.json +0 -11
- package/conformance/test_conformance.js +0 -129
- package/docs/ACCOUNTING_ASSURANCE_AUDIT_DOSSIER.md +0 -276
- package/docs/ADESHA_ASSURANCE_OVERVIEW.md +0 -166
- package/docs/ARCHITECTURE.md +0 -773
- package/docs/ARCHITECTURE_DECISIONS.md +0 -158
- package/docs/CASE_01_FORM_TEXT.txt +0 -48
- package/docs/CATALOG.md +0 -1901
- package/docs/CA_PILOT_BENCHMARK_CASES.md +0 -282
- package/docs/CORPUS_QUALITY.md +0 -106
- package/docs/DATA_LICENSING.md +0 -73
- package/docs/DOMAIN_BREADTH_AND_DEPTH_COMPARISON.md +0 -209
- package/docs/ENTERPRISE_GOVERNANCE.md +0 -160
- package/docs/OKF_MAINTENANCE_SOP.md +0 -286
- package/docs/PILOT_EVALUATION_GUIDE.md +0 -215
- package/docs/PROVENANCE.md +0 -33
- package/docs/VERIFICATION.md +0 -106
- package/examples/README.md +0 -56
- package/examples/invoice_deduction_trace.json +0 -149
- package/examples/simulate_end_to_end_trace.js +0 -106
package/types/index.d.ts
CHANGED
|
@@ -194,33 +194,89 @@ export declare class StatutoryClient {
|
|
|
194
194
|
diff(options?: StatutoryDiffOptions): StatutoryDiffResult;
|
|
195
195
|
verify(targetDir?: string): any;
|
|
196
196
|
doctor(options?: any): Promise<any>;
|
|
197
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
198
|
+
|
|
197
199
|
calculateCorporateTaxMatVsConcessional(payload?: any): any;
|
|
200
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
201
|
+
|
|
198
202
|
evaluatePlaceOfSupplyAndLut(payload?: any): any;
|
|
203
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
204
|
+
|
|
199
205
|
calculateTransferPricingAlp(payload?: any): any;
|
|
206
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
207
|
+
|
|
200
208
|
evaluateSection79LossContinuity(payload?: any): any;
|
|
209
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
210
|
+
|
|
201
211
|
revalueForeignExchangeIndAs109(payload?: any): any;
|
|
212
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
213
|
+
|
|
202
214
|
calculateBusinessCombinationsIndAs103(payload?: any): any;
|
|
215
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
216
|
+
|
|
203
217
|
calculateImpairmentIndAs36(payload?: any): any;
|
|
218
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
219
|
+
|
|
204
220
|
calculateRevenueAllocationIndAs115(payload?: any): any;
|
|
221
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
222
|
+
|
|
205
223
|
calculateLeaseAmortizationIndAs116(payload?: any): any;
|
|
224
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
225
|
+
|
|
206
226
|
calculateExpectedCreditLossIndAs109(payload?: any): any;
|
|
227
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
228
|
+
|
|
207
229
|
calculateEsopAmortizationIndAs102(payload?: any): any;
|
|
230
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
231
|
+
|
|
208
232
|
calculateDeferredTaxIndAs12(payload?: any): any;
|
|
233
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
234
|
+
|
|
209
235
|
evaluateProvisionsAndContingenciesIndAs37(payload?: any): any;
|
|
236
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
237
|
+
|
|
210
238
|
calculateForeignCurrencyIndAs21(payload?: any): any;
|
|
239
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
240
|
+
|
|
211
241
|
evaluateSection194A(payload?: any): any;
|
|
242
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
243
|
+
|
|
212
244
|
evaluateSection194O(payload?: any): any;
|
|
245
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
246
|
+
|
|
213
247
|
evaluateSection194IA(payload?: any): any;
|
|
248
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
249
|
+
|
|
214
250
|
evaluateSection194IB(payload?: any): any;
|
|
251
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
252
|
+
|
|
215
253
|
evaluateSection194M(payload?: any): any;
|
|
254
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
255
|
+
|
|
216
256
|
evaluateSection194R(payload?: any): any;
|
|
257
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
258
|
+
|
|
217
259
|
evaluateSection43B(payload?: any): any;
|
|
260
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
261
|
+
|
|
218
262
|
evaluateSection281(payload?: any): any;
|
|
263
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
264
|
+
|
|
219
265
|
calculateItcReversalRule37(payload?: any): any;
|
|
266
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
267
|
+
|
|
220
268
|
calculateRule37ASupplierNonFilingReversal(payload?: any): any;
|
|
269
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
270
|
+
|
|
221
271
|
calculateRule42InputServiceReversal(payload?: any): any;
|
|
272
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
273
|
+
|
|
222
274
|
reconcileRule42AnnualTrueUp(payload?: any): any;
|
|
275
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
276
|
+
|
|
223
277
|
calculateRule43CapitalGoodsReversal(payload?: any): any;
|
|
278
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
279
|
+
|
|
224
280
|
calculateGstItcApportionmentRule42_43(payload?: any): any;
|
|
225
281
|
parseTallyDaybookCsv(csvText: string): DaybookVoucherInput[];
|
|
226
282
|
parseTallyDaybookXml(xmlText: string): DaybookVoucherInput[];
|
|
@@ -418,44 +474,83 @@ export declare function fromIntegerPaise(paise: number): number;
|
|
|
418
474
|
export declare function roundToPaisa(amount: number | string): number;
|
|
419
475
|
export declare function roundSection288B(amount: number | string): number;
|
|
420
476
|
export declare function cleanNumericAmount(val: any, options?: CleanNumericAmountOptions): number;
|
|
477
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
421
478
|
export declare function calculateCorporateTaxMatVsConcessional(payload?: any): any;
|
|
479
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
422
480
|
export declare function evaluatePlaceOfSupplyAndLut(payload?: any): any;
|
|
481
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
423
482
|
export declare function calculateTransferPricingAlp(payload?: any): any;
|
|
483
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
424
484
|
export declare function evaluateSection79LossContinuity(payload?: any): any;
|
|
485
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
425
486
|
export declare function evaluateSection281TaxClearance(payload: any): any;
|
|
487
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
426
488
|
export declare function revalueForeignExchangeIndAs109(payload?: any): any;
|
|
489
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
427
490
|
export declare function calculateBusinessCombinationsIndAs103(payload?: any): any;
|
|
491
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
428
492
|
export declare function calculateImpairmentIndAs36(payload?: any): any;
|
|
493
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
429
494
|
export declare function calculateRevenueAllocationIndAs115(payload?: any): any;
|
|
495
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
430
496
|
export declare function calculateLeaseAmortizationIndAs116(payload?: any): any;
|
|
497
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
431
498
|
export declare function calculateExpectedCreditLossIndAs109(payload?: any): any;
|
|
499
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
432
500
|
export declare function calculateEsopAmortizationIndAs102(payload?: any): any;
|
|
501
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
433
502
|
export declare function calculateDeferredTaxIndAs12(payload?: any): any;
|
|
503
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
434
504
|
export declare function evaluateProvisionsAndContingenciesIndAs37(payload?: any): any;
|
|
505
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
435
506
|
export declare function calculateForeignCurrencyIndAs21(payload?: any): any;
|
|
507
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
436
508
|
export declare function resolveMissingPanPenaltyFloor(params?: any): any;
|
|
509
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
437
510
|
export declare function evaluateSection194Q(payload: any): any;
|
|
511
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
438
512
|
export declare function evaluateSection194C(payload: any): any;
|
|
513
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
439
514
|
export declare function evaluateSection194H(payload: any): any;
|
|
515
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
440
516
|
export declare function evaluateSection194I(payload: any): any;
|
|
517
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
441
518
|
export declare function evaluateSection194J(payload: any): any;
|
|
519
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
442
520
|
export declare function evaluateSection194A(payload: any): any;
|
|
521
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
443
522
|
export declare function evaluateSection194O(payload: any): any;
|
|
523
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
444
524
|
export declare function evaluateSection194IA(payload: any): any;
|
|
525
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
445
526
|
export declare function evaluateSection194IB(payload: any): any;
|
|
527
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
446
528
|
export declare function evaluateSection194M(payload: any): any;
|
|
529
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
447
530
|
export declare function evaluateSection194R(payload: any): any;
|
|
531
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
448
532
|
export declare function evaluateSection43BStatutoryPayables(payload: any): any;
|
|
533
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
449
534
|
export declare function calculateItcReversalRule37(payload: any): any;
|
|
535
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
450
536
|
export declare function calculateRule37ASupplierNonFilingReversal(payload: any): any;
|
|
537
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
451
538
|
export declare function evaluateSection206C1H(payload: any): any;
|
|
539
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
452
540
|
export declare function evaluateSection43bH(payload: any): any;
|
|
541
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
453
542
|
export declare function calculateMsmeCompoundInterest(payload: any): any;
|
|
543
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
454
544
|
export declare function calculateAdvanceTaxAndInterest(payload: any): any;
|
|
545
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
455
546
|
export declare function calculateRule42InputServiceReversal(payload: any): any;
|
|
547
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
456
548
|
export declare function reconcileRule42AnnualTrueUp(payload: any): any;
|
|
549
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
457
550
|
export declare function calculateRule43CapitalGoodsReversal(payload: any): any;
|
|
551
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
458
552
|
export declare function calculateGstItcApportionmentRule42_43(payload: any): any;
|
|
553
|
+
/** @deprecated Use evaluateStatutoryAst from '@mudraforge/statutory/usvm' instead. */
|
|
459
554
|
export declare function evaluateCrossBorderRemittance(payload: any): any;
|
|
460
555
|
export declare function getRbiBankRateForDate(dateString?: string): number;
|
|
461
556
|
export declare const DEFAULT_RBI_BANK_RATE: number;
|
package/conformance/README.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# OKF-Statutory Vendor-Neutral Conformance Specification
|
|
2
|
-
|
|
3
|
-
> **Version**: 0.2.0
|
|
4
|
-
> **Status**: Institutional Normative Standard
|
|
5
|
-
> **Target Audience**: Authors of OKF parsers and AI agents in Python, Go, Rust, Ruby, and TypeScript.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 1. Purpose
|
|
10
|
-
|
|
11
|
-
The `@mudraforge/statutory` open knowledge substrate publishes machine-readable legal provisions designed to be consumed across multiple languages, agent frameworks, and database backends without requiring the MudraForge JavaScript SDK or proprietary runtime.
|
|
12
|
-
|
|
13
|
-
This directory contains standalone, vendor-neutral test fixtures and assertions that any conforming parser must satisfy.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 2. Conformance Criteria
|
|
18
|
-
|
|
19
|
-
A conforming OKF parser must guarantee:
|
|
20
|
-
|
|
21
|
-
1. **Mandatory Identity Fields**:
|
|
22
|
-
- Every `section.json` must provide `sectionCode` (string), `statutorySection` (string), and `governingStatute` (string).
|
|
23
|
-
2. **Deterministic Temporal Evaluation**:
|
|
24
|
-
- `effectivePeriod` must provide explicit `validFrom` (format `YYYY-MM-DD`) and `validTo` (`YYYY-MM-DD` or literal string `"OPEN_ENDED"`).
|
|
25
|
-
- Inverted timelines (`validTo < validFrom`) must be rejected at parse time.
|
|
26
|
-
3. **Dual-Act Mapping Preservation**:
|
|
27
|
-
- If a provision transitions to a successor statute (such as the *Income-tax Act, 2025* succeeding the *Income-tax Act, 1961*), the parser must preserve `successorStatute` and `successorSection` without loss.
|
|
28
|
-
4. **Google OKF Frontmatter Compatibility**:
|
|
29
|
-
- Administrative circulars (`circulars/*.md`) must declare standard YAML frontmatter bounded by `---` containing `id`, `title`, `authority`, `date`, `valid_from`, and `temporal_status`.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## 3. Test Fixtures
|
|
34
|
-
|
|
35
|
-
| Fixture | Expected Behavior | Description |
|
|
36
|
-
| :--- | :--- | :--- |
|
|
37
|
-
| [`valid_minimal_section.json`](./fixtures/valid_minimal_section.json) | **ACCEPT** | Minimal valid section schema with temporal bounds. |
|
|
38
|
-
| [`valid_full_section.json`](./fixtures/valid_full_section.json) | **ACCEPT** | Complete section schema with thresholds, citations, and checklists. |
|
|
39
|
-
| [`invalid_missing_section_code.json`](./fixtures/invalid_missing_section_code.json) | **REJECT** | Schema missing the required `sectionCode` field. |
|
|
40
|
-
| [`invalid_missing_effective_period.json`](./fixtures/invalid_missing_effective_period.json) | **REJECT** | Schema missing `effectivePeriod`. |
|
|
41
|
-
| [`invalid_malformed_temporal_dates.json`](./fixtures/invalid_malformed_temporal_dates.json) | **REJECT** | Inverted temporal boundary (`validTo < validFrom`). |
|
|
42
|
-
| [`valid_circular_frontmatter.md`](./fixtures/valid_circular_frontmatter.md) | **ACCEPT** | Google OKF YAML frontmatter with circular metadata. |
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 4. Running the Conformance Test
|
|
47
|
-
|
|
48
|
-
To run the reference conformance runner in Node.js:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
node conformance/test_conformance.js
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Third-party implementations in other languages should mirror these exact assertions against the JSON/Markdown fixtures in `fixtures/`.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: conf_circular_01
|
|
3
|
-
title: Conformance Standard Test Circular
|
|
4
|
-
authority: Conformance Verification Authority
|
|
5
|
-
date: 2024-04-01
|
|
6
|
-
statutory_section: Section 1
|
|
7
|
-
valid_from: 2024-04-01
|
|
8
|
-
valid_to: OPEN_ENDED
|
|
9
|
-
temporal_status: ACTIVE
|
|
10
|
-
subject: Operational guidelines for vendor-neutral OKF consumption
|
|
11
|
-
official_url: https://example.org/circulars/2024/conf_01.pdf
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Conformance Circular Body
|
|
15
|
-
This circular fixture asserts that standard YAML frontmatter can be extracted
|
|
16
|
-
by any third-party parser adhering to the Google OKF specification.
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sectionId": "CONF_SEC_02_FULL",
|
|
3
|
-
"sectionCode": "CONF_SEC_02",
|
|
4
|
-
"aliases": ["CONF_02", "conformance-full"],
|
|
5
|
-
"governingStatute": "Comprehensive Compliance Act, 2024",
|
|
6
|
-
"statutorySection": "Section 2",
|
|
7
|
-
"successorStatute": "Future Compliance Act, 2026",
|
|
8
|
-
"successorSection": "Section 101",
|
|
9
|
-
"title": "Comprehensive Conformance Test Section with Temporal Bounds & Thresholds",
|
|
10
|
-
"effectivePeriod": {
|
|
11
|
-
"validFrom": "2024-04-01",
|
|
12
|
-
"validTo": "2026-03-31",
|
|
13
|
-
"annualReset": "Every April 1",
|
|
14
|
-
"sunsetNotes": "Transitions to Section 101 on 1 April 2026."
|
|
15
|
-
},
|
|
16
|
-
"plainTextSummary": "This fixture asserts parsing of full metadata, thresholds, citations, and checklists.",
|
|
17
|
-
"keyStatutoryThresholds": {
|
|
18
|
-
"monetaryThresholdInr": 1000000,
|
|
19
|
-
"ratePercent": 1.5,
|
|
20
|
-
"penaltyRatePercent": 10.0
|
|
21
|
-
},
|
|
22
|
-
"officialCitations": [
|
|
23
|
-
{
|
|
24
|
-
"authority": "Standard Setting Authority",
|
|
25
|
-
"instrument": "Notification No. 01/2024",
|
|
26
|
-
"officialUrl": "https://example.org/gazette/2024/01.pdf"
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
"requiredDocumentChecklist": [
|
|
30
|
-
"Taxpayer Identification Card",
|
|
31
|
-
"Transaction Invoices"
|
|
32
|
-
],
|
|
33
|
-
"tier": "PUBLIC_COMMONS_FREE",
|
|
34
|
-
"version": "2.4.0"
|
|
35
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ═══════════════════════════════════════════════════════════════════════════
|
|
3
|
-
* @mudraforge/statutory — Vendor-Neutral OKF Conformance Runner
|
|
4
|
-
* ═══════════════════════════════════════════════════════════════════════════
|
|
5
|
-
* Validates that an OKF parser accurately distinguishes valid and invalid
|
|
6
|
-
* statutory records without relying on internal framework logic.
|
|
7
|
-
* Third-party language implementations (Python, Go, Rust) should replicate
|
|
8
|
-
* these exact test assertions against the fixtures/ directory.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import fs from 'node:fs';
|
|
12
|
-
import path from 'node:path';
|
|
13
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = path.dirname(__filename);
|
|
17
|
-
const FIXTURES_DIR = path.join(__dirname, 'fixtures');
|
|
18
|
-
|
|
19
|
-
function parseYamlFrontmatter(content) {
|
|
20
|
-
if (!content.startsWith('---')) return null;
|
|
21
|
-
const endIdx = content.indexOf('\n---', 3);
|
|
22
|
-
if (endIdx === -1) return null;
|
|
23
|
-
const yamlBlock = content.slice(3, endIdx).trim();
|
|
24
|
-
const meta = {};
|
|
25
|
-
for (const line of yamlBlock.split('\n')) {
|
|
26
|
-
const colonIdx = line.indexOf(':');
|
|
27
|
-
if (colonIdx !== -1) {
|
|
28
|
-
const key = line.slice(0, colonIdx).trim();
|
|
29
|
-
const val = line.slice(colonIdx + 1).trim();
|
|
30
|
-
meta[key] = val;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return meta;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function validateSectionRecord(record) {
|
|
37
|
-
const errors = [];
|
|
38
|
-
if (!record.sectionCode || typeof record.sectionCode !== 'string') {
|
|
39
|
-
errors.push('Missing or invalid [sectionCode].');
|
|
40
|
-
}
|
|
41
|
-
if (!record.governingStatute || typeof record.governingStatute !== 'string') {
|
|
42
|
-
errors.push('Missing or invalid [governingStatute].');
|
|
43
|
-
}
|
|
44
|
-
if (!record.effectivePeriod || typeof record.effectivePeriod !== 'object') {
|
|
45
|
-
errors.push('Missing [effectivePeriod] object.');
|
|
46
|
-
} else {
|
|
47
|
-
const { validFrom, validTo } = record.effectivePeriod;
|
|
48
|
-
if (!validFrom || !/^\d{4}-\d{2}-\d{2}$/.test(validFrom)) {
|
|
49
|
-
errors.push('Malformed [effectivePeriod.validFrom] (expected YYYY-MM-DD).');
|
|
50
|
-
}
|
|
51
|
-
if (!validTo || (!/^\d{4}-\d{2}-\d{2}$/.test(validTo) && validTo !== 'OPEN_ENDED')) {
|
|
52
|
-
errors.push('Malformed [effectivePeriod.validTo] (expected YYYY-MM-DD or OPEN_ENDED).');
|
|
53
|
-
}
|
|
54
|
-
if (validFrom && validTo && validTo !== 'OPEN_ENDED' && validTo < validFrom) {
|
|
55
|
-
errors.push(`Temporal paradox: [validTo: ${validTo}] is earlier than [validFrom: ${validFrom}].`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
isValid: errors.length === 0,
|
|
60
|
-
errors
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export function runConformanceSuite() {
|
|
65
|
-
console.log('===========================================================================');
|
|
66
|
-
console.log('OKF VENDOR-NEUTRAL CONFORMANCE TEST SUITE');
|
|
67
|
-
console.log('===========================================================================');
|
|
68
|
-
|
|
69
|
-
let totalTests = 0;
|
|
70
|
-
let passedTests = 0;
|
|
71
|
-
|
|
72
|
-
function assert(name, condition, extraInfo = '') {
|
|
73
|
-
totalTests++;
|
|
74
|
-
if (condition) {
|
|
75
|
-
passedTests++;
|
|
76
|
-
console.log(`[PASS] ${name}`);
|
|
77
|
-
} else {
|
|
78
|
-
console.error(`[FAIL] ${name} — ${extraInfo}`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// 1. Valid Minimal Section
|
|
83
|
-
const minRaw = JSON.parse(fs.readFileSync(path.join(FIXTURES_DIR, 'valid_minimal_section.json'), 'utf8'));
|
|
84
|
-
const minRes = validateSectionRecord(minRaw);
|
|
85
|
-
assert('Fixture: valid_minimal_section.json correctly accepted', minRes.isValid, minRes.errors.join(', '));
|
|
86
|
-
|
|
87
|
-
// 2. Valid Full Section
|
|
88
|
-
const fullRaw = JSON.parse(fs.readFileSync(path.join(FIXTURES_DIR, 'valid_full_section.json'), 'utf8'));
|
|
89
|
-
const fullRes = validateSectionRecord(fullRaw);
|
|
90
|
-
assert('Fixture: valid_full_section.json correctly accepted', fullRes.isValid, fullRes.errors.join(', '));
|
|
91
|
-
assert('Fixture: valid_full_section.json retains keyStatutoryThresholds', Boolean(fullRaw.keyStatutoryThresholds?.monetaryThresholdInr === 1000000));
|
|
92
|
-
assert('Fixture: valid_full_section.json retains dual-act successor mapping', fullRaw.successorStatute === 'Future Compliance Act, 2026');
|
|
93
|
-
|
|
94
|
-
// 3. Invalid: Missing Section Code
|
|
95
|
-
const noCodeRaw = JSON.parse(fs.readFileSync(path.join(FIXTURES_DIR, 'invalid_missing_section_code.json'), 'utf8'));
|
|
96
|
-
const noCodeRes = validateSectionRecord(noCodeRaw);
|
|
97
|
-
assert('Fixture: invalid_missing_section_code.json correctly rejected', !noCodeRes.isValid);
|
|
98
|
-
assert('Fixture: rejected with code error', noCodeRes.errors.some(e => e.includes('sectionCode')));
|
|
99
|
-
|
|
100
|
-
// 4. Invalid: Missing Effective Period
|
|
101
|
-
const noDatesRaw = JSON.parse(fs.readFileSync(path.join(FIXTURES_DIR, 'invalid_missing_effective_period.json'), 'utf8'));
|
|
102
|
-
const noDatesRes = validateSectionRecord(noDatesRaw);
|
|
103
|
-
assert('Fixture: invalid_missing_effective_period.json correctly rejected', !noDatesRes.isValid);
|
|
104
|
-
assert('Fixture: rejected with effectivePeriod error', noDatesRes.errors.some(e => e.includes('effectivePeriod')));
|
|
105
|
-
|
|
106
|
-
// 5. Invalid: Malformed / Inverted Timeline
|
|
107
|
-
const paradoxRaw = JSON.parse(fs.readFileSync(path.join(FIXTURES_DIR, 'invalid_malformed_temporal_dates.json'), 'utf8'));
|
|
108
|
-
const paradoxRes = validateSectionRecord(paradoxRaw);
|
|
109
|
-
assert('Fixture: invalid_malformed_temporal_dates.json correctly rejected (temporal paradox)', !paradoxRes.isValid);
|
|
110
|
-
assert('Fixture: rejected with temporal paradox explanation', paradoxRes.errors.some(e => e.includes('Temporal paradox')));
|
|
111
|
-
|
|
112
|
-
// 6. Circular Markdown Frontmatter
|
|
113
|
-
const mdContent = fs.readFileSync(path.join(FIXTURES_DIR, 'valid_circular_frontmatter.md'), 'utf8');
|
|
114
|
-
const frontmatter = parseYamlFrontmatter(mdContent);
|
|
115
|
-
assert('Fixture: valid_circular_frontmatter.md parsed YAML metadata', Boolean(frontmatter));
|
|
116
|
-
assert('Fixture: circular frontmatter extracted required fields', frontmatter?.id === 'conf_circular_01' && frontmatter?.statutory_section === 'Section 1');
|
|
117
|
-
|
|
118
|
-
console.log('===========================================================================');
|
|
119
|
-
console.log(`CONFORMANCE SUMMARY: ${passedTests}/${totalTests} Tests Passed (100% Agreement)`);
|
|
120
|
-
console.log('===========================================================================');
|
|
121
|
-
|
|
122
|
-
if (passedTests !== totalTests) {
|
|
123
|
-
process.exit(1);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
128
|
-
runConformanceSuite();
|
|
129
|
-
}
|