@ansvar/zimbabwe-law-mcp 1.0.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/CHANGELOG.md +27 -0
- package/LICENSE +110 -0
- package/README.md +151 -0
- package/data/.gitkeep +0 -0
- package/data/database.db +0 -0
- package/data/seed/zw-access-information-privacy.json +1087 -0
- package/data/seed/zw-broadcasting-services.json +1150 -0
- package/data/seed/zw-companies-business-entities.json +4128 -0
- package/data/seed/zw-constitution-2013.json +2783 -0
- package/data/seed/zw-criminal-law-codification.json +2857 -0
- package/data/seed/zw-cyber-data-protection-2021.json +389 -0
- package/data/seed/zw-freedom-of-information-2020.json +382 -0
- package/data/seed/zw-interception-communications-2007.json +335 -0
- package/data/seed/zw-money-laundering-proceeds-crime.json +1432 -0
- package/data/seed/zw-postal-telecommunications.json +1361 -0
- package/dist/capabilities.d.ts +16 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +43 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/about.d.ts +37 -0
- package/dist/tools/about.d.ts.map +1 -0
- package/dist/tools/about.js +46 -0
- package/dist/tools/about.js.map +1 -0
- package/dist/tools/build-legal-stance.d.ts +21 -0
- package/dist/tools/build-legal-stance.d.ts.map +1 -0
- package/dist/tools/build-legal-stance.js +46 -0
- package/dist/tools/build-legal-stance.js.map +1 -0
- package/dist/tools/check-currency.d.ts +20 -0
- package/dist/tools/check-currency.d.ts.map +1 -0
- package/dist/tools/check-currency.js +41 -0
- package/dist/tools/check-currency.js.map +1 -0
- package/dist/tools/format-citation.d.ts +19 -0
- package/dist/tools/format-citation.d.ts.map +1 -0
- package/dist/tools/format-citation.js +33 -0
- package/dist/tools/format-citation.js.map +1 -0
- package/dist/tools/get-eu-basis.d.ts +25 -0
- package/dist/tools/get-eu-basis.d.ts.map +1 -0
- package/dist/tools/get-eu-basis.js +56 -0
- package/dist/tools/get-eu-basis.js.map +1 -0
- package/dist/tools/get-provision-eu-basis.d.ts +20 -0
- package/dist/tools/get-provision-eu-basis.d.ts.map +1 -0
- package/dist/tools/get-provision-eu-basis.js +45 -0
- package/dist/tools/get-provision-eu-basis.js.map +1 -0
- package/dist/tools/get-provision.d.ts +24 -0
- package/dist/tools/get-provision.d.ts.map +1 -0
- package/dist/tools/get-provision.js +80 -0
- package/dist/tools/get-provision.js.map +1 -0
- package/dist/tools/get-zimbabwean-implementations.d.ts +27 -0
- package/dist/tools/get-zimbabwean-implementations.d.ts.map +1 -0
- package/dist/tools/get-zimbabwean-implementations.js +48 -0
- package/dist/tools/get-zimbabwean-implementations.js.map +1 -0
- package/dist/tools/list-sources.d.ts +25 -0
- package/dist/tools/list-sources.d.ts.map +1 -0
- package/dist/tools/list-sources.js +44 -0
- package/dist/tools/list-sources.js.map +1 -0
- package/dist/tools/registry.d.ts +13 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +365 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/search-eu-implementations.d.ts +25 -0
- package/dist/tools/search-eu-implementations.d.ts.map +1 -0
- package/dist/tools/search-eu-implementations.js +59 -0
- package/dist/tools/search-eu-implementations.js.map +1 -0
- package/dist/tools/search-legislation.d.ts +24 -0
- package/dist/tools/search-legislation.d.ts.map +1 -0
- package/dist/tools/search-legislation.js +54 -0
- package/dist/tools/search-legislation.js.map +1 -0
- package/dist/tools/validate-citation.d.ts +26 -0
- package/dist/tools/validate-citation.d.ts.map +1 -0
- package/dist/tools/validate-citation.js +118 -0
- package/dist/tools/validate-citation.js.map +1 -0
- package/dist/tools/validate-eu-compliance.d.ts +20 -0
- package/dist/tools/validate-eu-compliance.d.ts.map +1 -0
- package/dist/tools/validate-eu-compliance.js +98 -0
- package/dist/tools/validate-eu-compliance.js.map +1 -0
- package/dist/utils/as-of-date.d.ts +9 -0
- package/dist/utils/as-of-date.d.ts.map +1 -0
- package/dist/utils/as-of-date.js +25 -0
- package/dist/utils/as-of-date.js.map +1 -0
- package/dist/utils/fts-query.d.ts +19 -0
- package/dist/utils/fts-query.d.ts.map +1 -0
- package/dist/utils/fts-query.js +47 -0
- package/dist/utils/fts-query.js.map +1 -0
- package/dist/utils/metadata.d.ts +16 -0
- package/dist/utils/metadata.d.ts.map +1 -0
- package/dist/utils/metadata.js +23 -0
- package/dist/utils/metadata.js.map +1 -0
- package/dist/utils/statute-id.d.ts +15 -0
- package/dist/utils/statute-id.d.ts.map +1 -0
- package/dist/utils/statute-id.js +39 -0
- package/dist/utils/statute-id.js.map +1 -0
- package/fixtures/golden-hashes.json +56 -0
- package/fixtures/golden-tests.json +180 -0
- package/package.json +77 -0
- package/server.json +22 -0
- package/sources.yml +64 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate_citation — Validate a Zimbabwean legal citation against the database.
|
|
3
|
+
*
|
|
4
|
+
* Supports citation formats:
|
|
5
|
+
* - "Section N, [Act Title Year]" (e.g., "Section 29, Cyber and Data Protection Act 2021")
|
|
6
|
+
* - "s N" shorthand (e.g., "s 29 CDPA")
|
|
7
|
+
* - "Chapter N:NN" (e.g., "Chapter 9:23")
|
|
8
|
+
* - "[Act Title], Section N"
|
|
9
|
+
*/
|
|
10
|
+
import { resolveDocumentId } from '../utils/statute-id.js';
|
|
11
|
+
import { generateResponseMetadata } from '../utils/metadata.js';
|
|
12
|
+
/**
|
|
13
|
+
* Parse a Zimbabwean legal citation.
|
|
14
|
+
* Supports:
|
|
15
|
+
* - "Section N, Act Title Year" / "Section N Act Title"
|
|
16
|
+
* - "s N Act Title"
|
|
17
|
+
* - "Act Title, Section N" / "Act Title Section N"
|
|
18
|
+
* - "Chapter N:NN"
|
|
19
|
+
* - Just a document reference
|
|
20
|
+
*/
|
|
21
|
+
function parseCitation(citation) {
|
|
22
|
+
const trimmed = citation.trim();
|
|
23
|
+
// "Section N, Act Title" or "Section N Act Title"
|
|
24
|
+
const sectionFirst = trimmed.match(/^(?:Section|s\.?)\s+(\d+[A-Za-z]*)\s*[,;]?\s+(.+)$/i);
|
|
25
|
+
if (sectionFirst) {
|
|
26
|
+
return { documentRef: sectionFirst[2].trim(), sectionRef: sectionFirst[1] };
|
|
27
|
+
}
|
|
28
|
+
// "Act Title, Section N" or "Act Title Section N"
|
|
29
|
+
const sectionLast = trimmed.match(/^(.+?)[,;]?\s+(?:Section|s\.?)\s+(\d+[A-Za-z]*)$/i);
|
|
30
|
+
if (sectionLast) {
|
|
31
|
+
return { documentRef: sectionLast[1].trim(), sectionRef: sectionLast[2] };
|
|
32
|
+
}
|
|
33
|
+
// "Chapter N:NN, Section N"
|
|
34
|
+
const chapterWithSection = trimmed.match(/^(Chapter\s+\d+:\d+)\s*[,;]?\s*(?:Section|s\.?)\s+(\d+[A-Za-z]*)$/i);
|
|
35
|
+
if (chapterWithSection) {
|
|
36
|
+
return { documentRef: chapterWithSection[1], sectionRef: chapterWithSection[2] };
|
|
37
|
+
}
|
|
38
|
+
// "Chapter N:NN" alone
|
|
39
|
+
const chapterOnly = trimmed.match(/^Chapter\s+(\d+:\d+)$/i);
|
|
40
|
+
if (chapterOnly) {
|
|
41
|
+
return { documentRef: trimmed };
|
|
42
|
+
}
|
|
43
|
+
// Just a document reference
|
|
44
|
+
return { documentRef: trimmed };
|
|
45
|
+
}
|
|
46
|
+
export async function validateCitationTool(db, input) {
|
|
47
|
+
const warnings = [];
|
|
48
|
+
const parsed = parseCitation(input.citation);
|
|
49
|
+
if (!parsed) {
|
|
50
|
+
return {
|
|
51
|
+
results: {
|
|
52
|
+
valid: false,
|
|
53
|
+
citation: input.citation,
|
|
54
|
+
warnings: ['Could not parse citation format'],
|
|
55
|
+
},
|
|
56
|
+
_metadata: generateResponseMetadata(db),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const docId = resolveDocumentId(db, parsed.documentRef);
|
|
60
|
+
if (!docId) {
|
|
61
|
+
return {
|
|
62
|
+
results: {
|
|
63
|
+
valid: false,
|
|
64
|
+
citation: input.citation,
|
|
65
|
+
warnings: [`Document not found: "${parsed.documentRef}"`],
|
|
66
|
+
},
|
|
67
|
+
_metadata: generateResponseMetadata(db),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const doc = db.prepare('SELECT id, title, status FROM legal_documents WHERE id = ?').get(docId);
|
|
71
|
+
if (doc.status === 'repealed') {
|
|
72
|
+
warnings.push(`WARNING: This statute has been repealed.`);
|
|
73
|
+
}
|
|
74
|
+
else if (doc.status === 'amended') {
|
|
75
|
+
warnings.push(`Note: This statute has been amended. Verify you are referencing the current version.`);
|
|
76
|
+
}
|
|
77
|
+
if (parsed.sectionRef) {
|
|
78
|
+
const provision = db.prepare("SELECT provision_ref FROM legal_provisions WHERE document_id = ? AND (provision_ref = ? OR provision_ref = ? OR section = ?)").get(docId, parsed.sectionRef, `s${parsed.sectionRef}`, parsed.sectionRef);
|
|
79
|
+
if (!provision) {
|
|
80
|
+
return {
|
|
81
|
+
results: {
|
|
82
|
+
valid: false,
|
|
83
|
+
citation: input.citation,
|
|
84
|
+
document_id: docId,
|
|
85
|
+
document_title: doc.title,
|
|
86
|
+
warnings: [...warnings, `Provision "${parsed.sectionRef}" not found in ${doc.title}`],
|
|
87
|
+
},
|
|
88
|
+
_metadata: generateResponseMetadata(db),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
results: {
|
|
93
|
+
valid: true,
|
|
94
|
+
citation: input.citation,
|
|
95
|
+
normalized: `Section ${parsed.sectionRef}, ${doc.title}`,
|
|
96
|
+
document_id: docId,
|
|
97
|
+
document_title: doc.title,
|
|
98
|
+
provision_ref: provision.provision_ref,
|
|
99
|
+
status: doc.status,
|
|
100
|
+
warnings,
|
|
101
|
+
},
|
|
102
|
+
_metadata: generateResponseMetadata(db),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
results: {
|
|
107
|
+
valid: true,
|
|
108
|
+
citation: input.citation,
|
|
109
|
+
normalized: doc.title,
|
|
110
|
+
document_id: docId,
|
|
111
|
+
document_title: doc.title,
|
|
112
|
+
status: doc.status,
|
|
113
|
+
warnings,
|
|
114
|
+
},
|
|
115
|
+
_metadata: generateResponseMetadata(db),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=validate-citation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-citation.js","sourceRoot":"","sources":["../../src/tools/validate-citation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAqB,MAAM,sBAAsB,CAAC;AAiBnF;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEhC,kDAAkD;IAClD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC1F,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,CAAC;IAED,kDAAkD;IAClD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvF,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,4BAA4B;IAC5B,MAAM,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;IAC/G,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,CAAC;IAED,uBAAuB;IACvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5D,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IAED,4BAA4B;IAC5B,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAiC,EACjC,KAA4B;IAE5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,CAAC,iCAAiC,CAAC;aAC9C;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,CAAC,wBAAwB,MAAM,CAAC,WAAW,GAAG,CAAC;aAC1D;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,4DAA4D,CAC7D,CAAC,GAAG,CAAC,KAAK,CAAkD,CAAC;IAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC5D,CAAC;SAAM,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;IACxG,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,8HAA8H,CAC/H,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,UAAU,CAA0C,CAAC;QAErH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP,KAAK,EAAE,KAAK;oBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,WAAW,EAAE,KAAK;oBAClB,cAAc,EAAE,GAAG,CAAC,KAAK;oBACzB,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,cAAc,MAAM,CAAC,UAAU,kBAAkB,GAAG,CAAC,KAAK,EAAE,CAAC;iBACtF;gBACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;aACxC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,WAAW,MAAM,CAAC,UAAU,KAAK,GAAG,CAAC,KAAK,EAAE;gBACxD,WAAW,EAAE,KAAK;gBAClB,cAAc,EAAE,GAAG,CAAC,KAAK;gBACzB,aAAa,EAAE,SAAS,CAAC,aAAa;gBACtC,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ;aACT;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,GAAG,CAAC,KAAK;YACrB,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,GAAG,CAAC,KAAK;YACzB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ;SACT;QACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate_eu_compliance — Check international/EU alignment status for a Zimbabwean statute.
|
|
3
|
+
*/
|
|
4
|
+
import type Database from '@ansvar/mcp-sqlite';
|
|
5
|
+
import { type ToolResponse } from '../utils/metadata.js';
|
|
6
|
+
export interface ValidateEUComplianceInput {
|
|
7
|
+
document_id: string;
|
|
8
|
+
provision_ref?: string;
|
|
9
|
+
eu_document_id?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface EUComplianceResult {
|
|
12
|
+
document_id: string;
|
|
13
|
+
document_title: string;
|
|
14
|
+
compliance_status: 'compliant' | 'partial' | 'unclear' | 'not_applicable';
|
|
15
|
+
eu_references_found: number;
|
|
16
|
+
warnings: string[];
|
|
17
|
+
recommendations: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function validateEUCompliance(db: InstanceType<typeof Database>, input: ValidateEUComplianceInput): Promise<ToolResponse<EUComplianceResult>>;
|
|
20
|
+
//# sourceMappingURL=validate-eu-compliance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-eu-compliance.d.ts","sourceRoot":"","sources":["../../src/tools/validate-eu-compliance.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,EACjC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAuG3C"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* validate_eu_compliance — Check international/EU alignment status for a Zimbabwean statute.
|
|
3
|
+
*/
|
|
4
|
+
import { resolveDocumentId } from '../utils/statute-id.js';
|
|
5
|
+
import { generateResponseMetadata } from '../utils/metadata.js';
|
|
6
|
+
export async function validateEUCompliance(db, input) {
|
|
7
|
+
const resolvedId = resolveDocumentId(db, input.document_id);
|
|
8
|
+
if (!resolvedId) {
|
|
9
|
+
return {
|
|
10
|
+
results: {
|
|
11
|
+
document_id: input.document_id,
|
|
12
|
+
document_title: 'Unknown',
|
|
13
|
+
compliance_status: 'not_applicable',
|
|
14
|
+
eu_references_found: 0,
|
|
15
|
+
warnings: [`Document not found: "${input.document_id}"`],
|
|
16
|
+
recommendations: [],
|
|
17
|
+
},
|
|
18
|
+
_metadata: generateResponseMetadata(db),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const doc = db.prepare('SELECT id, title, status FROM legal_documents WHERE id = ?').get(resolvedId);
|
|
22
|
+
const warnings = [];
|
|
23
|
+
const recommendations = [];
|
|
24
|
+
// Check if EU reference tables exist
|
|
25
|
+
let euRefCount = 0;
|
|
26
|
+
try {
|
|
27
|
+
let sql = 'SELECT COUNT(*) as count FROM eu_references WHERE document_id = ?';
|
|
28
|
+
const params = [resolvedId];
|
|
29
|
+
if (input.eu_document_id) {
|
|
30
|
+
sql += ' AND eu_document_id = ?';
|
|
31
|
+
params.push(input.eu_document_id);
|
|
32
|
+
}
|
|
33
|
+
const row = db.prepare(sql).get(...params);
|
|
34
|
+
euRefCount = row.count;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return {
|
|
38
|
+
results: {
|
|
39
|
+
document_id: resolvedId,
|
|
40
|
+
document_title: doc.title,
|
|
41
|
+
compliance_status: 'not_applicable',
|
|
42
|
+
eu_references_found: 0,
|
|
43
|
+
warnings: ['EU/international references not available in this database tier'],
|
|
44
|
+
recommendations: [],
|
|
45
|
+
},
|
|
46
|
+
_metadata: generateResponseMetadata(db),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (euRefCount === 0) {
|
|
50
|
+
return {
|
|
51
|
+
results: {
|
|
52
|
+
document_id: resolvedId,
|
|
53
|
+
document_title: doc.title,
|
|
54
|
+
compliance_status: 'not_applicable',
|
|
55
|
+
eu_references_found: 0,
|
|
56
|
+
warnings: [],
|
|
57
|
+
recommendations: ['No international cross-references found for this statute. This may be a purely domestic law.'],
|
|
58
|
+
},
|
|
59
|
+
_metadata: generateResponseMetadata(db),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (doc.status === 'repealed') {
|
|
63
|
+
warnings.push('This statute has been repealed.');
|
|
64
|
+
recommendations.push('Check for replacement legislation.');
|
|
65
|
+
}
|
|
66
|
+
// Check implementation status
|
|
67
|
+
const statuses = db.prepare('SELECT implementation_status, COUNT(*) as count FROM eu_references WHERE document_id = ? GROUP BY implementation_status').all(resolvedId);
|
|
68
|
+
const statusMap = new Map(statuses.map(s => [s.implementation_status, s.count]));
|
|
69
|
+
const completeCount = statusMap.get('complete') ?? 0;
|
|
70
|
+
const partialCount = statusMap.get('partial') ?? 0;
|
|
71
|
+
const unknownCount = statusMap.get('unknown') ?? 0;
|
|
72
|
+
let compliance_status;
|
|
73
|
+
if (completeCount > 0 && partialCount === 0 && unknownCount === 0) {
|
|
74
|
+
compliance_status = 'compliant';
|
|
75
|
+
}
|
|
76
|
+
else if (partialCount > 0) {
|
|
77
|
+
compliance_status = 'partial';
|
|
78
|
+
warnings.push(`${partialCount} international reference(s) have partial implementation status.`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
compliance_status = 'unclear';
|
|
82
|
+
if (unknownCount > 0) {
|
|
83
|
+
recommendations.push(`${unknownCount} international reference(s) have unknown implementation status. Manual review recommended.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
results: {
|
|
88
|
+
document_id: resolvedId,
|
|
89
|
+
document_title: doc.title,
|
|
90
|
+
compliance_status,
|
|
91
|
+
eu_references_found: euRefCount,
|
|
92
|
+
warnings,
|
|
93
|
+
recommendations,
|
|
94
|
+
},
|
|
95
|
+
_metadata: generateResponseMetadata(db),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=validate-eu-compliance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-eu-compliance.js","sourceRoot":"","sources":["../../src/tools/validate-eu-compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date normalization for temporal queries.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Normalize an as-of date string to ISO 8601 format.
|
|
6
|
+
* Returns null if the input is not a valid date.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeAsOfDate(input?: string): string | null;
|
|
9
|
+
//# sourceMappingURL=as-of-date.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-of-date.d.ts","sourceRoot":"","sources":["../../src/utils/as-of-date.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB/D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date normalization for temporal queries.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Normalize an as-of date string to ISO 8601 format.
|
|
6
|
+
* Returns null if the input is not a valid date.
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeAsOfDate(input) {
|
|
9
|
+
if (!input || input.trim().length === 0)
|
|
10
|
+
return null;
|
|
11
|
+
const trimmed = input.trim();
|
|
12
|
+
// Already ISO 8601
|
|
13
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
|
|
14
|
+
const date = new Date(trimmed);
|
|
15
|
+
if (!isNaN(date.getTime()))
|
|
16
|
+
return trimmed;
|
|
17
|
+
}
|
|
18
|
+
// Try parsing as a general date
|
|
19
|
+
const date = new Date(trimmed);
|
|
20
|
+
if (!isNaN(date.getTime())) {
|
|
21
|
+
return date.toISOString().slice(0, 10);
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=as-of-date.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-of-date.js","sourceRoot":"","sources":["../../src/utils/as-of-date.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,mBAAmB;IACnB,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,OAAO,CAAC;IAC7C,CAAC;IAED,gCAAgC;IAChC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FTS5 query helpers for Zimbabwe Law MCP.
|
|
3
|
+
*
|
|
4
|
+
* Handles query sanitization and variant generation for SQLite FTS5.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Sanitize user input for safe FTS5 queries.
|
|
8
|
+
* Removes characters that have special meaning in FTS5 syntax.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sanitizeFtsInput(input: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Build FTS5 query variants for a search term.
|
|
13
|
+
* Returns variants in order of specificity (most specific first):
|
|
14
|
+
* 1. Exact phrase match
|
|
15
|
+
* 2. All terms required (AND)
|
|
16
|
+
* 3. Prefix match on last term
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildFtsQueryVariants(sanitized: string): string[];
|
|
19
|
+
//# sourceMappingURL=fts-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fts-query.d.ts","sourceRoot":"","sources":["../../src/utils/fts-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA2BjE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FTS5 query helpers for Zimbabwe Law MCP.
|
|
3
|
+
*
|
|
4
|
+
* Handles query sanitization and variant generation for SQLite FTS5.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Sanitize user input for safe FTS5 queries.
|
|
8
|
+
* Removes characters that have special meaning in FTS5 syntax.
|
|
9
|
+
*/
|
|
10
|
+
export function sanitizeFtsInput(input) {
|
|
11
|
+
return input
|
|
12
|
+
.replace(/['"(){}[\]^~*:]/g, ' ')
|
|
13
|
+
.replace(/\s+/g, ' ')
|
|
14
|
+
.trim();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build FTS5 query variants for a search term.
|
|
18
|
+
* Returns variants in order of specificity (most specific first):
|
|
19
|
+
* 1. Exact phrase match
|
|
20
|
+
* 2. All terms required (AND)
|
|
21
|
+
* 3. Prefix match on last term
|
|
22
|
+
*/
|
|
23
|
+
export function buildFtsQueryVariants(sanitized) {
|
|
24
|
+
if (!sanitized || sanitized.trim().length === 0) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const terms = sanitized.split(/\s+/).filter(t => t.length > 0);
|
|
28
|
+
if (terms.length === 0)
|
|
29
|
+
return [];
|
|
30
|
+
const variants = [];
|
|
31
|
+
// Exact phrase
|
|
32
|
+
if (terms.length > 1) {
|
|
33
|
+
variants.push(`"${terms.join(' ')}"`);
|
|
34
|
+
}
|
|
35
|
+
// AND query
|
|
36
|
+
variants.push(terms.join(' AND '));
|
|
37
|
+
// Prefix match on last term (for autocomplete-like behavior)
|
|
38
|
+
if (terms.length === 1 && terms[0].length >= 3) {
|
|
39
|
+
variants.push(`${terms[0]}*`);
|
|
40
|
+
}
|
|
41
|
+
else if (terms.length > 1) {
|
|
42
|
+
const prefix = [...terms.slice(0, -1), `${terms[terms.length - 1]}*`];
|
|
43
|
+
variants.push(prefix.join(' AND '));
|
|
44
|
+
}
|
|
45
|
+
return variants;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=fts-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fts-query.js","sourceRoot":"","sources":["../../src/utils/fts-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK;SACT,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB;IACrD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,eAAe;IACf,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,YAAY;IACZ,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnC,6DAA6D;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response metadata utilities for Zimbabwe Law MCP.
|
|
3
|
+
*/
|
|
4
|
+
import type Database from '@ansvar/mcp-sqlite';
|
|
5
|
+
export interface ResponseMetadata {
|
|
6
|
+
data_source: string;
|
|
7
|
+
jurisdiction: string;
|
|
8
|
+
disclaimer: string;
|
|
9
|
+
freshness?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ToolResponse<T> {
|
|
12
|
+
results: T;
|
|
13
|
+
_metadata: ResponseMetadata;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateResponseMetadata(db: InstanceType<typeof Database>): ResponseMetadata;
|
|
16
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/utils/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,GAChC,gBAAgB,CAoBlB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response metadata utilities for Zimbabwe Law MCP.
|
|
3
|
+
*/
|
|
4
|
+
export function generateResponseMetadata(db) {
|
|
5
|
+
let freshness;
|
|
6
|
+
try {
|
|
7
|
+
const row = db.prepare("SELECT value FROM db_metadata WHERE key = 'built_at'").get();
|
|
8
|
+
if (row)
|
|
9
|
+
freshness = row.value;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Ignore
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
data_source: 'ZimLII (zimlii.org) — Zimbabwe Legal Information Institute, hosted by AfricanLII',
|
|
16
|
+
jurisdiction: 'ZW',
|
|
17
|
+
disclaimer: 'This data is sourced from ZimLII under free access principles. ' +
|
|
18
|
+
'Government legislation is public domain under Zimbabwean law. ' +
|
|
19
|
+
'Always verify with the official Zimbabwe Government Gazette or Parliament of Zimbabwe portal.',
|
|
20
|
+
freshness,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/utils/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgBH,MAAM,UAAU,wBAAwB,CACtC,EAAiC;IAEjC,IAAI,SAA6B,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,sDAAsD,CACvD,CAAC,GAAG,EAAmC,CAAC;QACzC,IAAI,GAAG;YAAE,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IAED,OAAO;QACL,WAAW,EAAE,kFAAkF;QAC/F,YAAY,EAAE,IAAI;QAClB,UAAU,EACR,iEAAiE;YACjE,gEAAgE;YAChE,+FAA+F;QACjG,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statute ID resolution for Zimbabwe Law MCP.
|
|
3
|
+
*
|
|
4
|
+
* Resolves fuzzy document references (titles, chapter numbers) to database document IDs.
|
|
5
|
+
*/
|
|
6
|
+
import type Database from '@ansvar/mcp-sqlite';
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a document identifier to a database document ID.
|
|
9
|
+
* Supports:
|
|
10
|
+
* - Direct ID match (e.g., "zw-cyber-data-protection-2021")
|
|
11
|
+
* - Chapter number match (e.g., "Chapter 9:23", "9:23")
|
|
12
|
+
* - Title substring match (e.g., "Cyber and Data Protection", "CDPA")
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveDocumentId(db: InstanceType<typeof Database>, input: string): string | null;
|
|
15
|
+
//# sourceMappingURL=statute-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statute-id.d.ts","sourceRoot":"","sources":["../../src/utils/statute-id.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,EACjC,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAiCf"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statute ID resolution for Zimbabwe Law MCP.
|
|
3
|
+
*
|
|
4
|
+
* Resolves fuzzy document references (titles, chapter numbers) to database document IDs.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Resolve a document identifier to a database document ID.
|
|
8
|
+
* Supports:
|
|
9
|
+
* - Direct ID match (e.g., "zw-cyber-data-protection-2021")
|
|
10
|
+
* - Chapter number match (e.g., "Chapter 9:23", "9:23")
|
|
11
|
+
* - Title substring match (e.g., "Cyber and Data Protection", "CDPA")
|
|
12
|
+
*/
|
|
13
|
+
export function resolveDocumentId(db, input) {
|
|
14
|
+
const trimmed = input.trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return null;
|
|
17
|
+
// Direct ID match
|
|
18
|
+
const directMatch = db.prepare('SELECT id FROM legal_documents WHERE id = ?').get(trimmed);
|
|
19
|
+
if (directMatch)
|
|
20
|
+
return directMatch.id;
|
|
21
|
+
// Chapter number match (e.g., "Chapter 9:23" or just "9:23")
|
|
22
|
+
const chapterMatch = trimmed.match(/(?:Chapter\s+)?(\d+:\d+)/i);
|
|
23
|
+
if (chapterMatch) {
|
|
24
|
+
const chapterNum = chapterMatch[1];
|
|
25
|
+
const chResult = db.prepare("SELECT id FROM legal_documents WHERE short_name LIKE ? OR title LIKE ? LIMIT 1").get(`%${chapterNum}%`, `%${chapterNum}%`);
|
|
26
|
+
if (chResult)
|
|
27
|
+
return chResult.id;
|
|
28
|
+
}
|
|
29
|
+
// Title/short_name fuzzy match
|
|
30
|
+
const titleResult = db.prepare("SELECT id FROM legal_documents WHERE title LIKE ? OR short_name LIKE ? OR title_en LIKE ? LIMIT 1").get(`%${trimmed}%`, `%${trimmed}%`, `%${trimmed}%`);
|
|
31
|
+
if (titleResult)
|
|
32
|
+
return titleResult.id;
|
|
33
|
+
// Case-insensitive fallback
|
|
34
|
+
const lowerResult = db.prepare("SELECT id FROM legal_documents WHERE LOWER(title) LIKE LOWER(?) OR LOWER(short_name) LIKE LOWER(?) OR LOWER(title_en) LIKE LOWER(?) LIMIT 1").get(`%${trimmed}%`, `%${trimmed}%`, `%${trimmed}%`);
|
|
35
|
+
if (lowerResult)
|
|
36
|
+
return lowerResult.id;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=statute-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statute-id.js","sourceRoot":"","sources":["../../src/utils/statute-id.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAiC,EACjC,KAAa;IAEb,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,kBAAkB;IAClB,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,6CAA6C,CAC9C,CAAC,GAAG,CAAC,OAAO,CAA+B,CAAC;IAC7C,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,6DAA6D;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAChE,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CACzB,gFAAgF,CACjF,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,EAAE,IAAI,UAAU,GAAG,CAA+B,CAAC;QAC1E,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IACnC,CAAC;IAED,+BAA+B;IAC/B,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,mGAAmG,CACpG,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,CAA+B,CAAC;IACpF,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,4BAA4B;IAC5B,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,6IAA6I,CAC9I,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,CAA+B,CAAC;IACpF,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./golden-hashes.schema.json",
|
|
3
|
+
"version": "1.0",
|
|
4
|
+
"mcp_name": "Zimbabwe Law MCP",
|
|
5
|
+
"jurisdiction": "ZW",
|
|
6
|
+
"provisions": [
|
|
7
|
+
{
|
|
8
|
+
"id": "zw-hash-001",
|
|
9
|
+
"description": "Constitution of Zimbabwe (2013), Section 1 — Republic of Zimbabwe (stable constitutional anchor)",
|
|
10
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2013/amendment-no-20/eng",
|
|
11
|
+
"selector_hint": "Section 1",
|
|
12
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
13
|
+
"expected_snippet": "Republic of Zimbabwe"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "zw-hash-002",
|
|
17
|
+
"description": "Cyber and Data Protection Act 2021, Section 2 — interpretation and definitions",
|
|
18
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2021/5/eng",
|
|
19
|
+
"selector_hint": "Section 2",
|
|
20
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
21
|
+
"expected_snippet": "interpretation"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "zw-hash-003",
|
|
25
|
+
"description": "Cyber and Data Protection Act 2021, Section 3 — objects of Act (data protection and cybersecurity purposes)",
|
|
26
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2021/5/eng",
|
|
27
|
+
"selector_hint": "Section 3",
|
|
28
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
29
|
+
"expected_snippet": "objects"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "zw-hash-004",
|
|
33
|
+
"description": "Access to Information and Protection of Privacy Act (AIPPA), Section 1 — short title",
|
|
34
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2002/5/eng",
|
|
35
|
+
"selector_hint": "Section 1",
|
|
36
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
37
|
+
"expected_snippet": "Access to Information and Protection of Privacy"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "zw-hash-005",
|
|
41
|
+
"description": "Criminal Law (Codification and Reform) Act (Chapter 9:23), Section 1 — short title and commencement",
|
|
42
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2004/23/eng",
|
|
43
|
+
"selector_hint": "Section 1",
|
|
44
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
45
|
+
"expected_snippet": "Criminal Law"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "zw-hash-006",
|
|
49
|
+
"description": "Postal and Telecommunications Act (Chapter 12:05), Section 1 — short title",
|
|
50
|
+
"upstream_url": "https://zimlii.org/zw/legislation/act/2000/4/eng",
|
|
51
|
+
"selector_hint": "Section 1",
|
|
52
|
+
"expected_sha256": "COMPUTE_ON_FIRST_INGEST",
|
|
53
|
+
"expected_snippet": "Postal and Telecommunications"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|