@mudraforge/statutory 2.7.0 → 2.8.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 CHANGED
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ---
9
9
 
10
+ ## [2.8.0] - 2026-10-25
11
+
12
+ ### Added
13
+ - **Dual-Act Statutory Crosswalk Engine (`crosswalk`)**:
14
+ - Implemented `crosswalkStatute()` in core library and exposed via `npx @mudraforge/statutory crosswalk <section> [--credit <date>] [--payment <date>] [--date <date>] [--json]`.
15
+ - Bridges provisions across the *Income-tax Act, 1961* and *Income-tax Act, 2025* (taking effect 1 April 2026).
16
+ - Enforces statutory withholding crystallization rule: tax withholding liability attaches on the earlier of credit in books or payment disbursement.
17
+ - Cites statutory savings authority under Section 536 of Income-tax Act, 2025 read with Section 6 of General Clauses Act, 1897.
18
+ - Correctly evaluates Section 206C(1H) seller TCS statutory sunset and formal omission w.e.f. 1 April 2025.
19
+ - Supports bidirectional crosswalks (both forward from 1961 Act and backward from 2025 Act).
20
+ - **Semantic Regulatory Diff & Amendment Tracker (`diff`)**:
21
+ - Implemented `getStatutoryDiff()` and exposed via `npx @mudraforge/statutory diff [--section <sec>] [--since <date>] [--domain <domain>] [--json]`.
22
+ - Compiles structured semantic regulatory changelogs across all 5 statutory domains.
23
+ - Tracks key legislative amendments: Section 194H rate cut (5% to 2% w.e.f. 2024-10-01), Section 206C(1H) sunset omission, Rule 48(4) e-invoicing ₹5 Cr threshold, Section 16(2)(aa) GSTR-2B mandatory matching, Section 43B(h) MSME disallowance, and Section 393 2025 Act transition.
24
+ - **StatutoryClient Parity**:
25
+ - Added `client.crosswalk()`, `client.diff()`, `client.verify()`, and `client.doctor()` methods to `StatutoryClient`.
26
+ - **Cryptographic Substrate Verifier (`verify`)**:
27
+ - Implemented `verifyLocalSubstrate()` in core library and exposed via `npx @mudraforge/statutory verify [path]`.
28
+ - Cryptographically verifies local file-level SHA-256 hashes against `manifest.json` (Integrity) and validates root Merkle digests against immutable release roots / Ed25519 signatures (Authenticity).
29
+ - Enforces mandatory statutory baseline policy checks (`194Q`, `194J`, `17(5)`, `MSMED-15-16`, `393`).
30
+ - **Diagnostic Environment Doctor (`doctor`)**:
31
+ - Implemented `runStatutoryDoctor()` in core library and exposed via `npx @mudraforge/statutory doctor [--offline]`.
32
+ - Diagnoses Node.js runtime (`>= v18`), OS platform, environment variables, local OKF filesystem health, and optional Cloudflare Anycast edge round-trip latency.
33
+ - Fully supports air-gapped / isolated VPC environments via `--offline` / `-o` without failing local health guarantees.
34
+ - **Global Machine-Readable Output (`--json`)**:
35
+ - Added `--json` / `-j` flag support across all CLI commands (`verify`, `doctor`, `lookup`, `list`, `browse`, `decode-id`, `check-update`).
36
+ - Emits clean, parseable JSON directly to `stdout` (suppressing banners, spinners, and update prompts) for CI/CD automation and `jq` scripting.
37
+ - **MudraForge Custom Exit Code Contract**:
38
+ - Established standardized exit codes: `0` (Success), `1` (Usage/Syntax error), `2` (Integrity/Security failure), `3` (Statutory policy violation).
39
+ - **Documentation & Release Alignment**:
40
+ - Unified package, manifest, and publication versions at `v2.8.0`.
41
+ - Extracted formal audit ledger into `docs/PROVENANCE.md` and streamlined main `README.md` for fast developer onboarding.
42
+
43
+ ---
44
+
10
45
  ## [2.7.0] - 2026-10-25
11
46
 
12
47
  ### Added
package/README.md CHANGED
@@ -36,37 +36,21 @@ console.log(statute.statute.title); // MSMED statutory payment timelines & compo
36
36
 
37
37
  ---
38
38
 
39
- ### Plain-English Orientation
39
+ ## Overview
40
40
 
41
- `@mudraforge/statutory` provides an open, machine-readable statutory knowledge layer for Indian and cross-border financial workflows, grounding compliance rules in primary legislation rather than probabilistic LLM guesswork. It serves software developers building financial applications, corporate finance operations teams seeking auditable withholding and delayed-payment rules, and autonomous AI agents requiring deterministic reference boundaries. The statutory commons acts as an open, inspectable reference substrate, while MudraForge's broader Adesha initiative governs downstream transactional execution, human authorization, and enterprise ledger writebacks. Developers can proceed directly to [Installation & Quick Start](#quick-start-free-tier), while finance leaders, controllers, and tax practitioners can inspect the indexed statutes, cumulative thresholds, and executive circulars in [docs/CATALOG.md](./docs/CATALOG.md).
41
+ `@mudraforge/statutory` is an offline, zero-dependency statutory knowledge substrate for Indian and cross-border financial compliance (Direct Tax, GST, MSME, Corporate M&A, International Tax). It grounds withholding rates, cumulative thresholds, and filing timelines in primary legislation and circulars rather than ungrounded LLM text generation.
42
42
 
43
- > **Statutory Dual-Act Temporal Boundary**: The *Income-tax Act, 2025* takes statutory effect on 1 April 2026. Relevant earlier tax years and prior transactions continue to be governed by the *Income-tax Act, 1961* under legislative transitional savings provisions (including Section 536(2) of the 2025 Act). This package explicitly models both legislative eras with date-bound temporal state machine evaluation.
43
+ * **Deterministic Knowledge**: Provides structured, offline rule definitions (`okf/**/section.json`) and ISO Mod-36 identifier decoding without outbound network calls.
44
+ * **Dual-Act Temporal Boundary**: Explicitly models both the *Income-tax Act, 1961* and the *Income-tax Act, 2025* (effective 1 April 2026), evaluating date-bound transitional savings rules automatically.
45
+ * **Separation of Concerns**: This open-source commons provides declarative statutory truth; downstream transactional execution, payment authorization, and bank disbursements belong to the governed execution layer (Adesha).
44
46
 
45
- ---
46
-
47
- ## Published Release & Provenance Ledger
48
-
49
- | Item | Value |
50
- |---|---|
51
- | **Package Release** | **`v2.4.2`** (Public Beta) |
52
- | **Knowledge Specification** | **Google Open Knowledge Format (OKF v0.2) + MudraForge Statutory Schema Extension** |
53
- | **Regulatory Snapshot** | **CBDT / CBIC / MCA / MSME Baseline: October 2026** |
54
- | **Corpus Quality Card** | 100% Citation Resolution (15/15 URLs) in [`docs/CORPUS_QUALITY.md`](./docs/CORPUS_QUALITY.md) |
55
- | **Architecture Decision Records** | 6 Normative ADRs documented in [`docs/ARCHITECTURE_DECISIONS.md`](./docs/ARCHITECTURE_DECISIONS.md) |
56
- | **Vendor Conformance Suite** | 12/12 Passing Fixture Tests in [`conformance/`](./conformance/) |
57
- | **End-to-End Execution Trace** | Audited 7-stage AP lifecycle in [`examples/`](./examples/) (`npm run example:trace`) |
58
- | **Enterprise Assurance Preview** | Formal TLA+ & mutation defenses in [`docs/ADESHA_ASSURANCE_OVERVIEW.md`](./docs/ADESHA_ASSURANCE_OVERVIEW.md) |
59
- | **Integrity Root** | SHA-256 root manifest in [`okf/manifest.json`](./okf/manifest.json) (reproducible byte-level non-tampering proof) |
60
- | **Temporal Framework** | Dual-Act Bridge: *Income-tax Act, 1961* & *Income-tax Act, 2025* |
61
- | **Verification Gate** | 100% Pass across cumulative thresholds, legislative sunsets, and excess math |
62
-
63
- > **Note on Cryptographic Scope**: The SHA-256 root hash in `okf/manifest.json` provides mathematical verification of **byte-level integrity** (ensuring local files have not been corrupted, altered, or partially written). A hash certifies that bytes match the published release; it does not by itself constitute legal or statutory authority. Epistemic authority is established strictly via the primary gazette citations, CBDT/CBIC executive circulars, and independent ground-truth tests.
47
+ > For cryptographic root digests, normative specifications, and formal assurance artifacts, see [docs/PROVENANCE.md](./docs/PROVENANCE.md).
64
48
 
65
49
  ---
66
50
 
67
51
  ## Table of Contents
68
52
 
69
- - [Plain-English Orientation](#plain-english-orientation)
53
+ - [Overview](#overview)
70
54
  - [Quick Start (Free Tier)](#quick-start-free-tier)
71
55
  - [1. Installation via npm](#1-installation-via-npm)
72
56
  - [2. Initialize AI Agent Skill](#2-initialize-ai-agent-skill)
@@ -81,7 +65,7 @@ console.log(statute.statute.title); // MSMED statutory payment timelines & compo
81
65
  - [Structured OKF Directory Hierarchy](#structured-okf-domain-hierarchy-zero-token-discovery)
82
66
  - [Canonical Edge Synchronization](#canonical-edge-synchronization-full-statutory-universe)
83
67
  - [Enterprise Tier (Paid Cloud Execution)](#enterprise-tier-paid-cloud-execution--analysis-mode)
84
- - [Edge API Endpoints & Quotas](#enterprise-edge-api-endpoints--quotas)
68
+ - [Edge API Endpoints & Rate Limits](#enterprise-edge-api-endpoints--rate-limits)
85
69
  - [Error Semantics & Response Codes](#error-semantics--response-codes)
86
70
  - [System Origin & Validation Baseline](#system-origin--validation-baseline)
87
71
  - [The Payment Instruction Boundary & End-to-End AP Architecture](#the-payment-instruction-boundary--end-to-end-ap-architecture)
@@ -427,6 +411,55 @@ const isActive2024 = await isStatuteActive('206C(1H)', '2024-05-01'); // true
427
411
  const isActive2025 = await isStatuteActive('206C(1H)', '2025-06-01'); // false (omitted by Finance Act, 2025)
428
412
  ```
429
413
 
414
+ ### 4. CLI Verification, Auditing & Pipeline Integration
415
+
416
+ The CLI provides cryptographic provenance checking, offline integrity verification, and machine-readable JSON output for CI/CD audit pipelines:
417
+
418
+ ```bash
419
+ # Run full environment, local substrate health, and edge latency diagnostics
420
+ npx @mudraforge/statutory doctor
421
+
422
+ # Force air-gapped / offline diagnostics (zero outbound network requests)
423
+ npx @mudraforge/statutory doctor --offline
424
+
425
+ # Cryptographically verify local statutory substrate integrity & origin authenticity
426
+ npx @mudraforge/statutory verify
427
+
428
+ # Dual-act 1961 <-> 2025 statutory crosswalk (earlier of credit vs payment)
429
+ npx @mudraforge/statutory crosswalk 194Q --credit 2026-03-25 --payment 2026-04-10
430
+
431
+ # Reverse crosswalk from 2025 Act provision
432
+ npx @mudraforge/statutory crosswalk 393 --date 2025-08-01
433
+
434
+ # Query semantic regulatory changelog and amendment tracker
435
+ npx @mudraforge/statutory diff --section 194H
436
+ npx @mudraforge/statutory diff --since 2025-01-01
437
+ npx @mudraforge/statutory diff --domain indirect_tax_gst
438
+
439
+ # Output machine-parseable JSON for CI/CD or jq integration
440
+ npx @mudraforge/statutory crosswalk 194Q --credit 2026-03-25 --payment 2026-04-10 --json
441
+ npx @mudraforge/statutory diff --section 194H --json
442
+ npx @mudraforge/statutory verify --json
443
+ npx @mudraforge/statutory doctor --json --offline
444
+
445
+ # Query section in pure JSON format
446
+ npx @mudraforge/statutory lookup 194Q --json
447
+
448
+ # Decode and validate PAN / GSTIN offline with ISO Mod-36 checksum
449
+ npx @mudraforge/statutory decode-id 27AAPFU0939F1ZV --json
450
+ ```
451
+
452
+ #### Custom MudraForge Exit Code Contract
453
+ Calling pipelines and CI/CD audit steps can inspect `$?` directly:
454
+
455
+ | Exit Code | Classification | Meaning |
456
+ |---|---|---|
457
+ | `0` | `SUCCESS` | Substrate verified authentic, intact, and all baseline provisions present. |
458
+ | `1` | `USAGE_OR_OPERATIONAL_ERROR` | Invalid CLI arguments, unknown command, or syntax error. |
459
+ | `2` | `INTEGRITY_OR_SECURITY_VIOLATION` | Cryptographic signature failure, unpinned root hash, file tampering, or revoked key. |
460
+ | `3` | `STATUTORY_POLICY_VIOLATION` | Statutory policy failure (e.g. missing mandatory baseline provision or sunset violation). |
461
+
462
+
430
463
  ---
431
464
 
432
465
  ## Enterprise Tier (Paid Cloud Execution & Analysis Mode)
@@ -453,9 +486,9 @@ console.log(result.taxableBase); // ₹70,00,000 (Calculates strictly on excess
453
486
  console.log(result.taxAmount); // ₹7,000 (0.1% TDS on taxable base)
454
487
  ```
455
488
 
456
- ### Enterprise Edge API Endpoints & Quotas
489
+ ### Enterprise Edge API Endpoints & Rate Limits
457
490
 
458
- | Endpoint | Method | Auth Required | Quota Limit | Response |
491
+ | Endpoint | Method | Auth Required | Rate Limit (Per Client / IP) | Response |
459
492
  |---|---|---|---|---|
460
493
  | `/api/v1/statutory/sections` | `GET` | No | 180 req/min | JSON array of indexed OKF sections |
461
494
  | `/api/v1/statutory/lookup` | `GET` | No | 180 req/min | Parametric section details & temporal validity |
@@ -487,7 +520,7 @@ All error responses from `@mudraforge/statutory` and the hosted edge API return
487
520
  | `405 Method Not Allowed` | `METHOD_NOT_ALLOWED` | Non-GET request sent to read-only commons endpoints. |
488
521
  | `413 Payload Too Large` | `PAYLOAD_TOO_LARGE` | JSON request body on `/calculate` exceeds 64KB security threshold. |
489
522
  | `415 Unsupported Media` | `UNSUPPORTED_MEDIA_TYPE` | Non-JSON payload sent to calculation engine. Set `Content-Type: application/json`. |
490
- | `429 Too Many Requests` | `RATE_LIMIT_EXCEEDED` | Request quota breached. Check `Retry-After` header before retrying. |
523
+ | `429 Too Many Requests` | `RATE_LIMIT_EXCEEDED` | Rate limit threshold breached. Check `Retry-After` header before retrying. |
491
524
 
492
525
  ---
493
526
 
package/bin/cli.js CHANGED
@@ -18,6 +18,11 @@ import {
18
18
  getLocalManifest,
19
19
  checkForPackageUpdate,
20
20
  decodeTaxIdentifier,
21
+ verifyLocalSubstrate,
22
+ runStatutoryDoctor,
23
+ crosswalkStatute,
24
+ getStatutoryDiff,
25
+ STATUTORY_EXIT_CODES,
21
26
  STATUTORY_CLIENT_VERSION,
22
27
  DEFAULT_LOCAL_OKF_DIR
23
28
  } from '../src/index.js';
@@ -25,11 +30,65 @@ import {
25
30
  const __filename = fileURLToPath(import.meta.url);
26
31
  const __dirname = path.dirname(__filename);
27
32
 
28
- const args = process.argv.slice(2);
33
+ const rawArgs = process.argv.slice(2);
34
+ const isJsonMode = rawArgs.includes('--json') || rawArgs.includes('-j');
35
+ const isOfflineMode = rawArgs.includes('--offline') || rawArgs.includes('-o');
36
+ const args = rawArgs.filter(a => a !== '--json' && a !== '-j' && a !== '--offline' && a !== '-o');
29
37
  const command = args[0] ? args[0].toLowerCase() : 'help';
30
38
 
39
+ function getNamedArg(nameList, argList) {
40
+ for (let i = 0; i < argList.length; i++) {
41
+ const item = argList[i];
42
+ for (const name of nameList) {
43
+ if (item === name && i + 1 < argList.length && !argList[i + 1].startsWith('-')) {
44
+ return argList[i + 1];
45
+ }
46
+ if (item.startsWith(`${name}=`)) {
47
+ return item.slice(name.length + 1);
48
+ }
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+
31
54
  async function main() {
32
55
  switch (command) {
56
+ case 'doctor':
57
+ case 'diagnose':
58
+ await handleDoctor();
59
+ break;
60
+
61
+ case 'verify':
62
+ case 'audit':
63
+ case 'check':
64
+ await handleVerify(args[1]);
65
+ break;
66
+
67
+ case 'crosswalk':
68
+ case 'bridge':
69
+ case 'transition': {
70
+ const section = (args[1] && !args[1].startsWith('-')) ? args[1] : getNamedArg(['--section', '-s'], rawArgs);
71
+ const creditDate = getNamedArg(['--credit', '-c'], rawArgs);
72
+ const paymentDate = getNamedArg(['--payment', '-p'], rawArgs);
73
+ const asOfDate = getNamedArg(['--date', '-d', '--as-of'], rawArgs);
74
+ if (!section) {
75
+ console.error('[ERROR] Please specify a section to crosswalk, e.g. npx @mudraforge/statutory crosswalk 194Q --credit 2026-03-25 --payment 2026-04-10');
76
+ process.exit(STATUTORY_EXIT_CODES.USAGE_ERROR);
77
+ }
78
+ await handleCrosswalk(section, { creditDate, paymentDate, asOfDate });
79
+ break;
80
+ }
81
+
82
+ case 'diff':
83
+ case 'changelog':
84
+ case 'amendments': {
85
+ const section = (args[1] && !args[1].startsWith('-')) ? args[1] : getNamedArg(['--section', '-s'], rawArgs);
86
+ const since = getNamedArg(['--since'], rawArgs);
87
+ const domain = getNamedArg(['--domain'], rawArgs);
88
+ await handleDiff({ section, since, domain });
89
+ break;
90
+ }
91
+
33
92
  case 'init-skill':
34
93
  case 'install-skill':
35
94
  await handleInitSkill(args[1]);
@@ -90,7 +149,7 @@ async function main() {
90
149
  }
91
150
 
92
151
  // Non-intrusive background npm package update notice
93
- if (!['check-update', 'status', 'version'].includes(command)) {
152
+ if (!isJsonMode && !['check-update', 'status', 'version', 'verify', 'audit', 'check', 'crosswalk', 'bridge', 'transition', 'diff', 'changelog', 'amendments'].includes(command)) {
94
153
  try {
95
154
  const updateInfo = await checkForPackageUpdate();
96
155
  if (updateInfo && updateInfo.updateAvailable) {
@@ -103,23 +162,244 @@ async function main() {
103
162
  }
104
163
  }
105
164
 
165
+ async function handleVerify(targetDir) {
166
+ try {
167
+ let dest = DEFAULT_LOCAL_OKF_DIR;
168
+ if (targetDir) {
169
+ dest = path.resolve(process.cwd(), targetDir);
170
+ }
171
+ const report = verifyLocalSubstrate(dest);
172
+ if (isJsonMode) {
173
+ console.log(JSON.stringify(report, null, 2));
174
+ process.exit(report.exitCode);
175
+ }
176
+
177
+ console.log('\n===========================================================================');
178
+ console.log(`MUDRAFORGE OPEN KNOWLEDGE FORMAT (OKF) — CRYPTOGRAPHIC VERIFIER [v${report.okfVersion || 'Unknown'}]`);
179
+ console.log('===========================================================================');
180
+
181
+ if (report.integrity.valid) {
182
+ console.log(`[OK] Integrity: ${report.integrity.totalFilesChecked} files verified against Merkle manifest.`);
183
+ console.log(` Root Merkle Hash: ${report.integrity.computedRoot}`);
184
+ } else {
185
+ console.error(`[FAIL] Integrity: Mismatches: ${report.integrity.mismatches.length}, Missing: ${report.integrity.missingFiles.length}, Untracked: ${report.integrity.untrackedFiles.length}`);
186
+ for (const m of report.integrity.mismatches) {
187
+ console.error(` • ${m.file} (Expected ${m.expected.slice(0, 10)}..., actual ${m.actual.slice(0, 10)}...)`);
188
+ }
189
+ for (const mf of report.integrity.missingFiles) {
190
+ console.error(` • Missing: ${mf}`);
191
+ }
192
+ }
193
+
194
+ if (report.authenticity.valid) {
195
+ console.log(`[OK] Authenticity: Provenance authenticated via ${report.authenticity.method}.`);
196
+ if (report.authenticity.keyId) {
197
+ console.log(` Signer Key ID: ${report.authenticity.keyId}`);
198
+ }
199
+ } else {
200
+ console.error(`[FAIL] Authenticity: Root hash "${report.integrity.computedRoot}" is neither pinned nor signed by an authorized MudraForge trust anchor.`);
201
+ }
202
+
203
+ if (report.baselineCheck.valid) {
204
+ console.log(`[OK] Statutory Policy: All mandatory baseline provisions present (${report.baselineCheck.baselineSections.join(', ')}).`);
205
+ } else {
206
+ console.error(`[FAIL] Statutory Policy: Missing mandatory baseline provisions: ${report.baselineCheck.missingBaseline.join(', ')}`);
207
+ }
208
+
209
+ console.log('───────────────────────────────────────────────────────────────────────────');
210
+ if (report.valid) {
211
+ console.log(`[PASS] Statutory substrate is authentic, intact, and compliant (Exit ${report.exitCode}).\n`);
212
+ } else {
213
+ console.error(`[FAIL] Verification failed with Exit Code ${report.exitCode}.\n`);
214
+ }
215
+ process.exit(report.exitCode);
216
+ } catch (err) {
217
+ if (isJsonMode) {
218
+ console.log(JSON.stringify({ valid: false, exitCode: STATUTORY_EXIT_CODES.USAGE_ERROR, error: err.message }, null, 2));
219
+ } else {
220
+ console.error(`[ERROR] Verification error: ${err.message}`);
221
+ }
222
+ process.exit(STATUTORY_EXIT_CODES.USAGE_ERROR);
223
+ }
224
+ }
225
+
226
+ async function handleDoctor() {
227
+ try {
228
+ const report = await runStatutoryDoctor({ offline: isOfflineMode });
229
+ if (isJsonMode) {
230
+ console.log(JSON.stringify(report, null, 2));
231
+ process.exit(report.exitCode);
232
+ }
233
+
234
+ console.log('\n===========================================================================');
235
+ console.log(`MUDRAFORGE STATUTORY DIAGNOSTIC DOCTOR [v${report.clientVersion}]`);
236
+ console.log('===========================================================================');
237
+
238
+ console.log('── 1. RUNTIME & HOST ENVIRONMENT ──');
239
+ console.log(`Node.js: ${report.runtime.nodeVersion} ${report.runtime.isSupportedNode ? '(Supported: v18+)' : '[UNSUPPORTED]'}`);
240
+ console.log(`Platform: ${report.runtime.platform} (${report.runtime.arch})`);
241
+ console.log(`Environment: ${report.runtime.environment}${report.runtime.isCI ? ' (CI Active)' : ''}`);
242
+ console.log(`API Key Config: ${report.runtime.hasApiKey ? 'CONFIGURED (Enterprise Tier Enabled)' : 'NOT_CONFIGURED (Free Commons Mode)'}`);
243
+
244
+ console.log('\n── 2. LOCAL OKF SUBSTRATE HEALTH ──');
245
+ if (report.substrate.valid) {
246
+ console.log(`Directory: ${DEFAULT_LOCAL_OKF_DIR}`);
247
+ console.log(`Manifest Version: v${report.substrate.okfVersion} (Published: ${report.substrate.publishedAt})`);
248
+ console.log(`Files Checked: ${report.substrate.integrity.totalFilesChecked} (0 mismatches, 0 missing, 0 untracked)`);
249
+ console.log(`Root Merkle Hash: ${report.substrate.integrity.computedRoot}`);
250
+ console.log(`Integrity: PASS`);
251
+ console.log(`Provenance: AUTHENTIC (${report.substrate.authenticity.method})`);
252
+ console.log(`Statutory Policy: PASS (All ${report.substrate.baselineCheck.baselineSections.length} mandatory baselines present)`);
253
+ } else {
254
+ console.error(`Substrate: FAILED (Exit Code ${report.substrate.exitCode})`);
255
+ if (report.substrate.error) console.error(`Error: ${report.substrate.error}`);
256
+ if (!report.substrate.integrity.valid) {
257
+ console.error(`Integrity Failure: ${report.substrate.integrity.mismatches.length} mismatch(es), ${report.substrate.integrity.missingFiles.length} missing files.`);
258
+ }
259
+ if (!report.substrate.authenticity.valid) {
260
+ console.error(`Authenticity: Root hash not authenticated.`);
261
+ }
262
+ if (!report.substrate.baselineCheck.valid) {
263
+ console.error(`Missing Baselines: ${report.substrate.baselineCheck.missingBaseline.join(', ')}`);
264
+ }
265
+ }
266
+
267
+ console.log('\n── 3. CLOUDFLARE ANYCAST EDGE CONNECTIVITY ──');
268
+ console.log(`Endpoint: ${report.edge.baseUrl}`);
269
+ if (report.edge.status === 'REACHABLE') {
270
+ console.log(`Status: REACHABLE (Latency: ${report.edge.latencyMs}ms)`);
271
+ } else if (report.edge.status === 'SKIPPED_AIR_GAPPED') {
272
+ console.log(`Status: SKIPPED (Air-Gapped / Offline Flag Enabled)`);
273
+ } else {
274
+ console.log(`Status: ${report.edge.status} (Offline-first local mode operative)`);
275
+ }
276
+ console.log(`Advisory: ${report.edge.advisory}`);
277
+
278
+ console.log('───────────────────────────────────────────────────────────────────────────');
279
+ if (report.healthy) {
280
+ console.log(`[PASS] All diagnostic checks passed with zero defects (Exit 0).\n`);
281
+ } else {
282
+ console.error(`[FAIL] Diagnostic doctor flagged health violations (Exit ${report.exitCode}).\n`);
283
+ }
284
+ process.exit(report.exitCode);
285
+ } catch (err) {
286
+ if (isJsonMode) {
287
+ console.log(JSON.stringify({ healthy: false, exitCode: STATUTORY_EXIT_CODES.USAGE_ERROR, error: err.message }, null, 2));
288
+ } else {
289
+ console.error(`[ERROR] Doctor diagnostic error: ${err.message}`);
290
+ }
291
+ process.exit(STATUTORY_EXIT_CODES.USAGE_ERROR);
292
+ }
293
+ }
294
+
295
+ async function handleCrosswalk(section, options) {
296
+ try {
297
+ const result = crosswalkStatute(section, options);
298
+ if (isJsonMode) {
299
+ console.log(JSON.stringify(result, null, 2));
300
+ process.exit(0);
301
+ }
302
+
303
+ console.log('\n===========================================================================');
304
+ console.log('MUDRAFORGE DUAL-ACT STATUTORY CROSSWALK (1961 ACT <-> 2025 ACT)');
305
+ console.log('===========================================================================');
306
+ console.log(`Query Section: ${result.querySection}`);
307
+ console.log(`Governing Statute: ${result.governingAct}`);
308
+ console.log(`Applicable Section: ${result.applicableSection}`);
309
+ console.log(`Temporal Status: ${result.temporalStatus}`);
310
+
311
+ console.log('\n── TEMPORAL CRYSTALLIZATION (EARLIER OF CREDIT OR PAYMENT) ──');
312
+ if (result.creditDate) console.log(`Credit in Books: ${result.creditDate}`);
313
+ if (result.paymentDate) console.log(`Payment Rail: ${result.paymentDate}`);
314
+ console.log(`Trigger Date: ${result.triggerDate}`);
315
+ console.log(`Trigger Event: ${result.triggerReason}`);
316
+ console.log(`Event Context: ${result.triggerDescription}`);
317
+
318
+ console.log('\n── STATUTORY BRIDGE & DUAL-ACT MAPPING ──');
319
+ console.log(`Predecessor (1961): ${result.crosswalk.predecessor.statutorySection} (${result.crosswalk.predecessor.title})`);
320
+ console.log(` Rate: ${result.crosswalk.predecessor.standardRate} | Challan: ${result.crosswalk.predecessor.challan} | Return: ${result.crosswalk.predecessor.returnForm}`);
321
+ console.log(`Successor (2025): ${result.crosswalk.successor.statutorySection} (Effective ${result.crosswalk.successor.effectiveDate})`);
322
+ console.log(` Rate: ${result.crosswalk.successor.standardRate} | Return: ${result.crosswalk.successor.returnForm}`);
323
+
324
+ console.log('\n── STATUTORY SAVINGS & LEGAL GROUNDING ──');
325
+ console.log(`Primary Authority: ${result.crosswalk.savingsAuthority.statute}`);
326
+ console.log(`Subsidiary Principle: ${result.crosswalk.savingsAuthority.subsidiary}`);
327
+ console.log(`Legal Analysis: ${result.legalAnalysis}`);
328
+
329
+ console.log('───────────────────────────────────────────────────────────────────────────');
330
+ console.log('[PASS] Statutory crosswalk resolved successfully (Exit 0).\n');
331
+ process.exit(0);
332
+ } catch (err) {
333
+ if (isJsonMode) {
334
+ console.log(JSON.stringify({ status: 'ERROR', exitCode: STATUTORY_EXIT_CODES.USAGE_ERROR, error: err.message }, null, 2));
335
+ } else {
336
+ console.error(`[ERROR] Crosswalk failure: ${err.message}`);
337
+ }
338
+ process.exit(STATUTORY_EXIT_CODES.USAGE_ERROR);
339
+ }
340
+ }
341
+
342
+ async function handleDiff(options) {
343
+ try {
344
+ const result = getStatutoryDiff(options);
345
+ if (isJsonMode) {
346
+ console.log(JSON.stringify(result, null, 2));
347
+ process.exit(0);
348
+ }
349
+
350
+ console.log('\n===========================================================================');
351
+ console.log('MUDRAFORGE STATUTORY REGULATORY CHANGELOG & AMENDMENT TRACKER');
352
+ console.log('===========================================================================');
353
+ console.log(`Filter Section: ${result.filterSection || 'ALL SECTIONS'}`);
354
+ console.log(`Filter Since: ${result.filterSince || 'ALL TIME'}`);
355
+ console.log(`Filter Domain: ${result.filterDomain || 'ALL DOMAINS'}`);
356
+ console.log(`Total Amendments: ${result.totalAmendments}`);
357
+
358
+ if (result.amendments.length === 0) {
359
+ console.log('\n[NOTICE] No statutory amendments matched the specified query filters.');
360
+ } else {
361
+ for (const am of result.amendments) {
362
+ console.log(`\n── [${am.id}] ${am.sectionCode} (${am.domain}) ──`);
363
+ console.log(`Title: ${am.title}`);
364
+ console.log(`Effective Date: ${am.effectiveDate} (${am.amendmentType})`);
365
+ console.log(`Governing Statute: ${am.statute}`);
366
+ console.log(`Enacted By: ${am.legalAuthority}`);
367
+ console.log(`Previous Baseline: ${am.previousValue}`);
368
+ console.log(`Amended Baseline: ${am.amendedValue}`);
369
+ console.log(`Summary: ${am.changeSummary}`);
370
+ console.log(`Statutory Impact: ${am.statutoryImpact}`);
371
+ }
372
+ }
373
+
374
+ console.log('───────────────────────────────────────────────────────────────────────────');
375
+ console.log(`[PASS] Statutory diff completed successfully (${result.totalAmendments} amendment(s) found) (Exit 0).\n`);
376
+ process.exit(0);
377
+ } catch (err) {
378
+ if (isJsonMode) {
379
+ console.log(JSON.stringify({ status: 'ERROR', exitCode: STATUTORY_EXIT_CODES.USAGE_ERROR, error: err.message }, null, 2));
380
+ } else {
381
+ console.error(`[ERROR] Statutory diff failure: ${err.message}`);
382
+ }
383
+ process.exit(STATUTORY_EXIT_CODES.USAGE_ERROR);
384
+ }
385
+ }
386
+
106
387
  async function handleCheckUpdate() {
107
388
  try {
108
- console.log('\n[INFO] Checking npm package version against registry.npmjs.org...');
389
+ let pkgUpdate = null;
109
390
  try {
110
- const pkgUpdate = await checkForPackageUpdate({ cacheTtlMs: 0 });
111
- if (pkgUpdate && pkgUpdate.updateAvailable) {
112
- console.log('───────────────────────────────────────────────────────────────────────────');
113
- console.log(`[WARN] New npm package version available: v${pkgUpdate.latestVersion} (installed: v${pkgUpdate.currentVersion})`);
114
- console.log(`Run: npm install @mudraforge/statutory@latest`);
115
- console.log('───────────────────────────────────────────────────────────────────────────');
116
- } else if (pkgUpdate) {
117
- console.log(`[OK] npm package code is up to date (v${pkgUpdate.currentVersion}).`);
118
- }
391
+ pkgUpdate = await checkForPackageUpdate({ cacheTtlMs: 0 });
119
392
  } catch (_) {}
120
393
 
121
- console.log('\n[INFO] Checking OKF knowledge substrate status against Cloudflare edge...');
122
394
  const status = await checkUpdates();
395
+
396
+ if (isJsonMode) {
397
+ console.log(JSON.stringify({
398
+ packageUpdate: pkgUpdate,
399
+ substrateStatus: status
400
+ }, null, 2));
401
+ process.exit(0);
402
+ }
123
403
  console.log('───────────────────────────────────────────────────────────────────────────');
124
404
  console.log(`Local OKF Version: ${status.localVersion}`);
125
405
  console.log(`Latest Edge Version: ${status.latestVersion}`);
@@ -186,6 +466,18 @@ async function handleSync(targetDir) {
186
466
  async function handleBrowse() {
187
467
  const manifest = getLocalManifest();
188
468
 
469
+ if (isJsonMode) {
470
+ console.log(JSON.stringify(manifest ? {
471
+ okfVersion: manifest.okfVersion,
472
+ publishedAt: manifest.publishedAt,
473
+ rootHash: manifest.rootHash,
474
+ totalSections: manifest.totalSections,
475
+ domains: manifest.domains,
476
+ sections: manifest.sections
477
+ } : { okfVersion: null, sections: [] }, null, 2));
478
+ process.exit(0);
479
+ }
480
+
189
481
  console.log('\n===========================================================================');
190
482
  console.log(`OPEN KNOWLEDGE FORMAT (OKF) — LOCAL BROWSER [v${manifest ? manifest.okfVersion : 'Local'}]`);
191
483
  console.log('===========================================================================');
@@ -283,18 +575,28 @@ async function handleLookup(section, asOfDate) {
283
575
  let temporalStatus = 'ACTIVE';
284
576
 
285
577
  if (s) {
286
- console.log(`\n[LOCAL OKF CACHE] Loaded section [${cleanSection}] from disk.`);
578
+ if (!isJsonMode) console.log(`\n[LOCAL OKF CACHE] Loaded section [${cleanSection}] from disk.`);
287
579
  if (asOfDate) {
288
580
  if (asOfDate < s.effectivePeriod.validFrom) temporalStatus = 'PRE_EFFECTIVE';
289
581
  else if (s.effectivePeriod.validTo && asOfDate > s.effectivePeriod.validTo) temporalStatus = 'SUNSET_SUPERSEDED';
290
582
  }
291
583
  } else {
292
- console.log(`\n[EDGE LOOKUP] Querying MudraForge Live Commons for [${cleanSection}]${asOfDate ? ` (as-of: ${asOfDate})` : ''}...`);
584
+ if (!isJsonMode) console.log(`\n[EDGE LOOKUP] Querying MudraForge Live Commons for [${cleanSection}]${asOfDate ? ` (as-of: ${asOfDate})` : ''}...`);
293
585
  const remote = await lookupStatute(cleanSection, { asOfDate });
294
586
  s = remote.statute;
295
587
  temporalStatus = remote.temporalStatus;
296
588
  }
297
589
 
590
+ if (isJsonMode) {
591
+ console.log(JSON.stringify({
592
+ status: 'SUCCESS',
593
+ sectionCode: cleanSection,
594
+ temporalStatus,
595
+ statute: s
596
+ }, null, 2));
597
+ process.exit(0);
598
+ }
599
+
298
600
  console.log('───────────────────────────────────────────────────────────────────────────');
299
601
  console.log(`Section: ${s.statutorySection} (${s.governingStatute})`);
300
602
  console.log(`Title: ${s.title}`);
@@ -324,6 +626,14 @@ async function handleLookup(section, asOfDate) {
324
626
  }
325
627
  console.log('───────────────────────────────────────────────────────────────────────────\n');
326
628
  } catch (err) {
629
+ if (isJsonMode) {
630
+ console.error(JSON.stringify({
631
+ status: 'ERROR',
632
+ error: err.message,
633
+ availableSections: err.availableSections || []
634
+ }, null, 2));
635
+ process.exit(1);
636
+ }
327
637
  console.error(`[ERROR] Lookup failed: ${err.message}`);
328
638
  if (err.availableSections) {
329
639
  console.log(`Available sections: ${err.availableSections.join(', ')}`);
@@ -334,8 +644,13 @@ async function handleLookup(section, asOfDate) {
334
644
 
335
645
  async function handleList() {
336
646
  try {
337
- console.log('\n[INFO] Fetching indexed statutory sections from MudraForge Commons...');
338
647
  const sections = await listSections();
648
+ if (isJsonMode) {
649
+ console.log(JSON.stringify({ sections, total: sections.length }, null, 2));
650
+ process.exit(0);
651
+ }
652
+
653
+ console.log('\n[INFO] Fetching indexed statutory sections from MudraForge Commons...');
339
654
  console.log('───────────────────────────────────────────────────────────────────────────');
340
655
  for (const s of sections) {
341
656
  const displayValidTo = (s.validTo === 'OPEN_ENDED' || s.validTo === '2099-12-31') ? 'In Force' : s.validTo;
@@ -343,6 +658,10 @@ async function handleList() {
343
658
  }
344
659
  console.log('───────────────────────────────────────────────────────────────────────────\n');
345
660
  } catch (err) {
661
+ if (isJsonMode) {
662
+ console.error(JSON.stringify({ status: 'ERROR', error: err.message }, null, 2));
663
+ process.exit(1);
664
+ }
346
665
  console.error(`[ERROR] Failed to list sections: ${err.message}`);
347
666
  process.exit(1);
348
667
  }
@@ -350,6 +669,11 @@ async function handleList() {
350
669
 
351
670
  function handleDecodeId(rawId) {
352
671
  const res = decodeTaxIdentifier(rawId);
672
+ if (isJsonMode) {
673
+ console.log(JSON.stringify(res, null, 2));
674
+ process.exit(res.isValid ? 0 : 1);
675
+ }
676
+
353
677
  console.log('\n===========================================================================');
354
678
  console.log('INDIAN TAX IDENTIFIER DECODER & OFFLINE MOD-36 VALIDATOR');
355
679
  console.log('===========================================================================');
@@ -382,6 +706,10 @@ Usage:
382
706
  npx @mudraforge/statutory <command> [options]
383
707
 
384
708
  Commands:
709
+ doctor [--offline] Run full diagnostic check of runtime, substrate integrity, & edge status
710
+ verify [path] Cryptographically verify OKF substrate authenticity & file integrity
711
+ crosswalk <section> Dual-act 1961 <-> 2025 bridge (earlier of credit vs payment)
712
+ diff Semantic regulatory changelog (--section, --since, --domain)
385
713
  browse Interactively browse local OKF statutory filesystem
386
714
  lookup <section> [date] Look up section details & temporal status (e.g. 194Q 2025-06-01)
387
715
  decode-id <pan_or_gstin> Offline ISO Mod-36 checksum, state name, and PAN entity decoding
@@ -390,6 +718,21 @@ Commands:
390
718
  list List all indexed statutory sections
391
719
  init-skill [path] Install SKILL.md into your agent workspace (defaults to .agents/skills/)
392
720
  help Show this help message
721
+
722
+ Options:
723
+ --credit <YYYY-MM-DD> Date of credit to vendor/payee account in books (used in crosswalk)
724
+ --payment <YYYY-MM-DD> Date of actual payment/disbursement (used in crosswalk)
725
+ --since <YYYY-MM-DD> Filter amendments taking effect on or after date (used in diff)
726
+ --section, -s <section> Filter amendments by section code (used in diff)
727
+ --domain <domain> Filter amendments by statutory domain (used in diff)
728
+ --json, -j Emit clean, machine-parseable JSON to stdout (suppresses banners)
729
+ --offline, -o Bypass outbound network checks (air-gapped / offline environment mode)
730
+
731
+ Exit Code Conventions:
732
+ 0 Success / Verification passed
733
+ 1 Usage or operational error (invalid syntax / parameters)
734
+ 2 Cryptographic authenticity or integrity violation (mismatch/revocation)
735
+ 3 Statutory policy violation (e.g. missing baseline provision)
393
736
  `);
394
737
  }
395
738