@planu/cli 0.80.1 → 0.81.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 (96) hide show
  1. package/dist/cli/commands/create.js.map +1 -1
  2. package/dist/cli/commands/list.js.map +1 -1
  3. package/dist/config/ac-gap-keywords.json +144 -0
  4. package/dist/config/challenge-scenarios.json +114 -0
  5. package/dist/config/code-quality-thresholds.json +114 -0
  6. package/dist/config/compliance-frameworks.json +150 -0
  7. package/dist/config/dor-dod-items.json +214 -0
  8. package/dist/config/drift-severity.json +22 -0
  9. package/dist/config/elicitation-questions.json +70 -0
  10. package/dist/config/feasibility-rules.json +91 -0
  11. package/dist/config/rbac-roles.json +27 -0
  12. package/dist/config/readiness-config.json +18 -0
  13. package/dist/config/spec-types.json +42 -0
  14. package/dist/engine/ac-gap-detector/constants.d.ts.map +1 -1
  15. package/dist/engine/ac-gap-detector/constants.js +24 -126
  16. package/dist/engine/ac-gap-detector/constants.js.map +1 -1
  17. package/dist/engine/ac-gap-detector/keyword-loader.d.ts +13 -0
  18. package/dist/engine/ac-gap-detector/keyword-loader.d.ts.map +1 -0
  19. package/dist/engine/ac-gap-detector/keyword-loader.js +35 -0
  20. package/dist/engine/ac-gap-detector/keyword-loader.js.map +1 -0
  21. package/dist/engine/challenge-scenarios-loader.d.ts +46 -0
  22. package/dist/engine/challenge-scenarios-loader.d.ts.map +1 -0
  23. package/dist/engine/challenge-scenarios-loader.js +83 -0
  24. package/dist/engine/challenge-scenarios-loader.js.map +1 -0
  25. package/dist/engine/code-quality-thresholds-loader.d.ts +27 -0
  26. package/dist/engine/code-quality-thresholds-loader.d.ts.map +1 -0
  27. package/dist/engine/code-quality-thresholds-loader.js +88 -0
  28. package/dist/engine/code-quality-thresholds-loader.js.map +1 -0
  29. package/dist/engine/compliance-injector.d.ts +46 -0
  30. package/dist/engine/compliance-injector.d.ts.map +1 -0
  31. package/dist/engine/compliance-injector.js +121 -0
  32. package/dist/engine/compliance-injector.js.map +1 -0
  33. package/dist/engine/dor-dod/dod.d.ts +3 -2
  34. package/dist/engine/dor-dod/dod.d.ts.map +1 -1
  35. package/dist/engine/dor-dod/dod.js +38 -73
  36. package/dist/engine/dor-dod/dod.js.map +1 -1
  37. package/dist/engine/dor-dod/dor.d.ts +3 -2
  38. package/dist/engine/dor-dod/dor.d.ts.map +1 -1
  39. package/dist/engine/dor-dod/dor.js +75 -125
  40. package/dist/engine/dor-dod/dor.js.map +1 -1
  41. package/dist/engine/dor-dod/items-loader.d.ts +18 -0
  42. package/dist/engine/dor-dod/items-loader.d.ts.map +1 -0
  43. package/dist/engine/dor-dod/items-loader.js +55 -0
  44. package/dist/engine/dor-dod/items-loader.js.map +1 -0
  45. package/dist/engine/elicitation/question-generator.d.ts.map +1 -1
  46. package/dist/engine/elicitation/question-generator.js +74 -63
  47. package/dist/engine/elicitation/question-generator.js.map +1 -1
  48. package/dist/engine/feasibility-rules-loader.d.ts +13 -0
  49. package/dist/engine/feasibility-rules-loader.d.ts.map +1 -0
  50. package/dist/engine/feasibility-rules-loader.js +39 -0
  51. package/dist/engine/feasibility-rules-loader.js.map +1 -0
  52. package/dist/engine/feasibility-validator.d.ts +1 -1
  53. package/dist/engine/feasibility-validator.d.ts.map +1 -1
  54. package/dist/engine/feasibility-validator.js +21 -78
  55. package/dist/engine/feasibility-validator.js.map +1 -1
  56. package/dist/engine/rbac/roles.d.ts +13 -5
  57. package/dist/engine/rbac/roles.d.ts.map +1 -1
  58. package/dist/engine/rbac/roles.js +58 -24
  59. package/dist/engine/rbac/roles.js.map +1 -1
  60. package/dist/engine/readiness-checker.d.ts +1 -1
  61. package/dist/engine/readiness-checker.d.ts.map +1 -1
  62. package/dist/engine/readiness-checker.js +10 -12
  63. package/dist/engine/readiness-checker.js.map +1 -1
  64. package/dist/engine/readiness-config-loader.d.ts +8 -0
  65. package/dist/engine/readiness-config-loader.d.ts.map +1 -0
  66. package/dist/engine/readiness-config-loader.js +58 -0
  67. package/dist/engine/readiness-config-loader.js.map +1 -0
  68. package/dist/engine/spec-types-loader.d.ts +22 -0
  69. package/dist/engine/spec-types-loader.d.ts.map +1 -0
  70. package/dist/engine/spec-types-loader.js +50 -0
  71. package/dist/engine/spec-types-loader.js.map +1 -0
  72. package/dist/engine/validator/analyzer.d.ts +1 -0
  73. package/dist/engine/validator/analyzer.d.ts.map +1 -1
  74. package/dist/engine/validator/analyzer.js +31 -8
  75. package/dist/engine/validator/analyzer.js.map +1 -1
  76. package/dist/types/common/primitives.d.ts.map +1 -1
  77. package/dist/types/index.d.ts +1 -0
  78. package/dist/types/index.d.ts.map +1 -1
  79. package/dist/types/index.js +1 -0
  80. package/dist/types/index.js.map +1 -1
  81. package/dist/types/plugin-configs.d.ts +105 -0
  82. package/dist/types/plugin-configs.d.ts.map +1 -0
  83. package/dist/types/plugin-configs.js +6 -0
  84. package/dist/types/plugin-configs.js.map +1 -0
  85. package/package.json +1 -1
  86. package/src/config/ac-gap-keywords.json +144 -0
  87. package/src/config/challenge-scenarios.json +114 -0
  88. package/src/config/code-quality-thresholds.json +114 -0
  89. package/src/config/compliance-frameworks.json +150 -0
  90. package/src/config/dor-dod-items.json +214 -0
  91. package/src/config/drift-severity.json +22 -0
  92. package/src/config/elicitation-questions.json +70 -0
  93. package/src/config/feasibility-rules.json +91 -0
  94. package/src/config/rbac-roles.json +27 -0
  95. package/src/config/readiness-config.json +18 -0
  96. package/src/config/spec-types.json +42 -0
@@ -1,72 +1,83 @@
1
1
  // src/engine/elicitation/question-generator.ts
2
2
  // SPEC-163: Generates structured clarification questions for spec creation.
3
+ // SPEC-219: Questions loaded from src/config/elicitation-questions.json via ConfigLoader.
4
+ import { z } from 'zod';
5
+ import { ConfigLoader } from '../config-loader.js';
6
+ // ---------------------------------------------------------------------------
7
+ // SPEC-219: Elicitation question config schema
8
+ // ---------------------------------------------------------------------------
9
+ const ElicitationQuestionConfigSchema = z.object({
10
+ id: z.string().describe('Unique question identifier (e.g. users, success, scope)'),
11
+ category: z
12
+ .enum(['scope', 'users', 'data', 'behavior', 'constraints', 'success'])
13
+ .describe('Question category: scope, users, data, behavior, constraints, or success'),
14
+ questionTemplate: z
15
+ .string()
16
+ .describe('Question text. Use {title} as placeholder for the feature title'),
17
+ hint: z.string().optional().describe('Optional guidance hint shown to the user'),
18
+ required: z.boolean().describe('Whether the question must be answered'),
19
+ answerType: z
20
+ .enum(['text', 'choice', 'yes-no'])
21
+ .describe('Answer format: text, choice, or yes-no'),
22
+ choices: z.array(z.string()).optional().describe('Available choices when answerType is "choice"'),
23
+ condition: z
24
+ .enum(['always', 'data', 'api'])
25
+ .describe('When to include this question: always, data (needs DB/store context), or api (needs API context)'),
26
+ conditionKeywords: z
27
+ .array(z.string())
28
+ .optional()
29
+ .describe('Keywords in description that trigger conditional inclusion'),
30
+ });
31
+ const questionConfigLoader = new ConfigLoader('elicitation-questions', z.array(ElicitationQuestionConfigSchema));
32
+ /**
33
+ * Resolve a question template against the feature title.
34
+ */
35
+ function resolveTemplate(template, title) {
36
+ return template.replace(/\{title\}/g, title);
37
+ }
38
+ /**
39
+ * Determine whether a conditional question should be included.
40
+ */
41
+ function shouldInclude(config, lowerDesc, context) {
42
+ if (config.condition === 'always') {
43
+ return true;
44
+ }
45
+ if (config.condition === 'data') {
46
+ if (context?.hasDatabase === true) {
47
+ return true;
48
+ }
49
+ return (config.conditionKeywords ?? []).some((kw) => lowerDesc.includes(kw));
50
+ }
51
+ // condition === 'api' is the only remaining case
52
+ if (context?.isApi === true) {
53
+ return true;
54
+ }
55
+ return (config.conditionKeywords ?? []).some((kw) => lowerDesc.includes(kw));
56
+ }
3
57
  /** Generate standard clarification questions for a feature spec */
4
58
  export function generateSpecQuestions(title, description, context) {
5
- const questions = [];
59
+ const configs = questionConfigLoader.load();
6
60
  const lowerDesc = description.toLowerCase();
7
- questions.push({
8
- id: 'users',
9
- category: 'users',
10
- question: `Who are the primary users of "${title}"?`,
11
- hint: 'e.g., "authenticated users", "admin only", "all visitors"',
12
- required: true,
13
- answerType: 'text',
14
- });
15
- questions.push({
16
- id: 'success',
17
- category: 'success',
18
- question: 'How will you know when this feature is successfully implemented?',
19
- hint: "Describe the outcome from the user's perspective",
20
- required: true,
21
- answerType: 'text',
22
- });
23
- questions.push({
24
- id: 'scope',
25
- category: 'scope',
26
- question: 'What is the scope of this change?',
27
- required: true,
28
- answerType: 'choice',
29
- choices: [
30
- 'Small change in one place',
31
- 'Medium feature across 2-3 areas',
32
- 'Large cross-module change',
33
- 'Major architectural change',
34
- ],
35
- });
36
- questions.push({
37
- id: 'edge_cases',
38
- category: 'behavior',
39
- question: 'What should happen in error or edge cases?',
40
- hint: 'e.g., "show error message", "redirect to login", "fail silently"',
41
- required: false,
42
- answerType: 'text',
43
- });
44
- if (context?.hasDatabase === true || lowerDesc.includes('data') || lowerDesc.includes('store')) {
45
- questions.push({
46
- id: 'data',
47
- category: 'data',
48
- question: 'What data needs to be stored or retrieved for this feature?',
49
- hint: 'List the key fields/entities involved',
50
- required: false,
51
- answerType: 'text',
52
- });
53
- }
54
- if (context?.isApi === true || lowerDesc.includes('api') || lowerDesc.includes('endpoint')) {
55
- questions.push({
56
- id: 'api_contract',
57
- category: 'constraints',
58
- question: 'Does this require a new API endpoint or changes to existing ones?',
59
- required: false,
60
- answerType: 'yes-no',
61
- });
61
+ const questions = [];
62
+ for (const config of configs) {
63
+ if (!shouldInclude(config, lowerDesc, context)) {
64
+ continue;
65
+ }
66
+ const question = {
67
+ id: config.id,
68
+ category: config.category,
69
+ question: resolveTemplate(config.questionTemplate, title),
70
+ required: config.required,
71
+ answerType: config.answerType,
72
+ };
73
+ if (config.hint !== undefined) {
74
+ question.hint = config.hint;
75
+ }
76
+ if (config.choices !== undefined) {
77
+ question.choices = config.choices;
78
+ }
79
+ questions.push(question);
62
80
  }
63
- questions.push({
64
- id: 'performance',
65
- category: 'constraints',
66
- question: 'Are there performance requirements (response time, load, etc.)?',
67
- required: false,
68
- answerType: 'text',
69
- });
70
81
  return questions;
71
82
  }
72
83
  /** Format questions as a readable prompt for the LLM to present to the user */
@@ -1 +1 @@
1
- {"version":3,"file":"question-generator.js","sourceRoot":"","sources":["../../../src/engine/elicitation/question-generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"question-generator.js","sourceRoot":"","sources":["../../../src/engine/elicitation/question-generator.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,4EAA4E;AAC5E,0FAA0F;AAE1F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAInD,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yDAAyD,CAAC;IAClF,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;SACtE,QAAQ,CAAC,0EAA0E,CAAC;IACvF,gBAAgB,EAAE,CAAC;SAChB,MAAM,EAAE;SACR,QAAQ,CAAC,iEAAiE,CAAC;IAC9E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAChF,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IACvE,UAAU,EAAE,CAAC;SACV,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;SAClC,QAAQ,CAAC,wCAAwC,CAAC;IACrD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;IACjG,SAAS,EAAE,CAAC;SACT,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;SAC/B,QAAQ,CACP,kGAAkG,CACnG;IACH,iBAAiB,EAAE,CAAC;SACjB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,4DAA4D,CAAC;CAC1E,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,IAAI,YAAY,CAC3C,uBAAuB,EACvB,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC,CACzC,CAAC;AAEF;;GAEG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,KAAa;IACtD,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CACpB,MAAiC,EACjC,SAAiB,EACjB,OAAwE;IAExE,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,IAAI,OAAO,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO,EAAE,KAAK,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,qBAAqB,CACnC,KAAa,EACb,WAAmB,EACnB,OAAwE;IAExE,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,SAAS,GAA0B,EAAE,CAAC;IAE5C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAwB;YACpC,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC;YACzD,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,QAAQ,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QAC9B,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QACpC,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,uBAAuB,CAAC,OAA2B;IACjE,MAAM,KAAK,GAAa;QACtB,iCAAiC,OAAO,CAAC,KAAK,GAAG;QACjD,EAAE;QACF,uEAAuE;QACvE,EAAE;KACH,CAAC;IAEF,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC;QAChE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1B,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CACR,0FAA0F,CAC3F,CAAC;IAEF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,YAAY,CAC1B,SAAgC,EAChC,WAAmB;IAEnB,MAAM,OAAO,GAA2B,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;YACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,GAAG,IAAI,CAAC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACvC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FeasibilityRule } from '../types/index.js';
2
+ export type { FeasibilityRule };
3
+ /**
4
+ * Load the merged feasibility keyword rules for a given project.
5
+ * Falls back to system defaults when no overrides exist.
6
+ */
7
+ export declare function loadFeasibilityRules(projectHash?: string): FeasibilityRule[];
8
+ /**
9
+ * Extract keywords for a specific category from the loaded rules.
10
+ * Returns an empty array if no rule exists for the category.
11
+ */
12
+ export declare function getKeywordsByCategory(rules: FeasibilityRule[], category: FeasibilityRule['category']): string[];
13
+ //# sourceMappingURL=feasibility-rules-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feasibility-rules-loader.d.ts","sourceRoot":"","sources":["../../src/engine/feasibility-rules-loader.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkBzD,YAAY,EAAE,eAAe,EAAE,CAAC;AAUhC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAE5E;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,eAAe,EAAE,EACxB,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,GACpC,MAAM,EAAE,CAEV"}
@@ -0,0 +1,39 @@
1
+ // engine/feasibility-rules-loader.ts — Config loader for feasibility-validator (SPEC-213)
2
+ //
3
+ // Provides the 3-layer configurable keyword rules using ConfigLoader.
4
+ // Layer 1: src/config/feasibility-rules.json — system defaults
5
+ // Layer 2: data/global/feasibility-rules-custom.json — global overrides
6
+ // Layer 3: data/projects/{hash}/config/feasibility-rules-overrides.json — project overrides
7
+ import { z } from 'zod';
8
+ import { ConfigLoader } from './config-loader.js';
9
+ // ── Schema ────────────────────────────────────────────────────────────────────
10
+ const feasibilityRuleSchema = z.object({
11
+ id: z.string().min(1).describe('Unique identifier for this rule group'),
12
+ category: z
13
+ .enum(['feature', 'performance', 'security', 'cheap', 'offline', 'realtime'])
14
+ .describe('Category of keywords. Valid values: feature, performance, security, cheap, offline, realtime'),
15
+ keywords: z
16
+ .array(z.string().min(1))
17
+ .min(1)
18
+ .describe('List of keyword strings to match in requirements text (case-insensitive)'),
19
+ });
20
+ const feasibilityRulesSchema = z
21
+ .array(feasibilityRuleSchema)
22
+ .describe('List of keyword rule groups for feasibility validation');
23
+ // ── Loader instance ───────────────────────────────────────────────────────────
24
+ const loader = new ConfigLoader('feasibility-rules', feasibilityRulesSchema);
25
+ /**
26
+ * Load the merged feasibility keyword rules for a given project.
27
+ * Falls back to system defaults when no overrides exist.
28
+ */
29
+ export function loadFeasibilityRules(projectHash) {
30
+ return loader.load(projectHash);
31
+ }
32
+ /**
33
+ * Extract keywords for a specific category from the loaded rules.
34
+ * Returns an empty array if no rule exists for the category.
35
+ */
36
+ export function getKeywordsByCategory(rules, category) {
37
+ return rules.find((r) => r.category === category)?.keywords ?? [];
38
+ }
39
+ //# sourceMappingURL=feasibility-rules-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feasibility-rules-loader.js","sourceRoot":"","sources":["../../src/engine/feasibility-rules-loader.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,EAAE;AACF,sEAAsE;AACtE,+DAA+D;AAC/D,wEAAwE;AACxE,4FAA4F;AAE5F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,iFAAiF;AAEjF,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;IACvE,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;SAC5E,QAAQ,CACP,8FAA8F,CAC/F;IACH,QAAQ,EAAE,CAAC;SACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SACxB,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,0EAA0E,CAAC;CACxF,CAAC,CAAC;AAIH,MAAM,sBAAsB,GAAG,CAAC;KAC7B,KAAK,CAAC,qBAAqB,CAAC;KAC5B,QAAQ,CAAC,wDAAwD,CAAC,CAAC;AAEtE,iFAAiF;AAEjF,MAAM,MAAM,GAAG,IAAI,YAAY,CAAkB,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;AAE9F;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAoB;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAwB,EACxB,QAAqC;IAErC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;AACpE,CAAC"}
@@ -3,5 +3,5 @@ import type { ProjectKnowledge, FeasibilityReport } from '../types/index.js';
3
3
  * Validate whether a set of requirements is feasible given project context.
4
4
  * Returns a FeasibilityReport with scored issues and a viability flag.
5
5
  */
6
- export declare function validateFeasibility(requirements: string[], knowledge: ProjectKnowledge): FeasibilityReport;
6
+ export declare function validateFeasibility(requirements: string[], knowledge: ProjectKnowledge, projectHash?: string): FeasibilityReport;
7
7
  //# sourceMappingURL=feasibility-validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"feasibility-validator.d.ts","sourceRoot":"","sources":["../../src/engine/feasibility-validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AA8F/F;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,GAC1B,iBAAiB,CA+BnB"}
1
+ {"version":3,"file":"feasibility-validator.d.ts","sourceRoot":"","sources":["../../src/engine/feasibility-validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAC;AAwB/F;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EAAE,EACtB,SAAS,EAAE,gBAAgB,EAC3B,WAAW,CAAC,EAAE,MAAM,GACnB,iBAAiB,CAwCnB"}
@@ -1,74 +1,10 @@
1
1
  // engine/feasibility-validator.ts — Requirement feasibility validation (SPEC-040)
2
2
  // Pure function — no I/O. Evaluates a list of requirements and returns a FeasibilityReport.
3
+ import { loadFeasibilityRules, getKeywordsByCategory } from './feasibility-rules-loader.js';
3
4
  // ---------------------------------------------------------------------------
4
5
  // Constants
5
6
  // ---------------------------------------------------------------------------
6
7
  const DISCLAIMER = 'Based on patterns from similar projects. Adjust based on your specific context.';
7
- const FEATURE_KEYWORDS = [
8
- 'quiero',
9
- 'debe',
10
- 'should',
11
- 'feature',
12
- 'screen',
13
- 'page',
14
- 'module',
15
- 'endpoint',
16
- 'flow',
17
- 'integration',
18
- 'dashboard',
19
- 'panel',
20
- 'view',
21
- 'form',
22
- 'report',
23
- 'notification',
24
- 'alert',
25
- 'widget',
26
- ];
27
- const PERFORMANCE_KEYWORDS = [
28
- 'ultra-fast',
29
- 'ultra fast',
30
- '< 100ms',
31
- '<100ms',
32
- 'high performance',
33
- 'low latency',
34
- 'sub-second',
35
- 'instant',
36
- 'real-time response',
37
- ];
38
- const SECURITY_KEYWORDS = [
39
- 'encrypted',
40
- 'encryption',
41
- 'highly secure',
42
- 'compliance',
43
- 'hipaa',
44
- 'gdpr',
45
- 'pci',
46
- 'soc2',
47
- 'zero-trust',
48
- 'audit log',
49
- 'audit trail',
50
- ];
51
- const CHEAP_KEYWORDS = [
52
- 'cheap',
53
- 'zero cost',
54
- 'free',
55
- 'no cost',
56
- 'minimal cost',
57
- 'low cost',
58
- 'budget',
59
- 'affordable',
60
- 'open source only',
61
- ];
62
- const OFFLINE_KEYWORDS = ['offline', 'offline mode', 'no internet', 'works offline'];
63
- const REALTIME_KEYWORDS = [
64
- 'real-time sync',
65
- 'realtime sync',
66
- 'live sync',
67
- 'instant sync',
68
- 'real-time updates',
69
- 'websocket sync',
70
- 'live updates',
71
- ];
72
8
  // ---------------------------------------------------------------------------
73
9
  // Score weights
74
10
  // ---------------------------------------------------------------------------
@@ -84,20 +20,27 @@ const SCORE_PENALTIES = {
84
20
  * Validate whether a set of requirements is feasible given project context.
85
21
  * Returns a FeasibilityReport with scored issues and a viability flag.
86
22
  */
87
- export function validateFeasibility(requirements, knowledge) {
23
+ export function validateFeasibility(requirements, knowledge, projectHash) {
24
+ const rules = loadFeasibilityRules(projectHash);
25
+ const featureKeywords = getKeywordsByCategory(rules, 'feature');
26
+ const performanceKeywords = getKeywordsByCategory(rules, 'performance');
27
+ const securityKeywords = getKeywordsByCategory(rules, 'security');
28
+ const cheapKeywords = getKeywordsByCategory(rules, 'cheap');
29
+ const offlineKeywords = getKeywordsByCategory(rules, 'offline');
30
+ const realtimeKeywords = getKeywordsByCategory(rules, 'realtime');
88
31
  const issues = [];
89
32
  const contextUsed = [];
90
33
  const fullText = requirements.join(' ').toLowerCase();
91
34
  const teamSize = resolveTeamSize(knowledge, contextUsed);
92
- const featureCount = countFeatures(requirements);
35
+ const featureCount = countFeatures(requirements, featureKeywords);
93
36
  // Rule 1: Timeline / team size
94
37
  checkTimelineIssues(featureCount, teamSize, issues, contextUsed);
95
38
  // Rule 2: Performance paradox
96
- checkPerformanceParadox(fullText, issues);
39
+ checkPerformanceParadox(fullText, performanceKeywords, securityKeywords, cheapKeywords, issues);
97
40
  // Rule 3: Scope creep
98
41
  checkScopeCreep(requirements.length, issues);
99
42
  // Rule 4: Offline vs real-time contradiction
100
- checkOfflineRealtime(fullText, issues);
43
+ checkOfflineRealtime(fullText, offlineKeywords, realtimeKeywords, issues);
101
44
  // Score calculation
102
45
  let score = 100;
103
46
  for (const issue of issues) {
@@ -137,10 +80,10 @@ function checkTimelineIssues(featureCount, teamSize, issues, contextUsed) {
137
80
  });
138
81
  }
139
82
  }
140
- function checkPerformanceParadox(fullText, issues) {
141
- const hasPerf = PERFORMANCE_KEYWORDS.some((kw) => fullText.includes(kw));
142
- const hasSecurity = SECURITY_KEYWORDS.some((kw) => fullText.includes(kw));
143
- const hasCheap = CHEAP_KEYWORDS.some((kw) => fullText.includes(kw));
83
+ function checkPerformanceParadox(fullText, performanceKeywords, securityKeywords, cheapKeywords, issues) {
84
+ const hasPerf = performanceKeywords.some((kw) => fullText.includes(kw));
85
+ const hasSecurity = securityKeywords.some((kw) => fullText.includes(kw));
86
+ const hasCheap = cheapKeywords.some((kw) => fullText.includes(kw));
144
87
  if (hasPerf && hasSecurity && hasCheap) {
145
88
  issues.push({
146
89
  type: 'performance',
@@ -166,9 +109,9 @@ function checkScopeCreep(requirementCount, issues) {
166
109
  });
167
110
  }
168
111
  }
169
- function checkOfflineRealtime(fullText, issues) {
170
- const hasOffline = OFFLINE_KEYWORDS.some((kw) => fullText.includes(kw));
171
- const hasRealtime = REALTIME_KEYWORDS.some((kw) => fullText.includes(kw));
112
+ function checkOfflineRealtime(fullText, offlineKeywords, realtimeKeywords, issues) {
113
+ const hasOffline = offlineKeywords.some((kw) => fullText.includes(kw));
114
+ const hasRealtime = realtimeKeywords.some((kw) => fullText.includes(kw));
172
115
  if (hasOffline && hasRealtime) {
173
116
  issues.push({
174
117
  type: 'contradiction',
@@ -193,10 +136,10 @@ function resolveTeamSize(knowledge, contextUsed) {
193
136
  // We cannot reliably know team size unless contributed — return 0 (unknown)
194
137
  return 0;
195
138
  }
196
- function countFeatures(requirements) {
139
+ function countFeatures(requirements, featureKeywords) {
197
140
  const text = requirements.join(' ').toLowerCase();
198
141
  const words = text.split(/\W+/);
199
- return words.filter((w) => FEATURE_KEYWORDS.includes(w)).length;
142
+ return words.filter((w) => featureKeywords.includes(w)).length;
200
143
  }
201
144
  function buildSummary(score, issues, viable) {
202
145
  if (issues.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"feasibility-validator.js","sourceRoot":"","sources":["../../src/engine/feasibility-validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feasibility-validator.js","sourceRoot":"","sources":["../../src/engine/feasibility-validator.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,20 @@
1
- import type { RbacRole, PermissionAction } from '../../types/index.js';
1
+ import type { RbacRole, PermissionAction, RbacRoleConfig } from '../../types/index.js';
2
2
  /**
3
- * Permissions granted to each role.
3
+ * Load all role definitions for an optional project, defaulting to system roles.
4
+ * Returns a map from role id to its config entry.
5
+ */
6
+ export declare function loadRoleConfigs(projectHash?: string): Map<string, RbacRoleConfig>;
7
+ /**
8
+ * Permissions granted to each role (system defaults).
4
9
  * All roles implicitly support 'read' — it is always included.
10
+ *
11
+ * For runtime extensibility (custom roles added via org/project config),
12
+ * use loadRoleConfigs(projectHash) instead.
5
13
  */
6
14
  export declare const ROLE_PERMISSIONS: Readonly<Record<RbacRole, ReadonlySet<PermissionAction>>>;
7
15
  export declare const ROLE_DESCRIPTIONS: Readonly<Record<RbacRole, string>>;
8
16
  /** Returns true if the given role has the requested permission on any resource. */
9
- export declare function roleHasPermission(role: RbacRole, action: PermissionAction): boolean;
10
- /** Returns all roles defined in the system. */
11
- export declare function listRoles(): RbacRole[];
17
+ export declare function roleHasPermission(role: string, action: PermissionAction): boolean;
18
+ /** Returns all roles defined in the system (or project if projectHash provided). */
19
+ export declare function listRoles(projectHash?: string): string[];
12
20
  //# sourceMappingURL=roles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../../src/engine/rbac/roles.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAMvE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAM7E,CAAC;AAMX,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAOvD,CAAC;AAMX,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEnF;AAED,+CAA+C;AAC/C,wBAAgB,SAAS,IAAI,QAAQ,EAAE,CAEtC"}
1
+ {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../../src/engine/rbac/roles.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA8BvF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAGjF;AASD;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAKvB,CAAC;AAMjE,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAE1B,CAAC;AAMxC,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAKjF;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAKxD"}
@@ -1,37 +1,71 @@
1
- // engine/rbac/roles.ts — Role definitions and permission sets for SPEC-166
1
+ // engine/rbac/roles.ts — Role definitions and permission sets (SPEC-166, SPEC-215)
2
+ //
3
+ // Roles and permissions are now loaded from src/config/rbac-roles.json via
4
+ // ConfigLoader, making them extensible per organization without code changes.
5
+ // The public API is backward-compatible: ROLE_PERMISSIONS, ROLE_DESCRIPTIONS,
6
+ // roleHasPermission, and listRoles all work exactly as before.
7
+ import { z } from 'zod';
8
+ import { ConfigLoader } from '../config-loader.js';
2
9
  // ---------------------------------------------------------------------------
3
- // Role permission matrix
10
+ // Config schema
4
11
  // ---------------------------------------------------------------------------
12
+ const PermissionActionSchema = z.enum([
13
+ 'create',
14
+ 'read',
15
+ 'update',
16
+ 'delete',
17
+ 'approve',
18
+ 'implement',
19
+ 'configure',
20
+ ]);
21
+ const RbacRoleConfigSchema = z.object({
22
+ id: z.string(),
23
+ description: z.string(),
24
+ permissions: z.array(PermissionActionSchema),
25
+ });
26
+ const RbacRoleConfigArraySchema = z.array(RbacRoleConfigSchema);
27
+ // ---------------------------------------------------------------------------
28
+ // Config loading (module-level, synchronous)
29
+ // ---------------------------------------------------------------------------
30
+ const loader = new ConfigLoader('rbac-roles', RbacRoleConfigArraySchema);
5
31
  /**
6
- * Permissions granted to each role.
32
+ * Load all role definitions for an optional project, defaulting to system roles.
33
+ * Returns a map from role id to its config entry.
34
+ */
35
+ export function loadRoleConfigs(projectHash) {
36
+ const items = loader.load(projectHash);
37
+ return new Map(items.map((item) => [item.id, item]));
38
+ }
39
+ // System-level defaults — used for ROLE_PERMISSIONS and ROLE_DESCRIPTIONS constants.
40
+ const _systemRoles = loader.load();
41
+ // ---------------------------------------------------------------------------
42
+ // Role permission matrix (backward-compatible)
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Permissions granted to each role (system defaults).
7
46
  * All roles implicitly support 'read' — it is always included.
47
+ *
48
+ * For runtime extensibility (custom roles added via org/project config),
49
+ * use loadRoleConfigs(projectHash) instead.
8
50
  */
9
- export const ROLE_PERMISSIONS = {
10
- Admin: new Set(['create', 'read', 'update', 'delete', 'approve', 'implement', 'configure']),
11
- Architect: new Set(['create', 'read', 'update', 'approve', 'configure']),
12
- Developer: new Set(['read', 'update', 'implement']),
13
- Reviewer: new Set(['read', 'approve']),
14
- Observer: new Set(['read']),
15
- };
16
- // ---------------------------------------------------------------------------
17
- // Role hierarchy (for display / description purposes)
18
- // ---------------------------------------------------------------------------
19
- export const ROLE_DESCRIPTIONS = {
20
- Admin: 'Full access to all operations: create, read, update, delete, approve, implement, configure.',
21
- Architect: 'Can create/approve specs and configure the project constitution.',
22
- Developer: 'Can read specs and implement (update) them.',
23
- Reviewer: 'Can read and approve/reject specs.',
24
- Observer: 'Read-only access to all specs and project data.',
25
- };
51
+ export const ROLE_PERMISSIONS = Object.freeze(Object.fromEntries(_systemRoles.map((r) => [r.id, new Set(r.permissions)])));
52
+ // ---------------------------------------------------------------------------
53
+ // Role descriptions (backward-compatible)
54
+ // ---------------------------------------------------------------------------
55
+ export const ROLE_DESCRIPTIONS = Object.freeze(Object.fromEntries(_systemRoles.map((r) => [r.id, r.description])));
26
56
  // ---------------------------------------------------------------------------
27
57
  // Helpers
28
58
  // ---------------------------------------------------------------------------
29
59
  /** Returns true if the given role has the requested permission on any resource. */
30
60
  export function roleHasPermission(role, action) {
31
- return ROLE_PERMISSIONS[role].has(action);
61
+ const perms = ROLE_PERMISSIONS[role];
62
+ return perms?.has(action) ?? false;
32
63
  }
33
- /** Returns all roles defined in the system. */
34
- export function listRoles() {
35
- return Object.keys(ROLE_PERMISSIONS);
64
+ /** Returns all roles defined in the system (or project if projectHash provided). */
65
+ export function listRoles(projectHash) {
66
+ if (projectHash) {
67
+ return [...loadRoleConfigs(projectHash).keys()];
68
+ }
69
+ return _systemRoles.map((r) => r.id);
36
70
  }
37
71
  //# sourceMappingURL=roles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/engine/rbac/roles.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAI3E,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA8D;IACzF,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAC3F,SAAS,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACxE,SAAS,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACnD,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;CACnB,CAAC;AAEX,8EAA8E;AAC9E,sDAAsD;AACtD,8EAA8E;AAE9E,MAAM,CAAC,MAAM,iBAAiB,GAAuC;IACnE,KAAK,EACH,6FAA6F;IAC/F,SAAS,EAAE,kEAAkE;IAC7E,SAAS,EAAE,6CAA6C;IACxD,QAAQ,EAAE,oCAAoC;IAC9C,QAAQ,EAAE,iDAAiD;CACnD,CAAC;AAEX,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,IAAc,EAAE,MAAwB;IACxE,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAe,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/engine/rbac/roles.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,+DAA+D;AAE/D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC;IACpC,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,WAAW;IACX,WAAW;CACZ,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC;CAC7C,CAAC,CAAC;AAEH,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;AAEhE,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,MAAM,MAAM,GAAG,IAAI,YAAY,CAAiB,YAAY,EAAE,yBAAyB,CAAC,CAAC;AAEzF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,WAAoB;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,qFAAqF;AACrF,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;AAEnC,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,WAAW,CAChB,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,CAAkC,CAAC,CAAC,CACzF,CAC2D,CAAC;AAEjE,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E,MAAM,CAAC,MAAM,iBAAiB,GAAuC,MAAM,CAAC,MAAM,CAChF,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAC7B,CAAC;AAExC,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAAwB;IACtE,MAAM,KAAK,GAA8C,gBAAgB,CAAC,IAAgB,CAE7E,CAAC;IACd,OAAO,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;AACrC,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,SAAS,CAAC,WAAoB;IAC5C,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { Spec, ReadinessReport } from '../types/index.js';
2
- export declare function checkSpecReadiness(spec: Spec, mode: 'strict' | 'lenient'): Promise<ReadinessReport>;
2
+ export declare function checkSpecReadiness(spec: Spec, mode: 'strict' | 'lenient', projectHash?: string): Promise<ReadinessReport>;
3
3
  //# sourceMappingURL=readiness-checker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"readiness-checker.d.ts","sourceRoot":"","sources":["../../src/engine/readiness-checker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,IAAI,EACJ,eAAe,EAIhB,MAAM,mBAAmB,CAAC;AAoL3B,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,SAAS,GACzB,OAAO,CAAC,eAAe,CAAC,CA2D1B"}
1
+ {"version":3,"file":"readiness-checker.d.ts","sourceRoot":"","sources":["../../src/engine/readiness-checker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,IAAI,EACJ,eAAe,EAIhB,MAAM,mBAAmB,CAAC;AA4K3B,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,QAAQ,GAAG,SAAS,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,eAAe,CAAC,CA+D1B"}