@planu/cli 0.45.5 → 0.47.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.
Files changed (68) hide show
  1. package/dist/config/license-plans.json +2 -0
  2. package/dist/config/mcp-archetypes.json +872 -0
  3. package/dist/config/tool-groups.json +2 -0
  4. package/dist/engine/detectors/mcp-candidate-detector.d.ts +13 -0
  5. package/dist/engine/detectors/mcp-candidate-detector.d.ts.map +1 -0
  6. package/dist/engine/detectors/mcp-candidate-detector.js +245 -0
  7. package/dist/engine/detectors/mcp-candidate-detector.js.map +1 -0
  8. package/dist/engine/legal-compliance/criteria-injector.d.ts +18 -0
  9. package/dist/engine/legal-compliance/criteria-injector.d.ts.map +1 -0
  10. package/dist/engine/legal-compliance/criteria-injector.js +176 -0
  11. package/dist/engine/legal-compliance/criteria-injector.js.map +1 -0
  12. package/dist/engine/legal-compliance/detector.d.ts +25 -0
  13. package/dist/engine/legal-compliance/detector.d.ts.map +1 -0
  14. package/dist/engine/legal-compliance/detector.js +515 -0
  15. package/dist/engine/legal-compliance/detector.js.map +1 -0
  16. package/dist/engine/legal-compliance/index.d.ts +4 -0
  17. package/dist/engine/legal-compliance/index.d.ts.map +1 -0
  18. package/dist/engine/legal-compliance/index.js +5 -0
  19. package/dist/engine/legal-compliance/index.js.map +1 -0
  20. package/dist/engine/legal-compliance/question-framework.d.ts +14 -0
  21. package/dist/engine/legal-compliance/question-framework.d.ts.map +1 -0
  22. package/dist/engine/legal-compliance/question-framework.js +461 -0
  23. package/dist/engine/legal-compliance/question-framework.js.map +1 -0
  24. package/dist/tools/create-spec/mcp-layer-adapter.d.ts +11 -0
  25. package/dist/tools/create-spec/mcp-layer-adapter.d.ts.map +1 -0
  26. package/dist/tools/create-spec/mcp-layer-adapter.js +57 -0
  27. package/dist/tools/create-spec/mcp-layer-adapter.js.map +1 -0
  28. package/dist/tools/create-spec/spec-builder.d.ts.map +1 -1
  29. package/dist/tools/create-spec/spec-builder.js +20 -0
  30. package/dist/tools/create-spec/spec-builder.js.map +1 -1
  31. package/dist/tools/init-project/handler.d.ts.map +1 -1
  32. package/dist/tools/init-project/handler.js +6 -0
  33. package/dist/tools/init-project/handler.js.map +1 -1
  34. package/dist/tools/legal-compliance-report.d.ts +3 -0
  35. package/dist/tools/legal-compliance-report.d.ts.map +1 -0
  36. package/dist/tools/legal-compliance-report.js +65 -0
  37. package/dist/tools/legal-compliance-report.js.map +1 -0
  38. package/dist/tools/register-governance-tools.d.ts.map +1 -1
  39. package/dist/tools/register-governance-tools.js +13 -1
  40. package/dist/tools/register-governance-tools.js.map +1 -1
  41. package/dist/tools/register-spec-tools/analysis-tools.d.ts.map +1 -1
  42. package/dist/tools/register-spec-tools/analysis-tools.js +10 -1
  43. package/dist/tools/register-spec-tools/analysis-tools.js.map +1 -1
  44. package/dist/tools/suggest-mcp-server.d.ts +3 -0
  45. package/dist/tools/suggest-mcp-server.d.ts.map +1 -0
  46. package/dist/tools/suggest-mcp-server.js +86 -0
  47. package/dist/tools/suggest-mcp-server.js.map +1 -0
  48. package/dist/types/index.d.ts +2 -0
  49. package/dist/types/index.d.ts.map +1 -1
  50. package/dist/types/index.js +2 -0
  51. package/dist/types/index.js.map +1 -1
  52. package/dist/types/legal.d.ts +71 -0
  53. package/dist/types/legal.d.ts.map +1 -0
  54. package/dist/types/legal.js +3 -0
  55. package/dist/types/legal.js.map +1 -0
  56. package/dist/types/mcp-recommendation.d.ts +47 -0
  57. package/dist/types/mcp-recommendation.d.ts.map +1 -0
  58. package/dist/types/mcp-recommendation.js +3 -0
  59. package/dist/types/mcp-recommendation.js.map +1 -0
  60. package/dist/types/project/core.d.ts +2 -0
  61. package/dist/types/project/core.d.ts.map +1 -1
  62. package/dist/types/project/core.js.map +1 -1
  63. package/dist/types/spec/core.d.ts +3 -0
  64. package/dist/types/spec/core.d.ts.map +1 -1
  65. package/package.json +1 -1
  66. package/src/config/license-plans.json +2 -0
  67. package/src/config/mcp-archetypes.json +872 -0
  68. package/src/config/tool-groups.json +2 -0
@@ -109,6 +109,7 @@
109
109
  "suggest_tooling",
110
110
  "suggest_stack",
111
111
  "suggest_mcps",
112
+ "suggest_mcp_server",
112
113
  "plan_upgrade",
113
114
  "check_versions",
114
115
  "check_config_health",
@@ -127,6 +128,7 @@
127
128
  "tools": [
128
129
  "security_check",
129
130
  "data_governance",
131
+ "legal_compliance_report",
130
132
  "manage_scope",
131
133
  "manage_context",
132
134
  "context_budget",
@@ -0,0 +1,13 @@
1
+ import type { ProjectKnowledge } from '../../types/index.js';
2
+ import type { McpCandidateScore, McpAppDomain } from '../../types/mcp-recommendation.js';
3
+ /**
4
+ * Detect which application domains apply to a project based on its knowledge.
5
+ * Returns matching domains excluding 'generic'.
6
+ */
7
+ export declare function detectAppDomains(knowledge: ProjectKnowledge): McpAppDomain[];
8
+ /**
9
+ * Score whether a project is a good candidate for an MCP server layer.
10
+ * Examines API contracts, stack, external services, app types, and detected domains.
11
+ */
12
+ export declare function scoreMcpCandidate(knowledge: ProjectKnowledge): McpCandidateScore;
13
+ //# sourceMappingURL=mcp-candidate-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-candidate-detector.d.ts","sourceRoot":"","sources":["../../../src/engine/detectors/mcp-candidate-detector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AA2KzF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,GAAG,YAAY,EAAE,CAc5E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,iBAAiB,CAuEhF"}
@@ -0,0 +1,245 @@
1
+ // Planu — MCP Candidate Detector
2
+ // Scores whether a project should create an MCP server layer based on
3
+ // its ProjectKnowledge (API contracts, stack, external services, etc.).
4
+ // ---------------------------------------------------------------------------
5
+ // Keyword dictionaries
6
+ // ---------------------------------------------------------------------------
7
+ const APP_DOMAIN_KEYWORDS = {
8
+ crm: [
9
+ 'salesforce',
10
+ 'hubspot',
11
+ 'contact',
12
+ 'customer',
13
+ 'lead',
14
+ 'account',
15
+ 'deal',
16
+ 'pipeline',
17
+ 'opportunity',
18
+ 'crm',
19
+ ],
20
+ billing: [
21
+ 'invoice',
22
+ 'billing',
23
+ 'subscription',
24
+ 'payment',
25
+ 'refund',
26
+ 'chargeback',
27
+ 'pricing',
28
+ 'plan',
29
+ 'coupon',
30
+ ],
31
+ inventory: [
32
+ 'stock',
33
+ 'warehouse',
34
+ 'sku',
35
+ 'shipment',
36
+ 'order',
37
+ 'fulfillment',
38
+ 'inventory',
39
+ 'supply-chain',
40
+ ],
41
+ healthcare: [
42
+ 'patient',
43
+ 'medical',
44
+ 'health',
45
+ 'clinic',
46
+ 'hospital',
47
+ 'appointment',
48
+ 'ehr',
49
+ 'fhir',
50
+ 'hipaa',
51
+ ],
52
+ ecommerce: [
53
+ 'product',
54
+ 'cart',
55
+ 'catalog',
56
+ 'storefront',
57
+ 'marketplace',
58
+ 'shopify',
59
+ 'woocommerce',
60
+ 'checkout',
61
+ ],
62
+ 'project-mgmt': [
63
+ 'jira',
64
+ 'asana',
65
+ 'sprint',
66
+ 'task',
67
+ 'issue',
68
+ 'backlog',
69
+ 'kanban',
70
+ 'agile',
71
+ 'ticket',
72
+ ],
73
+ social: [
74
+ 'chat',
75
+ 'messaging',
76
+ 'feed',
77
+ 'timeline',
78
+ 'friend',
79
+ 'follower',
80
+ 'community',
81
+ 'post',
82
+ 'comment',
83
+ ],
84
+ gaming: ['game', 'player', 'leaderboard', 'match', 'lobby', 'multiplayer', 'score', 'level'],
85
+ iot: ['mqtt', 'sensor', 'device', 'firmware', 'telemetry', 'smart-home', 'zigbee'],
86
+ hr: ['employee', 'payroll', 'recruitment', 'hiring', 'onboarding', 'timesheet', 'leave'],
87
+ logistics: [
88
+ 'logistics',
89
+ 'shipping',
90
+ 'delivery',
91
+ 'warehouse',
92
+ 'tracking',
93
+ 'fleet',
94
+ 'route',
95
+ 'freight',
96
+ ],
97
+ media: ['content', 'publishing', 'editorial', 'streaming', 'video', 'podcast', 'cms', 'drm'],
98
+ government: ['government', 'citizen', 'municipal', 'permit', 'license', 'e-gov', 'fedramp'],
99
+ generic: [],
100
+ };
101
+ const API_FRAMEWORK_KEYWORDS = [
102
+ 'express',
103
+ 'fastify',
104
+ 'nestjs',
105
+ 'koa',
106
+ 'hapi',
107
+ 'django',
108
+ 'flask',
109
+ 'fastapi',
110
+ 'rails',
111
+ 'spring',
112
+ 'gin',
113
+ 'fiber',
114
+ 'echo',
115
+ 'actix',
116
+ 'rocket',
117
+ ];
118
+ const BACKEND_APP_TYPES = ['backend', 'api', 'server', 'worker'];
119
+ // ---------------------------------------------------------------------------
120
+ // Helpers
121
+ // ---------------------------------------------------------------------------
122
+ /** Normalize a string for keyword matching (lowercase, trim). */
123
+ function normalize(s) {
124
+ return s.toLowerCase().trim();
125
+ }
126
+ /**
127
+ * Build a flat searchable corpus from ProjectKnowledge.
128
+ * Defensive against partial data — callers may pass incomplete objects (e.g., tests with `as never`).
129
+ */
130
+ function buildCorpus(knowledge) {
131
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
132
+ const parts = [
133
+ knowledge.language ?? '',
134
+ knowledge.framework ?? '',
135
+ knowledge.orm ?? '',
136
+ knowledge.database ?? '',
137
+ knowledge.packageManager ?? '',
138
+ ...(knowledge.stack ?? []),
139
+ ...(knowledge.externalServices ?? []),
140
+ ...(knowledge.layers ?? []),
141
+ ...Object.keys(knowledge.conventions ?? {}),
142
+ ...Object.values(knowledge.conventions ?? {}),
143
+ ...Object.keys(knowledge.tooling ?? {}),
144
+ ...Object.values(knowledge.tooling ?? {}),
145
+ ...(knowledge.apiContracts ?? []).map((c) => `${c.type} ${c.endpoints.join(' ')}`),
146
+ ...(knowledge.apps ?? []).flatMap((a) => [
147
+ a.name,
148
+ a.type,
149
+ a.language,
150
+ a.framework ?? '',
151
+ a.orm ?? '',
152
+ ]),
153
+ ];
154
+ /* eslint-enable @typescript-eslint/no-unnecessary-condition */
155
+ return normalize(parts.join(' '));
156
+ }
157
+ /** Check if corpus contains any keyword from list. */
158
+ function matchesAny(corpus, keywords) {
159
+ return keywords.some((kw) => corpus.includes(normalize(kw)));
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Public API
163
+ // ---------------------------------------------------------------------------
164
+ /**
165
+ * Detect which application domains apply to a project based on its knowledge.
166
+ * Returns matching domains excluding 'generic'.
167
+ */
168
+ export function detectAppDomains(knowledge) {
169
+ const corpus = buildCorpus(knowledge);
170
+ const domains = [];
171
+ for (const [domain, keywords] of Object.entries(APP_DOMAIN_KEYWORDS)) {
172
+ if (domain === 'generic') {
173
+ continue;
174
+ }
175
+ if (matchesAny(corpus, keywords)) {
176
+ domains.push(domain);
177
+ }
178
+ }
179
+ return domains;
180
+ }
181
+ /**
182
+ * Score whether a project is a good candidate for an MCP server layer.
183
+ * Examines API contracts, stack, external services, app types, and detected domains.
184
+ */
185
+ export function scoreMcpCandidate(knowledge) {
186
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
187
+ let score = 0;
188
+ const reasons = [];
189
+ // API contracts defined → +3
190
+ const contracts = knowledge.apiContracts ?? [];
191
+ if (contracts.length > 0) {
192
+ score += 3;
193
+ reasons.push(`Project has ${contracts.length} API contracts defined`);
194
+ }
195
+ // ORM + known database → +3
196
+ const orm = knowledge.orm ?? null;
197
+ const db = knowledge.database ?? 'unknown';
198
+ if (orm && db !== 'unknown') {
199
+ score += 3;
200
+ reasons.push(`Project uses ${orm} with ${db}`);
201
+ }
202
+ // Backend/API/server/worker apps → +2
203
+ const apps = knowledge.apps ?? [];
204
+ const hasBackendApp = apps.some((a) => BACKEND_APP_TYPES.some((t) => a.type.toLowerCase().includes(t)));
205
+ if (hasBackendApp) {
206
+ score += 2;
207
+ reasons.push('Project has backend/API applications');
208
+ }
209
+ // External services → +2
210
+ const services = knowledge.externalServices ?? [];
211
+ if (services.length > 0) {
212
+ score += 2;
213
+ reasons.push(`Project integrates ${services.length} external services`);
214
+ }
215
+ // API framework in stack → +2
216
+ const stack = knowledge.stack ?? [];
217
+ const framework = knowledge.framework ?? '';
218
+ const allStackItems = [...stack, framework].map((s) => normalize(s));
219
+ const matchedFramework = API_FRAMEWORK_KEYWORDS.find((fw) => allStackItems.some((item) => item.includes(fw)));
220
+ if (matchedFramework) {
221
+ score += 2;
222
+ reasons.push(`Project uses ${matchedFramework} (API framework)`);
223
+ }
224
+ // Detected app domains → +2
225
+ const detectedDomains = detectAppDomains(knowledge);
226
+ if (detectedDomains.length > 0) {
227
+ score += 2;
228
+ reasons.push(`Detected domains: ${detectedDomains.join(', ')}`);
229
+ }
230
+ // Already uses MCP ecosystem → +1
231
+ const mcps = knowledge.availableMcps ?? [];
232
+ if (mcps.length > 0) {
233
+ score += 1;
234
+ reasons.push('Project already uses MCP ecosystem');
235
+ }
236
+ /* eslint-enable @typescript-eslint/no-unnecessary-condition */
237
+ return {
238
+ score,
239
+ reasons,
240
+ detectedDomains,
241
+ isStrongCandidate: score >= 5,
242
+ isSoftCandidate: score >= 3 && score < 5,
243
+ };
244
+ }
245
+ //# sourceMappingURL=mcp-candidate-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-candidate-detector.js","sourceRoot":"","sources":["../../../src/engine/detectors/mcp-candidate-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { LegalProfile } from '../../types/index.js';
2
+ /**
3
+ * Checks whether a legal profile warrants injection of legal content.
4
+ * Returns true if the profile has domains beyond 'universal' or has countries specified.
5
+ */
6
+ export declare function shouldInjectLegal(profile: LegalProfile | null | undefined): boolean;
7
+ /**
8
+ * Generates an array of acceptance criteria strings to add to spec.md.
9
+ * These are meta-criteria that remind the implementer to check legal requirements.
10
+ * Returns 3-6 criteria based on detected domains.
11
+ */
12
+ export declare function generateLegalCriteria(profile: LegalProfile, _specDescription: string): string[];
13
+ /**
14
+ * Generates a markdown section to append to technical.md with legal compliance research instructions.
15
+ * Since the MCP server has no LLM access, this generates prompts/instructions for the calling LLM.
16
+ */
17
+ export declare function generateLegalSection(profile: LegalProfile, specDescription: string): string;
18
+ //# sourceMappingURL=criteria-injector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"criteria-injector.d.ts","sourceRoot":"","sources":["../../../src/engine/legal-compliance/criteria-injector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,sBAAsB,CAAC;AA+DtE;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CASnF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,CAoC/F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CA0E3F"}
@@ -0,0 +1,176 @@
1
+ // criteria-injector — Generates legal compliance content for spec injection
2
+ import { getQuestionsForDomains, buildLegalPrompt } from './question-framework.js';
3
+ /** Domain-to-criteria templates: each domain yields focused meta-criteria */
4
+ const DOMAIN_CRITERIA_TEMPLATES = {
5
+ billing: [
6
+ 'Validate invoice format against local tax authority requirements',
7
+ 'Implement mandatory tax calculation and reporting per applicable jurisdiction',
8
+ ],
9
+ health: [
10
+ 'Ensure health data handling complies with applicable medical privacy laws (e.g., HIPAA, local equivalents)',
11
+ 'Implement audit logging for all access to protected health information',
12
+ ],
13
+ fintech: [
14
+ 'Verify compliance with financial regulation and anti-money laundering requirements',
15
+ 'Implement transaction record retention per applicable financial laws',
16
+ ],
17
+ education: [
18
+ 'Verify compliance with student data privacy laws (e.g., FERPA, local equivalents)',
19
+ 'Implement parental consent mechanisms where student age requires it',
20
+ ],
21
+ ecommerce: [
22
+ 'Implement mandatory consumer protection disclosures per target market',
23
+ 'Ensure refund and cancellation policies meet local consumer law requirements',
24
+ ],
25
+ social: [
26
+ 'Implement content moderation mechanisms as required by applicable platform regulation',
27
+ 'Verify compliance with user data portability and deletion rights',
28
+ ],
29
+ gaming: [
30
+ 'Verify compliance with age rating and content classification requirements',
31
+ 'Implement loot box / in-app purchase disclosures per applicable gaming regulation',
32
+ ],
33
+ 'ai-ml': [
34
+ 'Implement transparency disclosures for AI-generated content per applicable AI regulation',
35
+ 'Verify compliance with algorithmic bias and fairness requirements',
36
+ ],
37
+ iot: [
38
+ 'Ensure device data collection complies with applicable IoT privacy regulation',
39
+ 'Implement mandatory security update mechanisms per connected device laws',
40
+ ],
41
+ hr: [
42
+ 'Verify employee data handling complies with applicable labor and privacy laws',
43
+ 'Implement mandatory data retention and deletion schedules for personnel records',
44
+ ],
45
+ 'real-estate': [
46
+ 'Verify compliance with fair housing and anti-discrimination laws in property listings',
47
+ 'Implement mandatory property disclosure requirements per jurisdiction',
48
+ ],
49
+ logistics: [
50
+ 'Verify compliance with customs and cross-border data transfer regulations',
51
+ 'Implement shipment tracking data retention per applicable transport law',
52
+ ],
53
+ media: [
54
+ 'Verify compliance with copyright and intellectual property laws for content distribution',
55
+ 'Implement mandatory content licensing and attribution mechanisms',
56
+ ],
57
+ government: [
58
+ 'Ensure compliance with public sector accessibility standards (e.g., WCAG, Section 508)',
59
+ 'Implement mandatory data sovereignty and residency requirements for government data',
60
+ ],
61
+ };
62
+ /**
63
+ * Checks whether a legal profile warrants injection of legal content.
64
+ * Returns true if the profile has domains beyond 'universal' or has countries specified.
65
+ */
66
+ export function shouldInjectLegal(profile) {
67
+ if (profile === null || profile === undefined) {
68
+ return false;
69
+ }
70
+ const hasNonUniversalDomains = profile.domains.some((d) => d !== 'universal');
71
+ const hasCountries = profile.countries.length > 0;
72
+ return hasNonUniversalDomains || hasCountries;
73
+ }
74
+ /**
75
+ * Generates an array of acceptance criteria strings to add to spec.md.
76
+ * These are meta-criteria that remind the implementer to check legal requirements.
77
+ * Returns 3-6 criteria based on detected domains.
78
+ */
79
+ export function generateLegalCriteria(profile, _specDescription) {
80
+ const criteria = [];
81
+ // Always add data protection criterion if countries are specified
82
+ if (profile.countries.length > 0) {
83
+ const countryList = profile.countries.join(', ');
84
+ criteria.push(`Verify compliance with data protection laws for target countries: [${countryList}]`);
85
+ }
86
+ // Add domain-specific criteria
87
+ for (const domain of profile.domains) {
88
+ if (domain === 'universal') {
89
+ continue;
90
+ }
91
+ const templates = DOMAIN_CRITERIA_TEMPLATES[domain];
92
+ for (const template of templates) {
93
+ criteria.push(template);
94
+ }
95
+ }
96
+ // Add consent criterion if handling PII or personal data
97
+ const personalDataTypes = ['pii', 'biometric', 'health', 'children'];
98
+ const hasPersonalData = profile.dataTypes.some((dt) => personalDataTypes.includes(dt));
99
+ if (hasPersonalData) {
100
+ criteria.push('Implement mandatory consent mechanism per applicable privacy regulation');
101
+ }
102
+ // Add minor protection if applicable
103
+ if (profile.audience.includesMinors) {
104
+ criteria.push('Implement age verification and parental consent per child protection laws');
105
+ }
106
+ // Cap at 6 criteria to avoid overwhelming the spec
107
+ return criteria.slice(0, 6);
108
+ }
109
+ /**
110
+ * Generates a markdown section to append to technical.md with legal compliance research instructions.
111
+ * Since the MCP server has no LLM access, this generates prompts/instructions for the calling LLM.
112
+ */
113
+ export function generateLegalSection(profile, specDescription) {
114
+ const questions = getQuestionsForDomains(profile.domains);
115
+ const prompt = buildLegalPrompt(questions, profile.countries, specDescription);
116
+ const lines = [];
117
+ lines.push('## Legal Compliance');
118
+ lines.push('');
119
+ lines.push('> **Disclaimer**: This section provides guidance for legal compliance research.');
120
+ lines.push('> It does NOT constitute legal advice. Consult qualified legal professionals');
121
+ lines.push('> for authoritative guidance on regulatory requirements.');
122
+ lines.push('');
123
+ // Detected profile summary
124
+ lines.push('### Detected Profile');
125
+ lines.push('');
126
+ const nonUniversalDomains = profile.domains.filter((d) => d !== 'universal');
127
+ if (nonUniversalDomains.length > 0) {
128
+ lines.push(`- **Domains**: ${nonUniversalDomains.join(', ')}`);
129
+ }
130
+ if (profile.countries.length > 0) {
131
+ lines.push(`- **Countries**: ${profile.countries.join(', ')}`);
132
+ }
133
+ if (profile.dataTypes.length > 0) {
134
+ lines.push(`- **Sensitive data types**: ${profile.dataTypes.join(', ')}`);
135
+ }
136
+ const audienceTraits = [];
137
+ if (profile.audience.includesMinors) {
138
+ audienceTraits.push('minors');
139
+ }
140
+ if (profile.audience.includesPatients) {
141
+ audienceTraits.push('patients');
142
+ }
143
+ if (profile.audience.includesEmployees) {
144
+ audienceTraits.push('employees');
145
+ }
146
+ if (profile.audience.isB2B) {
147
+ audienceTraits.push('B2B');
148
+ }
149
+ if (profile.audience.isB2C) {
150
+ audienceTraits.push('B2C');
151
+ }
152
+ if (audienceTraits.length > 0) {
153
+ lines.push(`- **Audience**: ${audienceTraits.join(', ')}`);
154
+ }
155
+ lines.push('');
156
+ // Legal compliance research section
157
+ lines.push('### Legal Compliance Research');
158
+ lines.push('');
159
+ lines.push('The following questions should be investigated to determine concrete legal requirements:');
160
+ lines.push('');
161
+ for (const q of questions) {
162
+ lines.push(`#### ${q.domain}: ${q.id}`);
163
+ lines.push('');
164
+ lines.push(`**Question**: ${q.question}`);
165
+ lines.push('');
166
+ lines.push(`**Rationale**: ${q.rationale}`);
167
+ lines.push('');
168
+ }
169
+ // LLM investigation instructions
170
+ lines.push('### Investigation Instructions');
171
+ lines.push('');
172
+ lines.push(prompt);
173
+ lines.push('');
174
+ return lines.join('\n');
175
+ }
176
+ //# sourceMappingURL=criteria-injector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"criteria-injector.js","sourceRoot":"","sources":["../../../src/engine/legal-compliance/criteria-injector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { ProjectKnowledge, LegalDomain, LegalProfile, LegalDataType } from '../../types/index.js';
2
+ /**
3
+ * Detect which legal domains apply to a project based on its knowledge.
4
+ * Always includes 'universal'.
5
+ */
6
+ export declare function detectLegalDomains(knowledge: ProjectKnowledge): LegalDomain[];
7
+ /**
8
+ * Detect target countries from locale, currency, timezone, and i18n hints.
9
+ * Returns ISO country codes. Empty array if nothing detected.
10
+ */
11
+ export declare function detectCountries(knowledge: ProjectKnowledge): string[];
12
+ /**
13
+ * Detect audience characteristics (minors, patients, B2B/B2C, employees).
14
+ */
15
+ export declare function detectAudience(knowledge: ProjectKnowledge): LegalProfile['audience'];
16
+ /**
17
+ * Detect types of sensitive data the project likely handles.
18
+ */
19
+ export declare function detectDataTypes(knowledge: ProjectKnowledge): LegalDataType[];
20
+ /**
21
+ * Build a complete LegalProfile by combining all detectors.
22
+ * This is the main entry point called by init_project.
23
+ */
24
+ export declare function buildLegalProfile(knowledge: ProjectKnowledge): LegalProfile;
25
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/engine/legal-compliance/detector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,aAAa,EACd,MAAM,sBAAsB,CAAC;AAkW9B;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,GAAG,WAAW,EAAE,CAW7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAyBrE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,YAAY,CAAC,UAAU,CAAC,CA4CpF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,gBAAgB,GAAG,aAAa,EAAE,CAiF5E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,YAAY,CAU3E"}