@planu/cli 0.45.4 → 0.46.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 (51) hide show
  1. package/dist/config/license-plans.json +1 -0
  2. package/dist/config/tool-groups.json +1 -0
  3. package/dist/engine/legal-compliance/criteria-injector.d.ts +18 -0
  4. package/dist/engine/legal-compliance/criteria-injector.d.ts.map +1 -0
  5. package/dist/engine/legal-compliance/criteria-injector.js +176 -0
  6. package/dist/engine/legal-compliance/criteria-injector.js.map +1 -0
  7. package/dist/engine/legal-compliance/detector.d.ts +25 -0
  8. package/dist/engine/legal-compliance/detector.d.ts.map +1 -0
  9. package/dist/engine/legal-compliance/detector.js +515 -0
  10. package/dist/engine/legal-compliance/detector.js.map +1 -0
  11. package/dist/engine/legal-compliance/index.d.ts +4 -0
  12. package/dist/engine/legal-compliance/index.d.ts.map +1 -0
  13. package/dist/engine/legal-compliance/index.js +5 -0
  14. package/dist/engine/legal-compliance/index.js.map +1 -0
  15. package/dist/engine/legal-compliance/question-framework.d.ts +14 -0
  16. package/dist/engine/legal-compliance/question-framework.d.ts.map +1 -0
  17. package/dist/engine/legal-compliance/question-framework.js +461 -0
  18. package/dist/engine/legal-compliance/question-framework.js.map +1 -0
  19. package/dist/engine/validator/dor-dod.d.ts +2 -2
  20. package/dist/engine/validator/dor-dod.d.ts.map +1 -1
  21. package/dist/engine/validator/dor-dod.js +62 -14
  22. package/dist/engine/validator/dor-dod.js.map +1 -1
  23. package/dist/tools/create-spec/spec-builder.d.ts.map +1 -1
  24. package/dist/tools/create-spec/spec-builder.js +39 -5
  25. package/dist/tools/create-spec/spec-builder.js.map +1 -1
  26. package/dist/tools/init-project/handler.d.ts.map +1 -1
  27. package/dist/tools/init-project/handler.js +6 -0
  28. package/dist/tools/init-project/handler.js.map +1 -1
  29. package/dist/tools/legal-compliance-report.d.ts +3 -0
  30. package/dist/tools/legal-compliance-report.d.ts.map +1 -0
  31. package/dist/tools/legal-compliance-report.js +65 -0
  32. package/dist/tools/legal-compliance-report.js.map +1 -0
  33. package/dist/tools/register-governance-tools.d.ts.map +1 -1
  34. package/dist/tools/register-governance-tools.js +13 -1
  35. package/dist/tools/register-governance-tools.js.map +1 -1
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/index.js +1 -0
  39. package/dist/types/index.js.map +1 -1
  40. package/dist/types/legal.d.ts +71 -0
  41. package/dist/types/legal.d.ts.map +1 -0
  42. package/dist/types/legal.js +3 -0
  43. package/dist/types/legal.js.map +1 -0
  44. package/dist/types/project/core.d.ts +2 -0
  45. package/dist/types/project/core.d.ts.map +1 -1
  46. package/dist/types/project/core.js.map +1 -1
  47. package/dist/types/spec/core.d.ts +2 -0
  48. package/dist/types/spec/core.d.ts.map +1 -1
  49. package/package.json +1 -1
  50. package/src/config/license-plans.json +1 -0
  51. package/src/config/tool-groups.json +1 -0
@@ -0,0 +1,461 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Universal domain — applies to ALL projects regardless of industry
3
+ // ---------------------------------------------------------------------------
4
+ const UNIVERSAL_QUESTIONS = [
5
+ {
6
+ id: 'universal-01',
7
+ domain: 'universal',
8
+ question: 'What data protection laws apply in each target country (e.g., GDPR, LGPD, CCPA, POPIA)?',
9
+ rationale: 'Data protection is the most common compliance area. Nearly every app collects some form of personal data.',
10
+ keywords: ['gdpr', 'lgpd', 'ccpa', 'popia', 'data protection', 'personal data'],
11
+ },
12
+ {
13
+ id: 'universal-02',
14
+ domain: 'universal',
15
+ question: 'What are the privacy policy requirements in each target country? Must it be in the local language?',
16
+ rationale: 'Most jurisdictions require a publicly accessible privacy policy with specific disclosures.',
17
+ keywords: ['privacy policy', 'privacy notice', 'disclosure'],
18
+ },
19
+ {
20
+ id: 'universal-03',
21
+ domain: 'universal',
22
+ question: 'What accessibility standards are legally required (e.g., WCAG level, ADA, EAA)?',
23
+ rationale: 'Accessibility lawsuits are increasing globally. Some countries mandate specific WCAG levels.',
24
+ keywords: ['wcag', 'accessibility', 'ada', 'eaa', 'a11y'],
25
+ },
26
+ {
27
+ id: 'universal-04',
28
+ domain: 'universal',
29
+ question: 'What are the mandatory data retention periods and deletion obligations in each country?',
30
+ rationale: 'Over-retaining data creates liability. Under-retaining may violate tax or audit laws.',
31
+ keywords: ['data retention', 'deletion', 'right to erasure', 'storage limitation'],
32
+ },
33
+ {
34
+ id: 'universal-05',
35
+ domain: 'universal',
36
+ question: 'What consent mechanisms are required for data collection (opt-in vs opt-out, granularity)?',
37
+ rationale: 'Consent requirements vary dramatically — EU requires explicit opt-in, US often allows opt-out.',
38
+ keywords: ['consent', 'opt-in', 'opt-out', 'legitimate interest'],
39
+ },
40
+ {
41
+ id: 'universal-06',
42
+ domain: 'universal',
43
+ question: 'What are the data breach notification requirements (timeline, authority, affected users)?',
44
+ rationale: 'Breach notification deadlines range from 24 hours to 72 hours depending on jurisdiction.',
45
+ keywords: ['breach notification', 'data breach', 'incident response', 'notification timeline'],
46
+ },
47
+ {
48
+ id: 'universal-07',
49
+ domain: 'universal',
50
+ question: 'What restrictions exist on cross-border data transfers between the target countries?',
51
+ rationale: 'Transferring data across borders may require Standard Contractual Clauses, adequacy decisions, or local storage.',
52
+ keywords: ['cross-border', 'data transfer', 'scc', 'adequacy', 'data localization'],
53
+ },
54
+ {
55
+ id: 'universal-08',
56
+ domain: 'universal',
57
+ question: 'What cookie and tracking consent requirements apply (e.g., cookie banners, ePrivacy)?',
58
+ rationale: 'Cookie consent is separately regulated from general data protection in many jurisdictions.',
59
+ keywords: ['cookie', 'tracking', 'eprivacy', 'cookie banner', 'analytics consent'],
60
+ },
61
+ ];
62
+ // ---------------------------------------------------------------------------
63
+ // Billing domain — invoicing, taxation, fiscal compliance
64
+ // ---------------------------------------------------------------------------
65
+ const BILLING_QUESTIONS = [
66
+ {
67
+ id: 'billing-01',
68
+ domain: 'billing',
69
+ question: 'What electronic invoice format is required in each country (e.g., CFDI in Mexico, FEL in Guatemala, Factura Electronica in Colombia)?',
70
+ rationale: 'Many countries mandate specific XML/JSON invoice formats validated by the tax authority.',
71
+ keywords: ['e-invoice', 'cfdi', 'fel', 'factura electronica', 'electronic invoice'],
72
+ },
73
+ {
74
+ id: 'billing-02',
75
+ domain: 'billing',
76
+ question: 'Does the tax authority require real-time certification or pre-authorization of invoices?',
77
+ rationale: 'Some countries require invoices to be stamped by an authorized provider before delivery.',
78
+ keywords: ['pac', 'certification', 'tax stamp', 'timbrado', 'authorization'],
79
+ },
80
+ {
81
+ id: 'billing-03',
82
+ domain: 'billing',
83
+ question: 'What is the mandatory fiscal document retention period in each country?',
84
+ rationale: 'Fiscal retention periods (often 5-10 years) may exceed general data retention rules.',
85
+ keywords: ['fiscal retention', 'document retention', 'tax records', 'archive'],
86
+ },
87
+ {
88
+ id: 'billing-04',
89
+ domain: 'billing',
90
+ question: 'What mandatory fields must appear on invoices and receipts in each country?',
91
+ rationale: 'Missing mandatory fields (tax ID, address, tax breakdown) can invalidate an invoice.',
92
+ keywords: ['mandatory fields', 'invoice fields', 'tax id', 'rfc', 'nit'],
93
+ },
94
+ {
95
+ id: 'billing-05',
96
+ domain: 'billing',
97
+ question: 'Are digital signatures or cryptographic seals required on fiscal documents?',
98
+ rationale: 'Digital signatures ensure document integrity and are legally required in several countries.',
99
+ keywords: ['digital signature', 'cryptographic seal', 'fiel', 'firma electronica'],
100
+ },
101
+ {
102
+ id: 'billing-06',
103
+ domain: 'billing',
104
+ question: 'What periodic tax reporting obligations exist (e.g., monthly VAT returns, annual summaries)?',
105
+ rationale: 'The system may need to generate or export data in formats required for tax filings.',
106
+ keywords: ['tax reporting', 'vat return', 'tax filing', 'periodic report'],
107
+ },
108
+ ];
109
+ // ---------------------------------------------------------------------------
110
+ // Health domain — health data, patients, medical records
111
+ // ---------------------------------------------------------------------------
112
+ const HEALTH_QUESTIONS = [
113
+ {
114
+ id: 'health-01',
115
+ domain: 'health',
116
+ question: 'What health data protection laws apply (e.g., HIPAA, NOM-024 in Mexico, LGPD health provisions)?',
117
+ rationale: 'Health data has stricter protections than general personal data in most jurisdictions.',
118
+ keywords: ['hipaa', 'health data', 'medical records', 'phi', 'nom-024'],
119
+ },
120
+ {
121
+ id: 'health-02',
122
+ domain: 'health',
123
+ question: 'What informed consent requirements exist for collecting and processing health data?',
124
+ rationale: 'Health data typically requires explicit, specific consent separate from general terms.',
125
+ keywords: ['informed consent', 'patient consent', 'health consent'],
126
+ },
127
+ {
128
+ id: 'health-03',
129
+ domain: 'health',
130
+ question: 'What interoperability standards are required or recommended (e.g., HL7 FHIR, DICOM)?',
131
+ rationale: 'Some jurisdictions mandate specific health data exchange formats for system interoperability.',
132
+ keywords: ['hl7', 'fhir', 'dicom', 'interoperability', 'health exchange'],
133
+ },
134
+ {
135
+ id: 'health-04',
136
+ domain: 'health',
137
+ question: 'What access control requirements exist for health data (role-based access, minimum necessary)?',
138
+ rationale: 'Health regulations typically require strict access controls with audit capabilities.',
139
+ keywords: ['access control', 'rbac', 'minimum necessary', 'need to know'],
140
+ },
141
+ {
142
+ id: 'health-05',
143
+ domain: 'health',
144
+ question: 'What audit trail requirements exist for health record access and modifications?',
145
+ rationale: 'Audit logs for health data access are legally required in most health data frameworks.',
146
+ keywords: ['audit trail', 'audit log', 'access log', 'health audit'],
147
+ },
148
+ {
149
+ id: 'health-06',
150
+ domain: 'health',
151
+ question: 'What patient data portability rights exist (e.g., right to export medical records)?',
152
+ rationale: 'Patients may have the right to receive their health data in a structured, portable format.',
153
+ keywords: ['data portability', 'patient rights', 'medical record export'],
154
+ },
155
+ ];
156
+ // ---------------------------------------------------------------------------
157
+ // Fintech domain — payments, banking, financial services
158
+ // ---------------------------------------------------------------------------
159
+ const FINTECH_QUESTIONS = [
160
+ {
161
+ id: 'fintech-01',
162
+ domain: 'fintech',
163
+ question: 'What PCI-DSS compliance level is required based on transaction volume and data handling?',
164
+ rationale: 'PCI-DSS is a global standard but compliance level depends on how card data is processed.',
165
+ keywords: ['pci-dss', 'pci', 'card data', 'payment security'],
166
+ },
167
+ {
168
+ id: 'fintech-02',
169
+ domain: 'fintech',
170
+ question: 'What KYC (Know Your Customer) and AML (Anti-Money Laundering) requirements apply?',
171
+ rationale: 'Financial services must verify customer identity and monitor for suspicious transactions.',
172
+ keywords: [
173
+ 'kyc',
174
+ 'aml',
175
+ 'know your customer',
176
+ 'anti-money laundering',
177
+ 'identity verification',
178
+ ],
179
+ },
180
+ {
181
+ id: 'fintech-03',
182
+ domain: 'fintech',
183
+ question: 'What financial licenses or registrations are required to operate in each country?',
184
+ rationale: 'Operating without proper licensing can result in criminal penalties and service shutdown.',
185
+ keywords: ['financial license', 'fintech license', 'banking license', 'money transmitter'],
186
+ },
187
+ {
188
+ id: 'fintech-04',
189
+ domain: 'fintech',
190
+ question: 'What regulatory reporting obligations exist (e.g., suspicious activity reports, transaction reporting)?',
191
+ rationale: 'Financial institutions must file reports with regulators on specific transaction patterns.',
192
+ keywords: ['regulatory reporting', 'sar', 'suspicious activity', 'transaction reporting'],
193
+ },
194
+ {
195
+ id: 'fintech-05',
196
+ domain: 'fintech',
197
+ question: 'What transaction limits or thresholds trigger additional compliance requirements?',
198
+ rationale: 'Certain transaction amounts trigger enhanced due diligence or reporting obligations.',
199
+ keywords: ['transaction limits', 'threshold', 'enhanced due diligence', 'ctr'],
200
+ },
201
+ {
202
+ id: 'fintech-06',
203
+ domain: 'fintech',
204
+ question: 'What fraud prevention and detection measures are legally required?',
205
+ rationale: 'Some jurisdictions mandate specific fraud prevention mechanisms for financial services.',
206
+ keywords: ['fraud prevention', 'fraud detection', 'strong authentication', 'sca', 'psd2'],
207
+ },
208
+ ];
209
+ // ---------------------------------------------------------------------------
210
+ // Education domain — students, minors, educational content
211
+ // ---------------------------------------------------------------------------
212
+ const EDUCATION_QUESTIONS = [
213
+ {
214
+ id: 'education-01',
215
+ domain: 'education',
216
+ question: "What laws protect minors' data in each country (e.g., COPPA, GDPR-K, local equivalents)?",
217
+ rationale: "Processing children's data has the strictest requirements in most legal frameworks.",
218
+ keywords: ['coppa', 'children', 'minor', 'gdpr-k', 'child data'],
219
+ },
220
+ {
221
+ id: 'education-02',
222
+ domain: 'education',
223
+ question: 'What parental or guardian consent mechanisms are required for users under the age threshold?',
224
+ rationale: 'Age thresholds vary (13 in US, 16 in some EU countries) and consent mechanisms differ.',
225
+ keywords: ['parental consent', 'guardian consent', 'age threshold', 'verifiable consent'],
226
+ },
227
+ {
228
+ id: 'education-03',
229
+ domain: 'education',
230
+ question: 'Are there regulations on educational content quality, certification, or accreditation?',
231
+ rationale: 'Educational platforms may need accreditation or must follow curriculum standards.',
232
+ keywords: ['accreditation', 'educational content', 'curriculum', 'certification'],
233
+ },
234
+ {
235
+ id: 'education-04',
236
+ domain: 'education',
237
+ question: 'What student privacy laws apply (e.g., FERPA, local student data protection)?',
238
+ rationale: 'Student records have special protections beyond general data protection in many countries.',
239
+ keywords: ['ferpa', 'student privacy', 'student records', 'educational records'],
240
+ },
241
+ ];
242
+ // ---------------------------------------------------------------------------
243
+ // E-commerce domain — online retail, consumer transactions
244
+ // ---------------------------------------------------------------------------
245
+ const ECOMMERCE_QUESTIONS = [
246
+ {
247
+ id: 'ecommerce-01',
248
+ domain: 'ecommerce',
249
+ question: 'What consumer protection laws apply to online sales in each country?',
250
+ rationale: 'Consumer protection rights (cooling-off periods, warranties) vary significantly by country.',
251
+ keywords: ['consumer protection', 'consumer rights', 'warranty', 'cooling-off'],
252
+ },
253
+ {
254
+ id: 'ecommerce-02',
255
+ domain: 'ecommerce',
256
+ question: 'What are the mandatory return, refund, and cancellation rights for online purchases?',
257
+ rationale: 'Many countries grant statutory return rights (e.g., 14 days in EU) that override store policy.',
258
+ keywords: ['return policy', 'refund', 'cancellation', 'right of withdrawal'],
259
+ },
260
+ {
261
+ id: 'ecommerce-03',
262
+ domain: 'ecommerce',
263
+ question: 'What receipt or invoice requirements apply to online transactions in each country?',
264
+ rationale: 'Online merchants must provide purchase confirmations with specific content in many jurisdictions.',
265
+ keywords: ['receipt', 'purchase confirmation', 'order confirmation', 'invoice'],
266
+ },
267
+ {
268
+ id: 'ecommerce-04',
269
+ domain: 'ecommerce',
270
+ question: 'What distance selling regulations apply (pre-contractual information, confirmation requirements)?',
271
+ rationale: 'Distance selling laws require specific information before and after purchase.',
272
+ keywords: ['distance selling', 'pre-contractual', 'terms and conditions', 'online contract'],
273
+ },
274
+ ];
275
+ // ---------------------------------------------------------------------------
276
+ // AI/ML domain — artificial intelligence, machine learning systems
277
+ // ---------------------------------------------------------------------------
278
+ const AI_ML_QUESTIONS = [
279
+ {
280
+ id: 'ai-ml-01',
281
+ domain: 'ai-ml',
282
+ question: 'What AI-specific regulations apply in each country (e.g., EU AI Act, local AI guidelines)?',
283
+ rationale: 'AI regulation is rapidly evolving with the EU AI Act as the most comprehensive framework.',
284
+ keywords: ['ai act', 'ai regulation', 'artificial intelligence', 'ai governance'],
285
+ },
286
+ {
287
+ id: 'ai-ml-02',
288
+ domain: 'ai-ml',
289
+ question: 'What explainability or transparency requirements exist for AI/ML-driven decisions?',
290
+ rationale: 'Many jurisdictions require that automated decisions be explainable to affected individuals.',
291
+ keywords: ['explainability', 'transparency', 'xai', 'interpretability', 'black box'],
292
+ },
293
+ {
294
+ id: 'ai-ml-03',
295
+ domain: 'ai-ml',
296
+ question: 'What restrictions exist on training data collection, usage, and bias mitigation?',
297
+ rationale: 'Training data may be subject to copyright, consent requirements, and bias auditing.',
298
+ keywords: ['training data', 'bias', 'fairness', 'data collection', 'copyright'],
299
+ },
300
+ {
301
+ id: 'ai-ml-04',
302
+ domain: 'ai-ml',
303
+ question: 'What rights do users have regarding automated decision-making (e.g., right to human review)?',
304
+ rationale: 'GDPR Art. 22 and similar laws grant rights against solely automated decisions with legal effects.',
305
+ keywords: ['automated decision', 'human review', 'right to contest', 'profiling'],
306
+ },
307
+ ];
308
+ // ---------------------------------------------------------------------------
309
+ // Social domain — social platforms, user-generated content
310
+ // ---------------------------------------------------------------------------
311
+ const SOCIAL_QUESTIONS = [
312
+ {
313
+ id: 'social-01',
314
+ domain: 'social',
315
+ question: 'What content moderation obligations exist (e.g., DSA, NetzDG, local platform liability)?',
316
+ rationale: 'Platform liability for user content varies from safe harbor to active moderation duties.',
317
+ keywords: ['content moderation', 'dsa', 'netzDG', 'platform liability', 'takedown'],
318
+ },
319
+ {
320
+ id: 'social-02',
321
+ domain: 'social',
322
+ question: 'What age verification mechanisms are required for social platforms?',
323
+ rationale: 'Several countries now mandate age verification beyond simple self-declaration.',
324
+ keywords: ['age verification', 'age gate', 'age assurance', 'social media age'],
325
+ },
326
+ {
327
+ id: 'social-03',
328
+ domain: 'social',
329
+ question: 'What liability framework applies to user-generated content in each country?',
330
+ rationale: 'Platforms may be liable for UGC under certain conditions depending on jurisdiction.',
331
+ keywords: ['user-generated content', 'ugc', 'liability', 'safe harbor', 'notice and takedown'],
332
+ },
333
+ {
334
+ id: 'social-04',
335
+ domain: 'social',
336
+ question: 'What right-to-be-forgotten or content removal obligations exist?',
337
+ rationale: 'Users may have the right to request removal of their content and personal data from the platform.',
338
+ keywords: ['right to be forgotten', 'content removal', 'erasure', 'delisting'],
339
+ },
340
+ ];
341
+ // ---------------------------------------------------------------------------
342
+ // Gaming domain — video games, online gaming, gambling
343
+ // ---------------------------------------------------------------------------
344
+ const GAMING_QUESTIONS = [
345
+ {
346
+ id: 'gaming-01',
347
+ domain: 'gaming',
348
+ question: 'What age rating or age gate requirements apply to games in each country?',
349
+ rationale: 'Most countries require age classification systems (ESRB, PEGI, CERO) for games.',
350
+ keywords: ['age rating', 'esrb', 'pegi', 'cero', 'age gate', 'content rating'],
351
+ },
352
+ {
353
+ id: 'gaming-02',
354
+ domain: 'gaming',
355
+ question: 'What regulations apply to loot boxes, gacha mechanics, or randomized paid items?',
356
+ rationale: 'Several countries classify loot boxes as gambling or require probability disclosures.',
357
+ keywords: ['loot box', 'gacha', 'randomized', 'probability disclosure', 'paid items'],
358
+ },
359
+ {
360
+ id: 'gaming-03',
361
+ domain: 'gaming',
362
+ question: 'Does the game involve real-money gambling, and what licensing is required?',
363
+ rationale: 'Real-money gambling requires specific licenses in virtually every jurisdiction.',
364
+ keywords: ['gambling license', 'betting', 'real-money', 'wagering', 'gambling regulation'],
365
+ },
366
+ {
367
+ id: 'gaming-04',
368
+ domain: 'gaming',
369
+ question: 'What addiction prevention or responsible gaming measures are required?',
370
+ rationale: 'Some countries mandate playtime warnings, spending limits, or cool-down mechanics.',
371
+ keywords: [
372
+ 'addiction prevention',
373
+ 'responsible gaming',
374
+ 'playtime',
375
+ 'spending limit',
376
+ 'cool-down',
377
+ ],
378
+ },
379
+ ];
380
+ // ---------------------------------------------------------------------------
381
+ // Full catalog
382
+ // ---------------------------------------------------------------------------
383
+ /** Complete catalog of legal questions organized by domain */
384
+ export const LEGAL_QUESTIONS = [
385
+ ...UNIVERSAL_QUESTIONS,
386
+ ...BILLING_QUESTIONS,
387
+ ...HEALTH_QUESTIONS,
388
+ ...FINTECH_QUESTIONS,
389
+ ...EDUCATION_QUESTIONS,
390
+ ...ECOMMERCE_QUESTIONS,
391
+ ...AI_ML_QUESTIONS,
392
+ ...SOCIAL_QUESTIONS,
393
+ ...GAMING_QUESTIONS,
394
+ ];
395
+ // ---------------------------------------------------------------------------
396
+ // Query functions
397
+ // ---------------------------------------------------------------------------
398
+ /**
399
+ * Returns all questions for the given domains, always including 'universal'.
400
+ * Deduplicates in case 'universal' is already in the input list.
401
+ */
402
+ export function getQuestionsForDomains(domains) {
403
+ const domainSet = new Set(domains);
404
+ domainSet.add('universal');
405
+ return LEGAL_QUESTIONS.filter((q) => domainSet.has(q.domain));
406
+ }
407
+ /**
408
+ * Builds a prompt string that an LLM can use to investigate legal requirements
409
+ * for a project's target countries and applicable domains.
410
+ */
411
+ export function buildLegalPrompt(questions, countries, specDescription) {
412
+ const countryList = countries.join(', ');
413
+ const questionBlocks = questions
414
+ .map((q) => `### ${q.id}\n**Question:** ${q.question}\n**Why it matters:** ${q.rationale}\n**Keywords:** ${q.keywords.join(', ')}`)
415
+ .join('\n\n');
416
+ return `You are a legal compliance analyst. Investigate the following legal questions for a software project.
417
+
418
+ ## Project Description
419
+ ${specDescription}
420
+
421
+ ## Target Countries
422
+ ${countryList}
423
+
424
+ ## Instructions
425
+ For each question below, research the applicable laws and regulations in EACH target country listed above. Then produce concrete, actionable acceptance criteria that a development team can implement.
426
+
427
+ Your response MUST follow this format for each applicable regulation:
428
+ - **Regulation**: Name and reference (e.g., "GDPR Art. 17 — Right to Erasure")
429
+ - **Country**: Which country this applies to (or "all" if universal)
430
+ - **Criterion**: A specific, testable acceptance criterion (e.g., "System MUST delete all personal data within 30 days of a verified erasure request")
431
+ - **Priority**: mandatory | recommended | informational
432
+ - **Reference**: URL to official documentation or legal text
433
+
434
+ ## Important Guidelines
435
+ 1. Check for regulatory updates enacted after 2024 — regulations change frequently.
436
+ 2. When multiple countries are listed, the final requirements are the UNION of all country-specific requirements. The strictest rule wins when requirements conflict.
437
+ 3. If a regulation does not apply to this specific project, skip it — do not generate irrelevant criteria.
438
+ 4. Be specific: "MUST encrypt health data at rest using AES-256" is better than "MUST protect data."
439
+ 5. Include both technical requirements (encryption, access control) and process requirements (policies, training).
440
+
441
+ ## Questions to Investigate
442
+
443
+ ${questionBlocks}
444
+
445
+ ## Output
446
+ Return a JSON array of objects with this shape:
447
+ \`\`\`json
448
+ [
449
+ {
450
+ "regulation": "string",
451
+ "country": "string",
452
+ "criterion": "string",
453
+ "priority": "mandatory | recommended | informational",
454
+ "reference": "string | null"
455
+ }
456
+ ]
457
+ \`\`\`
458
+
459
+ Only return the JSON array, no additional text.`;
460
+ }
461
+ //# sourceMappingURL=question-framework.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-framework.js","sourceRoot":"","sources":["../../../src/engine/legal-compliance/question-framework.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Spec, ValidateResult, DefinitionOfReady, DefinitionOfDone } from '../../types/index.js';
1
+ import type { Spec, ValidateResult, DefinitionOfReady, DefinitionOfDone, CodeState } from '../../types/index.js';
2
2
  /**
3
3
  * Generate a Definition of Ready checklist for a spec.
4
4
  */
@@ -6,5 +6,5 @@ export declare function generateDoR(spec: Spec): DefinitionOfReady;
6
6
  /**
7
7
  * Generate a Definition of Done checklist for a spec.
8
8
  */
9
- export declare function generateDoD(spec: Spec, validationResult?: ValidateResult): Promise<DefinitionOfDone>;
9
+ export declare function generateDoD(spec: Spec, validationResult?: ValidateResult, codeState?: CodeState): Promise<DefinitionOfDone>;
10
10
  //# sourceMappingURL=dor-dod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dor-dod.d.ts","sourceRoot":"","sources":["../../../src/engine/validator/dor-dod.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAGjB,MAAM,sBAAsB,CAAC;AAiG9B;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,iBAAiB,CAezD;AA8FD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,gBAAgB,CAAC,EAAE,cAAc,GAChC,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
1
+ {"version":3,"file":"dor-dod.d.ts","sourceRoot":"","sources":["../../../src/engine/validator/dor-dod.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,IAAI,EACJ,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAGhB,SAAS,EACV,MAAM,sBAAsB,CAAC;AAoG9B;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,iBAAiB,CAezD;AA+ID;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,gBAAgB,CAAC,EAAE,cAAc,EACjC,SAAS,CAAC,EAAE,SAAS,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA+B3B"}
@@ -1,8 +1,10 @@
1
1
  // Planu — Validator: Definition of Ready and Definition of Done generators
2
- import { readFile } from 'node:fs/promises';
3
- import { join, dirname } from 'node:path';
2
+ import { readFile, readdir } from 'node:fs/promises';
3
+ import { join, dirname, basename } from 'node:path';
4
4
  import { parseProgressActuals } from '../actuals/progress-parser.js';
5
5
  function buildDoRSpecItems(spec) {
6
+ // Adapt description to actual file name (modern: spec.md, legacy: HU.md)
7
+ const specFileName = spec.specPath ? basename(spec.specPath) : 'spec.md';
6
8
  return [
7
9
  {
8
10
  id: 'dor-1',
@@ -38,7 +40,7 @@ function buildDoRSpecItems(spec) {
38
40
  },
39
41
  {
40
42
  id: 'dor-5',
41
- description: 'HU.md file exists',
43
+ description: `${specFileName} file exists`,
42
44
  category: 'spec',
43
45
  required: true,
44
46
  autoCheck: true,
@@ -47,10 +49,11 @@ function buildDoRSpecItems(spec) {
47
49
  ];
48
50
  }
49
51
  function buildDoRTechnicalItems(spec) {
52
+ const techFileName = spec.technicalPath ? basename(spec.technicalPath) : 'technical.md';
50
53
  return [
51
54
  {
52
55
  id: 'dor-6',
53
- description: 'FICHA-TECNICA.md file exists',
56
+ description: `${techFileName} file exists`,
54
57
  category: 'design',
55
58
  required: true,
56
59
  autoCheck: true,
@@ -111,10 +114,12 @@ export function generateDoR(spec) {
111
114
  generatedAt: new Date().toISOString(),
112
115
  };
113
116
  }
114
- function buildDoDItems(spec, score, hasQualityIssues) {
117
+ function buildDoDItems(spec, score, hasBlockingQualityIssues, hasTestFiles) {
115
118
  // If spec is already marked "done", manual gates are implicitly satisfied —
116
119
  // the user explicitly transitioned the spec, which implies review/tests/docs passed.
117
120
  const isDone = spec.status === 'done';
121
+ // If spec is "implementing" and test files exist, auto-pass test gates
122
+ const isImplementing = spec.status === 'implementing';
118
123
  return [
119
124
  {
120
125
  id: 'dod-1',
@@ -126,19 +131,19 @@ function buildDoDItems(spec, score, hasQualityIssues) {
126
131
  },
127
132
  {
128
133
  id: 'dod-2',
129
- description: 'No critical quality issues',
134
+ description: 'No critical quality issues (errors only — warnings are non-blocking)',
130
135
  category: 'quality',
131
136
  required: true,
132
137
  autoCheck: true,
133
- status: !hasQualityIssues ? 'passed' : 'failed',
138
+ status: !hasBlockingQualityIssues ? 'passed' : 'failed',
134
139
  },
135
140
  {
136
141
  id: 'dod-3',
137
142
  description: 'Unit tests written for new code',
138
143
  category: 'tests',
139
144
  required: true,
140
- autoCheck: false,
141
- status: isDone ? 'passed' : 'pending',
145
+ autoCheck: true,
146
+ status: isDone || hasTestFiles ? 'passed' : isImplementing ? 'failed' : 'pending',
142
147
  },
143
148
  {
144
149
  id: 'dod-4',
@@ -161,8 +166,8 @@ function buildDoDItems(spec, score, hasQualityIssues) {
161
166
  description: 'No regressions in existing tests',
162
167
  category: 'tests',
163
168
  required: true,
164
- autoCheck: false,
165
- status: isDone ? 'passed' : 'pending',
169
+ autoCheck: true,
170
+ status: isDone || hasTestFiles ? 'passed' : isImplementing ? 'failed' : 'pending',
166
171
  },
167
172
  {
168
173
  id: 'dod-7',
@@ -201,13 +206,56 @@ async function hasActuals(spec) {
201
206
  return false;
202
207
  } /* v8 ignore stop */
203
208
  }
209
+ /**
210
+ * Detect if test files exist for the spec's affected code files.
211
+ */
212
+ async function detectTestFiles(spec, codeState) {
213
+ // Collect affected files from codeState or impactAnalysis
214
+ const affectedFiles = [];
215
+ if (codeState?.affectedFiles && codeState.affectedFiles.length > 0) {
216
+ affectedFiles.push(...codeState.affectedFiles);
217
+ }
218
+ else if (spec.impactAnalysis?.affectedFiles) {
219
+ affectedFiles.push(...spec.impactAnalysis.affectedFiles);
220
+ }
221
+ /* v8 ignore start -- filesystem heuristic, tested via integration */
222
+ if (affectedFiles.length === 0) {
223
+ return false;
224
+ }
225
+ // Check if any affected file IS a test file
226
+ const testPatterns = ['.test.', '.spec.', '_test.', '_spec.', '/tests/', '/__tests__/'];
227
+ if (affectedFiles.some((f) => testPatterns.some((p) => f.includes(p)))) {
228
+ return true;
229
+ }
230
+ // Check if test counterparts exist for source files
231
+ const specDir = dirname(spec.specPath);
232
+ try {
233
+ const projectDir = join(specDir, '..', '..', '..');
234
+ const testsDir = join(projectDir, 'tests');
235
+ const testEntries = await readdir(testsDir, { recursive: true });
236
+ for (const file of affectedFiles) {
237
+ const base = basename(file).replace(/\.\w+$/, '');
238
+ if (testEntries.some((tf) => tf.includes(base) && testPatterns.some((p) => tf.includes(p)))) {
239
+ return true;
240
+ }
241
+ }
242
+ }
243
+ catch {
244
+ // No tests directory — can't auto-detect
245
+ }
246
+ return false;
247
+ /* v8 ignore stop */
248
+ }
204
249
  /**
205
250
  * Generate a Definition of Done checklist for a spec.
206
251
  */
207
- export async function generateDoD(spec, validationResult) {
252
+ export async function generateDoD(spec, validationResult, codeState) {
208
253
  const score = validationResult?.score ?? 0;
209
- const hasQualityIssues = (validationResult?.qualityIssues.length ?? 0) > 0;
210
- const items = buildDoDItems(spec, score, hasQualityIssues);
254
+ // Only errors and critical issues block DoD — warnings and info are non-blocking
255
+ const blockingSeverities = ['error', 'critical'];
256
+ const hasBlockingQualityIssues = validationResult?.qualityIssues.some((i) => blockingSeverities.includes(i.severity)) ?? false;
257
+ const hasTestFiles = await detectTestFiles(spec, codeState);
258
+ const items = buildDoDItems(spec, score, hasBlockingQualityIssues, hasTestFiles);
211
259
  // Override actuals check with progress.md parsing
212
260
  const actualsItem = items.find((i) => i.id === 'dod-8');
213
261
  if (actualsItem?.status === 'pending') {