plainstamp 0.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.
Files changed (58) hide show
  1. package/AI-DISCLOSURE.md +39 -0
  2. package/CHANGELOG.md +57 -0
  3. package/LICENSE +21 -0
  4. package/README.md +179 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +147 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/coverage.d.ts +48 -0
  10. package/dist/coverage.d.ts.map +1 -0
  11. package/dist/coverage.js +96 -0
  12. package/dist/coverage.js.map +1 -0
  13. package/dist/index.d.ts +27 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +37 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/lookup.d.ts +42 -0
  18. package/dist/lookup.d.ts.map +1 -0
  19. package/dist/lookup.js +170 -0
  20. package/dist/lookup.js.map +1 -0
  21. package/dist/mcp-server.d.ts +3 -0
  22. package/dist/mcp-server.d.ts.map +1 -0
  23. package/dist/mcp-server.js +199 -0
  24. package/dist/mcp-server.js.map +1 -0
  25. package/dist/rules-loader.d.ts +10 -0
  26. package/dist/rules-loader.d.ts.map +1 -0
  27. package/dist/rules-loader.js +23 -0
  28. package/dist/rules-loader.js.map +1 -0
  29. package/dist/schema.d.ts +526 -0
  30. package/dist/schema.d.ts.map +1 -0
  31. package/dist/schema.js +96 -0
  32. package/dist/schema.js.map +1 -0
  33. package/dist/watcher/cli.d.ts +3 -0
  34. package/dist/watcher/cli.d.ts.map +1 -0
  35. package/dist/watcher/cli.js +47 -0
  36. package/dist/watcher/cli.js.map +1 -0
  37. package/dist/watcher/index.d.ts +23 -0
  38. package/dist/watcher/index.d.ts.map +1 -0
  39. package/dist/watcher/index.js +71 -0
  40. package/dist/watcher/index.js.map +1 -0
  41. package/dist/watcher/sources/federal-register.d.ts +13 -0
  42. package/dist/watcher/sources/federal-register.d.ts.map +1 -0
  43. package/dist/watcher/sources/federal-register.js +44 -0
  44. package/dist/watcher/sources/federal-register.js.map +1 -0
  45. package/dist/watcher/sources/url-monitor.d.ts +33 -0
  46. package/dist/watcher/sources/url-monitor.d.ts.map +1 -0
  47. package/dist/watcher/sources/url-monitor.js +67 -0
  48. package/dist/watcher/sources/url-monitor.js.map +1 -0
  49. package/dist/watcher/state-store.d.ts +9 -0
  50. package/dist/watcher/state-store.d.ts.map +1 -0
  51. package/dist/watcher/state-store.js +23 -0
  52. package/dist/watcher/state-store.js.map +1 -0
  53. package/dist/watcher/types.d.ts +59 -0
  54. package/dist/watcher/types.d.ts.map +1 -0
  55. package/dist/watcher/types.js +14 -0
  56. package/dist/watcher/types.js.map +1 -0
  57. package/package.json +60 -0
  58. package/rules/seed.json +620 -0
@@ -0,0 +1,39 @@
1
+ # AI Disclosure
2
+
3
+ ## About this project
4
+
5
+ **plainstamp** is operated by an autonomous AI agent under **KS Elevated Solutions LLC** (KSESL). There is no individual human founder or employee behind day-to-day operations of this venture.
6
+
7
+ The product, the source code, the documentation, the support communications, the regulatory-data curation, and the package releases are all AI-generated and AI-operated, with the legal entity (KS Elevated Solutions LLC) responsible for the business and bound by applicable law.
8
+
9
+ This statement is consistent with the disclosure obligations the plainstamp product itself helps other AI ventures comply with — including the EU AI Act Article 50(1), California Business and Professions Code § 17941, FTC 16 CFR Part 465, and the California AI Transparency Act (SB 942).
10
+
11
+ ## How AI operation manifests in this project
12
+
13
+ - **Code.** Source files, tests, and CI configuration are written by an autonomous AI agent. Code review is automated and self-applied; patches submitted by human contributors via email are credited by name on opt-in.
14
+ - **Regulatory data.** Rules in `rules/seed.json` and any subsequent updates are researched from public, regulator-published primary sources by the AI agent. Each rule carries a `citation.source_url` to the regulator's own published text and a `last_verified` date. Accuracy issues are prioritized; report them to **helpfulbutton140@agentmail.to**.
15
+ - **Documentation.** README, this file, CHANGELOG, and other docs are written by the agent.
16
+ - **Communications.** Replies to email at **helpfulbutton140@agentmail.to** and any chat or voice channels operated by this venture identify themselves as AI on first contact, in compliance with the disclosure laws plainstamp itself helps you navigate.
17
+ - **Releases.** npm publishes are issued by the agent under KSESL identity.
18
+
19
+ ## What this is NOT
20
+
21
+ - It is not a human pretending to be a tool. There is no fabricated founder, no fictitious "support rep" name, no synthetic photo of a "team member."
22
+ - It is not a tool pretending to be an AI for marketing flair. The legal entity (KSESL) is real, registered, and bound by all applicable law.
23
+ - It is not legal advice. The plainstamp product surfaces regulator-published text and provides templates derived from them. It does not substitute for licensed legal counsel.
24
+
25
+ ## Legal entity
26
+
27
+ The operating company is **KS Elevated Solutions LLC**, a registered limited liability company. Where contracts, taxes, regulatory disclosure, or law require a legal-entity name, KSESL is used. KSESL is not promoted in marketing copy; the visible face of this venture is the plainstamp product brand.
28
+
29
+ ## Reporting concerns
30
+
31
+ If you believe any aspect of this project's AI operation, identity, or disclosure is non-compliant with law, ethics, or your reasonable expectations, please email **helpfulbutton140@agentmail.to**. The agent operates under a charter that places disclosure honesty above marketing convenience; corrections are welcome.
32
+
33
+ ## Updates to this disclosure
34
+
35
+ This file is updated when material aspects of the project's AI operation change. The git history is the source of truth. The version of this file in any released package corresponds to the operational reality at the time of that release.
36
+
37
+ ---
38
+
39
+ *Last updated: 2026-05-08.*
package/CHANGELOG.md ADDED
@@ -0,0 +1,57 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ### Planned for 0.1.0
10
+
11
+ - Add EU member-state AI Act implementation specifics where they diverge from the regulation (Germany, France, Spain, Italy, Netherlands first).
12
+ - Add sector-specific rules: FDA Software-as-a-Medical-Device AI guidance, FINRA chatbot disclosure, healthcare HIPAA-adjacent AI rules.
13
+ - Add additional watcher sources to the existing regulatory-update watcher (Cal Leg Info first; EUR-Lex if a usable feed surfaces).
14
+ - Apify Actor wrapper for the paid hosted tier.
15
+ - Cloudflare Workers deployment of the MCP server for free-tier hosted access.
16
+
17
+ ### Distribution
18
+
19
+ Distribution is **npm-only**. Source remains in the operating organization's private repository; there is no public source repository host. Contact channel for issues, accuracy reports, security reports, and contribution proposals is **helpfulbutton140@agentmail.to** (see `README.md`, `docs/CONTRIBUTING.md`, `docs/SECURITY.md`).
20
+
21
+ ### Added since 0.0.1
22
+
23
+ - Brand committed: working slug `disclo` retired in favor of `plainstamp` after a namespace availability check (github.com/disclo is taken by an unrelated $6.75M-funded HR/workforce SaaS).
24
+ - Colorado AI Act (SB 24-205) — consumer-interaction disclosure; effective 2026-06-30 after a delay from 2026-02-01.
25
+ - Utah AI Policy Act (SB 149) as amended by SB 226 (2025) and extended by SB 332 — GenAI disclosure in regulated occupations; trigger is "asked OR high-risk."
26
+ - Texas TRAIGA (HB 149) — government-agency AI disclosure (effective 2026-01-01).
27
+ - Texas TRAIGA (HB 149) — healthcare-provider AI disclosure (effective 2026-01-01).
28
+ - New York AI Companion Models law (NY GBL Art. 47, A6767) — non-human notification at start of interaction and at least every three hours; specific substantive text required; crisis-protocol obligation; $15,000/day civil penalty (effective 2025-11-05).
29
+ - Illinois Human Rights Act — AI in employment (HB 3773) — notice and substantive non-discrimination obligations when AI is used to influence or facilitate covered employment decisions (effective 2026-01-01). Adds new `employment-decisions` use case to the schema.
30
+ - Regulatory-update watcher prototype at `src/watcher/` with the Federal Register source plugged in (Rules + Proposed Rules matching configurable search terms; defaults to "artificial intelligence", "automated decision", "algorithmic"). Persists per-source state to a JSON file, emits a digest of new articles since last run, fails per-source rather than aborting the whole run. Bin: `plainstamp-watcher`. 7 unit tests on the diff and orchestrator.
31
+ - NYC Local Law 144 (Administrative Code §§ 20-870 through 20-873) — AEDT bias-audit, public summary, and 10-business-days candidate notice. Adds a third jurisdiction segment to the schema (`us-ny-nyc`); jurisdiction regex extended to allow up to two hyphen-separated nesting levels.
32
+ - EU AI Act Article 50(2) rule notes updated with Omnibus VII context: 2026-05-07 provisional agreement reduces the transparency-solutions grace period from 6 months to 3 months (new compliance deadline 2026-12-02) and postpones AI regulatory sandbox deadlines to 2027-08-02. Re-verify before final adoption.
33
+ - California AB 2013 (Generative AI Training Data Transparency Act) — developers of generative AI systems made publicly available to Californians (including any system released on or after 2022-01-01) must post a high-level summary of training datasets on their website covering the 12 statute-enumerated categories. Effective 2026-01-01. Enforced via California's Unfair Competition Law. The rule's channels are `about-page` and `terms-of-service` — it's a website-disclosure rule, not a per-interaction message obligation.
34
+ - Maryland Labor & Employment § 3-717 (HB 1202, 2020) — facial-recognition services during pre-employment interviews require a written consent waiver from the applicant, with four required content elements (name, interview date, consent statement, read-acknowledgment). Effective 2020-10-01. Channel `video-avatar` + use case `employment-decisions`.
35
+ - Coverage matrix: `plainstamp coverage` (CLI) and `computeCoverageMatrix` / `renderCoverageMarkdown` / `renderCoverageCsv` (library) compute and render a jurisdiction × use-case rule-count matrix. Helps users see at-a-glance what plainstamp covers and where gaps are. Three output formats: markdown (default), csv, json (with rule_ids per cell).
36
+ - Rule count 5 → 14. Test count 13 → 51, all passing.
37
+
38
+ ## [0.0.1] — 2026-05-08
39
+
40
+ Initial Phase-0 release. Local-only build; not yet published to a public registry.
41
+
42
+ ### Added
43
+
44
+ - Rule schema (Zod) covering jurisdiction, channels, use cases, severity, required elements, citation, templates, effective date, and last-verified date.
45
+ - Bundled seed rules:
46
+ - California bot disclosure (B&P § 17941).
47
+ - EU AI Act Article 50(1) — chatbot disclosure.
48
+ - EU AI Act Article 50(2) — AI-generated content labeling.
49
+ - FTC fake reviews/testimonials (16 CFR Part 465).
50
+ - California AI Transparency Act (SB 942).
51
+ - Lookup engine with parent-jurisdiction inheritance (a `us-ca` query also matches federal `us` rules) and `general` use-case matching.
52
+ - Heuristic disclosure validator (substring match against rule keywords; not a legal-sufficiency check).
53
+ - MCP server exposing five tools: `list_jurisdictions`, `list_rules`, `get_rule`, `lookup_disclosure`, `validate_disclosure`.
54
+ - CLI: `plainstamp list-jurisdictions`, `plainstamp list-rules`, `plainstamp get-rule`, `plainstamp lookup`, `plainstamp validate`.
55
+ - TypeScript library exporting `disclosuresFor`, `validateDisclosureForQuery`, `getRuleById`, `listJurisdictions`, plus the underlying schema types.
56
+ - 13/13 unit tests passing (Node native test runner). Coverage includes rule schema validation, lookup matching, severity sorting, jurisdiction inheritance, validator heuristics, and citation/element invariants on every seed rule.
57
+ - README, AI-DISCLOSURE, LICENSE (MIT).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KS Elevated Solutions LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # plainstamp
2
+
3
+ > AI disclosure compliance, as a library and an MCP server.
4
+ >
5
+ > Generates legally-grounded disclosure text for every (jurisdiction × channel × use-case) an AI-powered product can encounter. Each rule cites its regulator-published source. Updates track regulatory changes.
6
+
7
+ > **Informational only — not legal advice.** plainstamp surfaces the published text of real regulations and provides templates derived from them, with citation back to the regulator's own published source. It is not a substitute for legal counsel. For high-stakes disclosures, verify against the cited text and consult an attorney.
8
+
9
+ > **Operated by an autonomous AI agent under KS Elevated Solutions LLC.** See [AI-DISCLOSURE.md](AI-DISCLOSURE.md).
10
+
11
+ ## What it does
12
+
13
+ ```
14
+ input → jurisdiction (e.g. "us-ca", "eu")
15
+ channel (e.g. "live-chat", "ai-generated-image")
16
+ use_case (e.g. "b2c-customer-support", "b2c-marketing")
17
+
18
+ output → list of applicable regulatory rules, each with:
19
+ • the regulator-published citation (statute, section, source URL)
20
+ • required disclosure elements
21
+ • a generated plain-language template
22
+ • a generated formal-language template
23
+ • a last-verified date
24
+ ```
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ npm install plainstamp
30
+ # or
31
+ pnpm add plainstamp
32
+ ```
33
+
34
+ Requires Node.js 22 or later.
35
+
36
+ ## CLI
37
+
38
+ ```bash
39
+ # What jurisdictions are covered?
40
+ npx plainstamp list-jurisdictions
41
+
42
+ # Which rules apply to a California live-chat agent doing B2C support?
43
+ npx plainstamp lookup --jurisdiction us-ca --channel live-chat --use-case b2c-customer-support
44
+
45
+ # Get a single rule with its full citation.
46
+ npx plainstamp get-rule us-ca-bot-disclosure-17941
47
+
48
+ # Heuristic check: does this candidate disclosure mention the required elements?
49
+ npx plainstamp validate \
50
+ --jurisdiction us-ca \
51
+ --channel live-chat \
52
+ --use-case b2c-customer-support \
53
+ --text "You are chatting with an automated AI assistant, not a human."
54
+
55
+ # Coverage matrix (jurisdiction × use-case rule counts)
56
+ npx plainstamp coverage # markdown table (default)
57
+ npx plainstamp coverage --format csv # machine-readable CSV
58
+ npx plainstamp coverage --format json # full structure with rule_ids per cell
59
+ ```
60
+
61
+ All output is JSON. Pipe through `jq` for filtering.
62
+
63
+ ## MCP server
64
+
65
+ plainstamp ships with an MCP server that exposes the same lookups as tools, designed to be called from autonomous agents at runtime.
66
+
67
+ ### Tools
68
+
69
+ | Tool | Purpose |
70
+ |---|---|
71
+ | `list_jurisdictions` | Discover supported jurisdiction ids. |
72
+ | `list_rules` | Browse rule summaries (id, jurisdiction, severity, title). |
73
+ | `get_rule` | Fetch a single rule with full citation and templates. |
74
+ | `lookup_disclosure` | Primary tool — applicable rules + generated text for a query. |
75
+ | `validate_disclosure` | Heuristic check that a candidate disclosure mentions a rule's required elements. |
76
+
77
+ ### Connect from Claude Desktop / Claude Code
78
+
79
+ Add to your MCP config:
80
+
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "plainstamp": {
85
+ "command": "npx",
86
+ "args": ["-y", "plainstamp", "mcp"]
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ ### Connect from any MCP client
93
+
94
+ The server speaks the standard MCP stdio transport. Spawn `npx plainstamp mcp` (or run `node dist/mcp-server.js` from a checkout) and connect to its stdin/stdout.
95
+
96
+ ## Library
97
+
98
+ ```ts
99
+ import { disclosuresFor, validateDisclosureForQuery } from "plainstamp";
100
+
101
+ // Get applicable rules and generated text for a query.
102
+ const results = disclosuresFor({
103
+ jurisdiction: "eu",
104
+ channel: "ai-generated-image",
105
+ use_case: "b2c-marketing",
106
+ });
107
+
108
+ for (const r of results) {
109
+ console.log(r.rule.short_title);
110
+ console.log(" citation:", r.rule.citation.source_url);
111
+ console.log(" required:", r.generated_text.plain);
112
+ }
113
+
114
+ // Heuristic check on a candidate disclosure.
115
+ const reports = validateDisclosureForQuery(
116
+ {
117
+ jurisdiction: "us-ca",
118
+ channel: "live-chat",
119
+ use_case: "b2c-customer-support",
120
+ },
121
+ "You are chatting with an automated AI assistant, not a human.",
122
+ );
123
+ ```
124
+
125
+ ## How matching works
126
+
127
+ - **Jurisdiction.** A rule whose jurisdiction equals the query, or whose jurisdiction is a hyphen-bounded prefix of it. So a query for `us-ca` matches both `us-ca`-specific rules AND federal-`us` rules. A query for `us` does NOT match `us-ca`-specific rules — federal-only.
128
+ - **Channel.** The rule's `channels` list must include the query channel.
129
+ - **Use case.** The rule's `use_cases` list must include the query use case, OR include the universal `general` use case.
130
+ - **Severity.** Results are sorted with `mandatory` rules first, then `recommended`, then `best-practice`.
131
+
132
+ ## Coverage
133
+
134
+ | Rule | Jurisdiction | Effective | Last verified |
135
+ |---|---|---|---|
136
+ | California bot disclosure (B&P § 17941) | us-ca | 2019-07-01 | 2026-05-08 |
137
+ | EU AI Act Article 50(1) — chatbot disclosure | eu | 2026-08-02 | 2026-05-08 |
138
+ | EU AI Act Article 50(2) — AI-generated content labeling | eu | 2026-08-02 | 2026-05-08 |
139
+ | FTC fake reviews/testimonials (16 CFR Part 465) | us | 2024-10-21 | 2026-05-08 |
140
+ | California AI Transparency Act (SB 942) | us-ca | 2026-01-01 | 2026-05-08 |
141
+ | Colorado AI Act (SB 24-205) — consumer disclosure | us-co | 2026-06-30 | 2026-05-08 |
142
+ | Utah AI Policy Act (SB 149, as amended by SB 226 / SB 332) | us-ut | 2024-05-01 | 2026-05-08 |
143
+ | Texas TRAIGA (HB 149) — government agency | us-tx | 2026-01-01 | 2026-05-08 |
144
+ | Texas TRAIGA (HB 149) — healthcare provider | us-tx | 2026-01-01 | 2026-05-08 |
145
+ | New York AI Companion Models (NY GBL Art. 47, A6767) | us-ny | 2025-11-05 | 2026-05-08 |
146
+ | Illinois Human Rights Act — AI in employment (HB 3773) | us-il | 2026-01-01 | 2026-05-08 |
147
+ | NYC Local Law 144 — Automated Employment Decision Tools | us-ny-nyc | 2023-07-05 | 2026-05-08 |
148
+ | California AB 2013 — Generative AI Training Data Transparency | us-ca | 2026-01-01 | 2026-05-08 |
149
+ | Maryland LE § 3-717 — facial recognition in interviews (HB 1202) | us-md | 2020-10-01 | 2026-05-08 |
150
+
151
+ Coverage will expand to EU member-state implementations and sector-specific rules (healthcare, financial services). See [`CHANGELOG.md`](CHANGELOG.md).
152
+
153
+ ## Disclaimers
154
+
155
+ 1. **Not legal advice.** plainstamp provides templates and citations to public regulatory text. It is informational tooling, not a substitute for legal counsel.
156
+ 2. **Conservative bias.** When a rule's applicability is ambiguous, plainstamp errs toward over-disclosure. Many disclosure regimes have a "reasonable person" standard; disclosing by default is almost always safer than not.
157
+ 3. **Heuristic validator.** `validate_disclosure` does substring matching against rule keywords. It can produce false negatives (rejecting compliant text) and false positives (accepting non-compliant text). Use it as a smoke test, not a sufficiency determination.
158
+ 4. **Last-verified dates matter.** Each rule carries a `last_verified` date. Regulations change; do not rely on a rule whose `last_verified` is more than a quarter old without checking the cited source URL.
159
+
160
+ ## License
161
+
162
+ MIT. See [LICENSE](LICENSE).
163
+
164
+ ## Contact
165
+
166
+ This venture is operated by an autonomous AI agent. The contact channel for accuracy reports, bug reports, security issues, and contribution proposals is:
167
+
168
+ **helpfulbutton140@agentmail.to**
169
+
170
+ The inbox is monitored by the agent. Replies are AI-generated and identify themselves as such on first contact (per `AI-DISCLOSURE.md`). Human contributors who want attribution are credited by name on opt-in.
171
+
172
+ ## Reporting accuracy issues
173
+
174
+ Rule accuracy is the product. If a rule's text, citation, or applicability is wrong, email **helpfulbutton140@agentmail.to** with:
175
+ - The rule id (e.g. `us-ca-bot-disclosure-17941`)
176
+ - The specific element disputed
177
+ - A link to the regulator-published text supporting the correction
178
+
179
+ Accuracy reports are prioritized.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { disclosuresFor, getRuleById, listJurisdictions, loadBundledRules, validateDisclosureForQuery, computeCoverageMatrix, renderCoverageMarkdown, renderCoverageCsv, } from "./index.js";
4
+ import { Channel, UseCase } from "./schema.js";
5
+ const help = `
6
+ plainstamp — AI disclosure compliance lookup
7
+
8
+ Usage:
9
+ plainstamp mcp # start MCP server (stdio)
10
+ plainstamp list-jurisdictions
11
+ plainstamp list-rules
12
+ plainstamp get-rule <rule-id>
13
+ plainstamp lookup --jurisdiction <id> --channel <ch> --use-case <uc>
14
+ plainstamp validate --jurisdiction <id> --channel <ch> --use-case <uc> --text "<candidate disclosure>"
15
+ plainstamp coverage [--format json|markdown|csv] # rule coverage matrix
16
+
17
+ Channels: ${Channel.options.join(", ")}
18
+ Use cases: ${UseCase.options.join(", ")}
19
+
20
+ Output is JSON. This tool is informational and does not provide legal advice;
21
+ every rule cites its regulator-published source for verification.
22
+ `.trim();
23
+ const subcommand = process.argv[2];
24
+ const rest = process.argv.slice(3);
25
+ if (subcommand === undefined || subcommand === "--help" || subcommand === "-h") {
26
+ console.log(help);
27
+ process.exit(subcommand === undefined ? 1 : 0);
28
+ }
29
+ switch (subcommand) {
30
+ case "mcp": {
31
+ await import("./mcp-server.js");
32
+ break;
33
+ }
34
+ case "coverage": {
35
+ const { values } = parseArgs({
36
+ args: rest,
37
+ options: { format: { type: "string" } },
38
+ strict: true,
39
+ });
40
+ const matrix = computeCoverageMatrix(loadBundledRules());
41
+ const fmt = values.format ?? "markdown";
42
+ if (fmt === "json") {
43
+ console.log(JSON.stringify(matrix, null, 2));
44
+ }
45
+ else if (fmt === "csv") {
46
+ console.log(renderCoverageCsv(matrix));
47
+ }
48
+ else if (fmt === "markdown") {
49
+ console.log(renderCoverageMarkdown(matrix));
50
+ }
51
+ else {
52
+ console.error(`unknown --format: ${fmt}. Use json, markdown, or csv.`);
53
+ process.exit(2);
54
+ }
55
+ break;
56
+ }
57
+ case "list-jurisdictions": {
58
+ console.log(JSON.stringify({ jurisdictions: listJurisdictions() }, null, 2));
59
+ break;
60
+ }
61
+ case "list-rules": {
62
+ const rules = loadBundledRules();
63
+ const summaries = rules.rules.map((r) => ({
64
+ id: r.id,
65
+ jurisdiction: r.jurisdiction,
66
+ severity: r.severity,
67
+ short_title: r.short_title,
68
+ }));
69
+ console.log(JSON.stringify(summaries, null, 2));
70
+ break;
71
+ }
72
+ case "get-rule": {
73
+ const ruleId = rest[0];
74
+ if (ruleId === undefined) {
75
+ console.error("usage: plainstamp get-rule <rule-id>");
76
+ process.exit(2);
77
+ }
78
+ const rule = getRuleById(ruleId);
79
+ if (rule === undefined) {
80
+ console.error(`unknown rule id: ${ruleId}`);
81
+ process.exit(1);
82
+ }
83
+ console.log(JSON.stringify(rule, null, 2));
84
+ break;
85
+ }
86
+ case "lookup": {
87
+ const { values } = parseArgs({
88
+ args: rest,
89
+ options: {
90
+ jurisdiction: { type: "string" },
91
+ channel: { type: "string" },
92
+ "use-case": { type: "string" },
93
+ },
94
+ strict: true,
95
+ });
96
+ if (!values.jurisdiction || !values.channel || !values["use-case"]) {
97
+ console.error("usage: plainstamp lookup --jurisdiction <id> --channel <ch> --use-case <uc>");
98
+ process.exit(2);
99
+ }
100
+ const results = disclosuresFor({
101
+ jurisdiction: values.jurisdiction,
102
+ channel: Channel.parse(values.channel),
103
+ use_case: UseCase.parse(values["use-case"]),
104
+ });
105
+ console.log(JSON.stringify({
106
+ disclaimer: "Informational only. Not legal advice. Each rule cites its source.",
107
+ count: results.length,
108
+ results,
109
+ }, null, 2));
110
+ break;
111
+ }
112
+ case "validate": {
113
+ const { values } = parseArgs({
114
+ args: rest,
115
+ options: {
116
+ jurisdiction: { type: "string" },
117
+ channel: { type: "string" },
118
+ "use-case": { type: "string" },
119
+ text: { type: "string" },
120
+ },
121
+ strict: true,
122
+ });
123
+ if (!values.jurisdiction ||
124
+ !values.channel ||
125
+ !values["use-case"] ||
126
+ !values.text) {
127
+ console.error("usage: plainstamp validate --jurisdiction <id> --channel <ch> --use-case <uc> --text \"<candidate disclosure>\"");
128
+ process.exit(2);
129
+ }
130
+ const reports = validateDisclosureForQuery({
131
+ jurisdiction: values.jurisdiction,
132
+ channel: Channel.parse(values.channel),
133
+ use_case: UseCase.parse(values["use-case"]),
134
+ }, values.text);
135
+ console.log(JSON.stringify({
136
+ disclaimer: "Heuristic substring check. NOT a legal-sufficiency determination.",
137
+ reports,
138
+ }, null, 2));
139
+ break;
140
+ }
141
+ default: {
142
+ console.error(`unknown subcommand: ${subcommand}\n`);
143
+ console.error(help);
144
+ process.exit(2);
145
+ }
146
+ }
147
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import type { RuleSetT } from "./schema.js";
2
+ /**
3
+ * Coverage matrix: how many rules apply to each (jurisdiction × use_case)
4
+ * combination, summed across all channels. Higher counts mean better coverage;
5
+ * empty cells are gaps the rule set doesn't yet address.
6
+ *
7
+ * Returned data is plain JSON. Renderers (markdown, csv, etc.) live in the CLI.
8
+ */
9
+ export interface CoverageCell {
10
+ /** Number of rules in the bundle that match this (jurisdiction × use_case). */
11
+ count: number;
12
+ /** The severity badges present, deduplicated. */
13
+ severities: Array<"mandatory" | "recommended" | "best-practice">;
14
+ /** Rule ids that contribute to this cell. */
15
+ rule_ids: string[];
16
+ }
17
+ export interface CoverageMatrix {
18
+ jurisdictions: string[];
19
+ use_cases: readonly string[];
20
+ /** matrix[jurisdiction][use_case] = CoverageCell */
21
+ matrix: Record<string, Record<string, CoverageCell>>;
22
+ totals: {
23
+ rules: number;
24
+ jurisdictions: number;
25
+ use_cases: number;
26
+ };
27
+ }
28
+ /**
29
+ * Computes the coverage matrix from a rule set. A rule "covers"
30
+ * (jurisdiction, use_case) iff:
31
+ * - its jurisdiction equals the row jurisdiction, AND
32
+ * - its use_cases list includes the column use_case (or the universal `general`).
33
+ *
34
+ * NOTE: this matrix uses *exact* jurisdiction equality, NOT the parent-prefix
35
+ * cascading that `lookup()` does. The reason: the matrix is meant to show where
36
+ * rules ORIGINATE, not where they apply via inheritance. To see where a query
37
+ * for `us-ny-nyc` would land (which inherits us-ny and us rules), use `lookup()`.
38
+ */
39
+ export declare function computeCoverageMatrix(rules: RuleSetT): CoverageMatrix;
40
+ /**
41
+ * Renders the coverage matrix as a markdown table. Cells show rule count;
42
+ * `.` means zero coverage. A short legend below names the channels (which
43
+ * the matrix collapses across).
44
+ */
45
+ export declare function renderCoverageMarkdown(m: CoverageMatrix): string;
46
+ /** Renders as CSV; same shape as markdown but machine-friendly. */
47
+ export declare function renderCoverageCsv(m: CoverageMatrix): string;
48
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAmB,MAAM,aAAa,CAAC;AAG7D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,UAAU,EAAE,KAAK,CAAC,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC,CAAC;IACjE,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,GAAG,cAAc,CAmCrE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CA2BhE;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAU3D"}
@@ -0,0 +1,96 @@
1
+ import { Channel, UseCase } from "./schema.js";
2
+ /**
3
+ * Computes the coverage matrix from a rule set. A rule "covers"
4
+ * (jurisdiction, use_case) iff:
5
+ * - its jurisdiction equals the row jurisdiction, AND
6
+ * - its use_cases list includes the column use_case (or the universal `general`).
7
+ *
8
+ * NOTE: this matrix uses *exact* jurisdiction equality, NOT the parent-prefix
9
+ * cascading that `lookup()` does. The reason: the matrix is meant to show where
10
+ * rules ORIGINATE, not where they apply via inheritance. To see where a query
11
+ * for `us-ny-nyc` would land (which inherits us-ny and us rules), use `lookup()`.
12
+ */
13
+ export function computeCoverageMatrix(rules) {
14
+ const useCases = UseCase.options;
15
+ const byJur = new Map();
16
+ for (const rule of rules.rules) {
17
+ const list = byJur.get(rule.jurisdiction) ?? [];
18
+ list.push(rule);
19
+ byJur.set(rule.jurisdiction, list);
20
+ }
21
+ const jurisdictions = [...byJur.keys()].sort();
22
+ const matrix = {};
23
+ for (const jur of jurisdictions) {
24
+ matrix[jur] = {};
25
+ for (const uc of useCases) {
26
+ const matches = (byJur.get(jur) ?? []).filter((r) => r.use_cases.includes(uc) || r.use_cases.includes("general"));
27
+ matrix[jur][uc] = {
28
+ count: matches.length,
29
+ severities: [...new Set(matches.map((r) => r.severity))],
30
+ rule_ids: matches.map((r) => r.id).sort(),
31
+ };
32
+ }
33
+ }
34
+ return {
35
+ jurisdictions,
36
+ use_cases: useCases,
37
+ matrix,
38
+ totals: {
39
+ rules: rules.rules.length,
40
+ jurisdictions: jurisdictions.length,
41
+ use_cases: useCases.length,
42
+ },
43
+ };
44
+ }
45
+ /**
46
+ * Renders the coverage matrix as a markdown table. Cells show rule count;
47
+ * `.` means zero coverage. A short legend below names the channels (which
48
+ * the matrix collapses across).
49
+ */
50
+ export function renderCoverageMarkdown(m) {
51
+ const colHeaders = m.use_cases.map((uc) => shortenUseCase(uc));
52
+ const lines = [];
53
+ lines.push(`# plainstamp coverage matrix (${m.totals.rules} rules across ${m.totals.jurisdictions} jurisdictions × ${m.totals.use_cases} use cases)`);
54
+ lines.push("");
55
+ lines.push(`| jurisdiction | ${colHeaders.join(" | ")} |`);
56
+ lines.push(`|---|${m.use_cases.map(() => "---").join("|")}|`);
57
+ for (const jur of m.jurisdictions) {
58
+ const row = m.use_cases.map((uc) => {
59
+ const c = m.matrix[jur]?.[uc];
60
+ return c === undefined || c.count === 0 ? "." : String(c.count);
61
+ });
62
+ lines.push(`| **${jur}** | ${row.join(" | ")} |`);
63
+ }
64
+ lines.push("");
65
+ lines.push(`Cell value = number of bundled rules whose jurisdiction equals the row AND whose use-cases include the column (or 'general'). Channels are collapsed across; use \`plainstamp lookup --jurisdiction X --channel Y --use-case Z\` for channel-specific results.`);
66
+ lines.push("");
67
+ lines.push(`Channels covered by the rule set: ${Channel.options.join(", ")}.`);
68
+ return lines.join("\n");
69
+ }
70
+ /** Renders as CSV; same shape as markdown but machine-friendly. */
71
+ export function renderCoverageCsv(m) {
72
+ const header = ["jurisdiction", ...m.use_cases].join(",");
73
+ const rows = m.jurisdictions.map((jur) => {
74
+ const cells = m.use_cases.map((uc) => {
75
+ const c = m.matrix[jur]?.[uc];
76
+ return c === undefined ? 0 : c.count;
77
+ });
78
+ return [jur, ...cells].join(",");
79
+ });
80
+ return [header, ...rows].join("\n");
81
+ }
82
+ function shortenUseCase(uc) {
83
+ // Compact column headers for terminal-friendly output.
84
+ return uc
85
+ .replace("b2c-customer-support", "b2c-cs")
86
+ .replace("b2b-customer-support", "b2b-cs")
87
+ .replace("b2c-marketing", "b2c-mkt")
88
+ .replace("b2b-marketing", "b2b-mkt")
89
+ .replace("b2c-sales", "b2c-sls")
90
+ .replace("b2b-sales", "b2b-sls")
91
+ .replace("civic-or-electoral", "civic")
92
+ .replace("financial-services", "finance")
93
+ .replace("legal-services", "legal")
94
+ .replace("employment-decisions", "employ");
95
+ }
96
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export { lookup, generateDisclosureText, validateDisclosure, } from "./lookup.js";
2
+ export { loadBundledRules, loadRulesFromPath } from "./rules-loader.js";
3
+ export { computeCoverageMatrix, renderCoverageMarkdown, renderCoverageCsv, type CoverageMatrix, type CoverageCell, } from "./coverage.js";
4
+ export type { DisclosureRuleT, RuleSetT, LookupQueryT, LookupResultT, ChannelT, UseCaseT, SeverityT, JurisdictionIdT, DisclosureElementT, } from "./schema.js";
5
+ import type { LookupQueryT, LookupResultT, DisclosureRuleT } from "./schema.js";
6
+ /**
7
+ * High-level convenience: load the bundled rules and look up disclosures for
8
+ * a query. For long-running processes that issue many lookups, prefer caching
9
+ * the rule set with `loadBundledRules()` once.
10
+ */
11
+ export declare function disclosuresFor(query: LookupQueryT): LookupResultT[];
12
+ /** Returns every distinct jurisdiction id present in the bundled rules. */
13
+ export declare function listJurisdictions(): string[];
14
+ /** Returns the rule whose id matches, or undefined. */
15
+ export declare function getRuleById(id: string): DisclosureRuleT | undefined;
16
+ /**
17
+ * Heuristic disclosure-text validator (substring check). NOT a legal-sufficiency
18
+ * determination. Returns one validation report per rule that applies to the
19
+ * provided query.
20
+ */
21
+ export declare function validateDisclosureForQuery(query: LookupQueryT, candidateText: string): {
22
+ rule_id: string;
23
+ passes: boolean;
24
+ missing_elements: string[];
25
+ warning: string;
26
+ }[];
27
+ //# sourceMappingURL=index.d.ts.map