popeye-cli 2.1.0 → 2.2.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.
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +4 -1
- package/dist/cli/interactive.js.map +1 -1
- package/dist/generators/all.d.ts.map +1 -1
- package/dist/generators/all.js +23 -1
- package/dist/generators/all.js.map +1 -1
- package/dist/pipeline/artifact-manager.d.ts.map +1 -1
- package/dist/pipeline/artifact-manager.js +3 -0
- package/dist/pipeline/artifact-manager.js.map +1 -1
- package/dist/pipeline/gate-engine.js +1 -1
- package/dist/pipeline/gate-engine.js.map +1 -1
- package/dist/pipeline/migration.d.ts.map +1 -1
- package/dist/pipeline/migration.js +3 -26
- package/dist/pipeline/migration.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +5 -0
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/phases/intake.d.ts +1 -0
- package/dist/pipeline/phases/intake.d.ts.map +1 -1
- package/dist/pipeline/phases/intake.js +49 -10
- package/dist/pipeline/phases/intake.js.map +1 -1
- package/dist/pipeline/phases/role-planning.d.ts.map +1 -1
- package/dist/pipeline/phases/role-planning.js +2 -3
- package/dist/pipeline/phases/role-planning.js.map +1 -1
- package/dist/pipeline/skills/constitution-generator.d.ts +51 -0
- package/dist/pipeline/skills/constitution-generator.d.ts.map +1 -0
- package/dist/pipeline/skills/constitution-generator.js +210 -0
- package/dist/pipeline/skills/constitution-generator.js.map +1 -0
- package/dist/pipeline/skills/generator.d.ts +65 -0
- package/dist/pipeline/skills/generator.d.ts.map +1 -0
- package/dist/pipeline/skills/generator.js +221 -0
- package/dist/pipeline/skills/generator.js.map +1 -0
- package/dist/pipeline/skills/role-map.d.ts +38 -0
- package/dist/pipeline/skills/role-map.d.ts.map +1 -0
- package/dist/pipeline/skills/role-map.js +234 -0
- package/dist/pipeline/skills/role-map.js.map +1 -0
- package/dist/pipeline/skills/types.d.ts +47 -0
- package/dist/pipeline/skills/types.d.ts.map +1 -0
- package/dist/pipeline/skills/types.js +5 -0
- package/dist/pipeline/skills/types.js.map +1 -0
- package/dist/pipeline/type-defs/artifacts.d.ts +5 -0
- package/dist/pipeline/type-defs/artifacts.d.ts.map +1 -1
- package/dist/pipeline/type-defs/artifacts.js +1 -0
- package/dist/pipeline/type-defs/artifacts.js.map +1 -1
- package/dist/pipeline/type-defs/audit.d.ts +3 -0
- package/dist/pipeline/type-defs/audit.d.ts.map +1 -1
- package/dist/pipeline/type-defs/checks.d.ts +1 -0
- package/dist/pipeline/type-defs/checks.d.ts.map +1 -1
- package/dist/pipeline/type-defs/packets.d.ts +15 -0
- package/dist/pipeline/type-defs/packets.d.ts.map +1 -1
- package/dist/pipeline/type-defs/state.d.ts +5 -0
- package/dist/pipeline/type-defs/state.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/interactive.ts +4 -1
- package/src/generators/all.ts +23 -1
- package/src/pipeline/artifact-manager.ts +3 -0
- package/src/pipeline/gate-engine.ts +1 -1
- package/src/pipeline/migration.ts +5 -30
- package/src/pipeline/orchestrator.ts +6 -0
- package/src/pipeline/phases/intake.ts +60 -11
- package/src/pipeline/phases/role-planning.ts +2 -3
- package/src/pipeline/skills/constitution-generator.ts +236 -0
- package/src/pipeline/skills/generator.ts +287 -0
- package/src/pipeline/skills/role-map.ts +248 -0
- package/src/pipeline/skills/types.ts +53 -0
- package/src/pipeline/type-defs/artifacts.ts +1 -0
- package/tests/pipeline/migration.test.ts +4 -3
- package/tests/pipeline/skills/constitution-generator.test.ts +201 -0
- package/tests/pipeline/skills/generator.test.ts +213 -0
- package/tests/pipeline/skills/role-map.test.ts +198 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic constitution generation — no AI call required.
|
|
3
|
+
* Produces skills/POPEYE_CONSTITUTION.md from templates + inferred tech stack.
|
|
4
|
+
* Includes pipeline governance invariants that never change.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
// ─── Constants ──────────────────────────────────────────
|
|
9
|
+
const CONSTITUTION_FILENAME = 'POPEYE_CONSTITUTION.md';
|
|
10
|
+
const PIPELINE_VERSION = '1.0';
|
|
11
|
+
// ─── Public API ─────────────────────────────────────────
|
|
12
|
+
/**
|
|
13
|
+
* Generate the project constitution file if it doesn't already exist.
|
|
14
|
+
* Entirely deterministic — built from templates and tech stack data.
|
|
15
|
+
*
|
|
16
|
+
* @param context - Constitution generation context
|
|
17
|
+
*/
|
|
18
|
+
export function generateConstitution(context) {
|
|
19
|
+
const { skillsDir } = context;
|
|
20
|
+
if (shouldSkipConstitution(skillsDir)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!existsSync(skillsDir)) {
|
|
24
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
const content = buildConstitutionContent(context);
|
|
27
|
+
const constitutionPath = join(skillsDir, CONSTITUTION_FILENAME);
|
|
28
|
+
writeFileSync(constitutionPath, content, 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if constitution generation should be skipped.
|
|
32
|
+
* Returns true if the file already exists (hand-written or prior run).
|
|
33
|
+
*
|
|
34
|
+
* @param skillsDir - Path to the skills directory
|
|
35
|
+
* @returns true if generation should be skipped
|
|
36
|
+
*/
|
|
37
|
+
export function shouldSkipConstitution(skillsDir) {
|
|
38
|
+
const constitutionPath = join(skillsDir, CONSTITUTION_FILENAME);
|
|
39
|
+
return existsSync(constitutionPath);
|
|
40
|
+
}
|
|
41
|
+
// ─── Content Assembly ───────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Build the full constitution markdown content.
|
|
44
|
+
*
|
|
45
|
+
* @param context - Constitution generation context
|
|
46
|
+
* @returns Complete markdown string
|
|
47
|
+
*/
|
|
48
|
+
function buildConstitutionContent(context) {
|
|
49
|
+
const { projectName, language, techStack, sessionGuidance } = context;
|
|
50
|
+
const date = new Date().toISOString().split('T')[0];
|
|
51
|
+
const sections = [
|
|
52
|
+
`# Project Constitution: ${projectName}`,
|
|
53
|
+
'',
|
|
54
|
+
`Generated: ${date} | Language: ${language} | Pipeline: v${PIPELINE_VERSION}`,
|
|
55
|
+
'',
|
|
56
|
+
getTechStackSection(techStack),
|
|
57
|
+
getArchitectureRules(techStack),
|
|
58
|
+
getCodeQualityRules(),
|
|
59
|
+
getGovernanceRules(),
|
|
60
|
+
getConstraintsSection(language, sessionGuidance),
|
|
61
|
+
getImmutabilitySection(),
|
|
62
|
+
];
|
|
63
|
+
return sections.join('\n');
|
|
64
|
+
}
|
|
65
|
+
// ─── Template Sections ──────────────────────────────────
|
|
66
|
+
/**
|
|
67
|
+
* Generate the tech stack section from inferred stack data.
|
|
68
|
+
*
|
|
69
|
+
* @param techStack - Inferred tech stack
|
|
70
|
+
* @returns Markdown section
|
|
71
|
+
*/
|
|
72
|
+
export function getTechStackSection(techStack) {
|
|
73
|
+
const lines = ['## Tech Stack'];
|
|
74
|
+
if (techStack.language)
|
|
75
|
+
lines.push(`- Language: ${techStack.language}`);
|
|
76
|
+
if (techStack.backend)
|
|
77
|
+
lines.push(`- Framework: ${techStack.backend}`);
|
|
78
|
+
if (techStack.frontend)
|
|
79
|
+
lines.push(`- Frontend: ${techStack.frontend}`);
|
|
80
|
+
if (techStack.database)
|
|
81
|
+
lines.push(`- Database: ${techStack.database}`);
|
|
82
|
+
if (techStack.orm)
|
|
83
|
+
lines.push(`- ORM: ${techStack.orm}`);
|
|
84
|
+
if (techStack.testing)
|
|
85
|
+
lines.push(`- Testing: ${techStack.testing}`);
|
|
86
|
+
lines.push('');
|
|
87
|
+
return lines.join('\n');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generate architecture rules based on the tech stack.
|
|
91
|
+
*
|
|
92
|
+
* @param techStack - Inferred tech stack
|
|
93
|
+
* @returns Markdown section
|
|
94
|
+
*/
|
|
95
|
+
export function getArchitectureRules(techStack) {
|
|
96
|
+
const rules = [];
|
|
97
|
+
let ruleNum = 1;
|
|
98
|
+
if (techStack.backend?.includes('FastAPI')) {
|
|
99
|
+
rules.push(`${ruleNum++}. All API endpoints MUST use async/await`);
|
|
100
|
+
}
|
|
101
|
+
if (techStack.backend?.includes('Express')) {
|
|
102
|
+
rules.push(`${ruleNum++}. Use Express middleware pattern for cross-cutting concerns`);
|
|
103
|
+
}
|
|
104
|
+
if (techStack.backend?.includes('Django')) {
|
|
105
|
+
rules.push(`${ruleNum++}. Follow Django app structure conventions`);
|
|
106
|
+
}
|
|
107
|
+
if (techStack.orm?.includes('SQLAlchemy')) {
|
|
108
|
+
rules.push(`${ruleNum++}. Database access exclusively via SQLAlchemy ORM`);
|
|
109
|
+
}
|
|
110
|
+
if (techStack.orm?.includes('Prisma')) {
|
|
111
|
+
rules.push(`${ruleNum++}. Database access exclusively via Prisma client`);
|
|
112
|
+
}
|
|
113
|
+
if (techStack.language?.includes('Python')) {
|
|
114
|
+
rules.push(`${ruleNum++}. Environment variables via python-dotenv, never hardcoded`);
|
|
115
|
+
rules.push(`${ruleNum++}. PEP8 style with type hints on all functions`);
|
|
116
|
+
}
|
|
117
|
+
if (techStack.language?.includes('TypeScript')) {
|
|
118
|
+
rules.push(`${ruleNum++}. TypeScript strict mode, no implicit any`);
|
|
119
|
+
rules.push(`${ruleNum++}. Environment variables via dotenv, never hardcoded`);
|
|
120
|
+
}
|
|
121
|
+
if (techStack.frontend?.includes('React')) {
|
|
122
|
+
rules.push(`${ruleNum++}. React components use functional patterns with hooks`);
|
|
123
|
+
}
|
|
124
|
+
if (techStack.frontend?.includes('Next')) {
|
|
125
|
+
rules.push(`${ruleNum++}. Next.js App Router conventions for routing and layouts`);
|
|
126
|
+
}
|
|
127
|
+
// Always add a generic rule if nothing specific matched
|
|
128
|
+
if (rules.length === 0) {
|
|
129
|
+
rules.push('1. Environment variables never hardcoded in source code');
|
|
130
|
+
rules.push('2. Clear separation of concerns between modules');
|
|
131
|
+
}
|
|
132
|
+
return ['## Architecture Rules', ...rules, ''].join('\n');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate code quality rules (constant across all projects).
|
|
136
|
+
*
|
|
137
|
+
* @returns Markdown section
|
|
138
|
+
*/
|
|
139
|
+
export function getCodeQualityRules() {
|
|
140
|
+
return [
|
|
141
|
+
'## Code Quality',
|
|
142
|
+
'1. Maximum 500 lines per source file',
|
|
143
|
+
'2. Unit tests for every module (happy path + edge case + failure)',
|
|
144
|
+
'3. Standard logging (no unstructured print statements)',
|
|
145
|
+
'4. Docstrings/JSDoc on public functions',
|
|
146
|
+
'',
|
|
147
|
+
].join('\n');
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Generate governance rules (pipeline invariants, constant).
|
|
151
|
+
*
|
|
152
|
+
* @returns Markdown section
|
|
153
|
+
*/
|
|
154
|
+
function getGovernanceRules() {
|
|
155
|
+
return [
|
|
156
|
+
'## Governance Rules',
|
|
157
|
+
'1. Consensus threshold: 0.95 with minimum 2 reviewers',
|
|
158
|
+
'2. All artifacts are immutable once stored (new versions create new files)',
|
|
159
|
+
'3. No placeholder content in production code or generated output',
|
|
160
|
+
'4. Gate failures route to RECOVERY_LOOP before phase retry',
|
|
161
|
+
'5. Constitution modifications during pipeline execution are forbidden',
|
|
162
|
+
'6. Change Requests required for scope changes after INTAKE',
|
|
163
|
+
'',
|
|
164
|
+
].join('\n');
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Generate language-specific and session-specific constraints.
|
|
168
|
+
*
|
|
169
|
+
* @param language - Project language
|
|
170
|
+
* @param sessionGuidance - Optional session guidance text
|
|
171
|
+
* @returns Markdown section
|
|
172
|
+
*/
|
|
173
|
+
export function getConstraintsSection(language, sessionGuidance) {
|
|
174
|
+
const lines = ['## Project Constraints'];
|
|
175
|
+
const langConstraints = {
|
|
176
|
+
python: ['- Python 3.11+ required', '- Use virtual environment (venv) for all operations'],
|
|
177
|
+
typescript: ['- Node.js 18+ required', '- ESM modules (import/export, .js extensions)'],
|
|
178
|
+
fullstack: [
|
|
179
|
+
'- Python 3.11+ for backend, Node.js 18+ for frontend',
|
|
180
|
+
'- Monorepo structure with clear app boundaries',
|
|
181
|
+
],
|
|
182
|
+
website: ['- Node.js 18+ required', '- SSG/SSR optimization for performance and SEO'],
|
|
183
|
+
all: [
|
|
184
|
+
'- Python 3.11+ for backend, Node.js 18+ for frontend and website',
|
|
185
|
+
'- Monorepo structure with clear app boundaries',
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
const constraints = langConstraints[language] ?? langConstraints.python;
|
|
189
|
+
lines.push(...constraints);
|
|
190
|
+
if (sessionGuidance) {
|
|
191
|
+
lines.push('', '### Session-Specific Guidance');
|
|
192
|
+
lines.push(sessionGuidance.slice(0, 500));
|
|
193
|
+
}
|
|
194
|
+
lines.push('');
|
|
195
|
+
return lines.join('\n');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Generate the immutability notice (constant).
|
|
199
|
+
*
|
|
200
|
+
* @returns Markdown section
|
|
201
|
+
*/
|
|
202
|
+
function getImmutabilitySection() {
|
|
203
|
+
return [
|
|
204
|
+
'## Immutability',
|
|
205
|
+
'This document MUST NOT be modified during pipeline execution.',
|
|
206
|
+
'Any modification triggers constitution verification failure at next gate.',
|
|
207
|
+
'',
|
|
208
|
+
].join('\n');
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=constitution-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constitution-generator.js","sourceRoot":"","sources":["../../../src/pipeline/skills/constitution-generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAKjC,2DAA2D;AAE3D,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AACvD,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAE/B,2DAA2D;AAE3D;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAA4B;IAC/D,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE9B,IAAI,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAChE,aAAa,CAAC,gBAAgB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAChE,OAAO,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACtC,CAAC;AAED,2DAA2D;AAE3D;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,OAA4B;IAC5D,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;IACtE,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpD,MAAM,QAAQ,GAAG;QACf,2BAA2B,WAAW,EAAE;QACxC,EAAE;QACF,cAAc,IAAI,gBAAgB,QAAQ,iBAAiB,gBAAgB,EAAE;QAC7E,EAAE;QACF,mBAAmB,CAAC,SAAS,CAAC;QAC9B,oBAAoB,CAAC,SAAS,CAAC;QAC/B,mBAAmB,EAAE;QACrB,kBAAkB,EAAE;QACpB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,CAAC;QAChD,sBAAsB,EAAE;KACzB,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,2DAA2D;AAE3D;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAoB;IACtD,MAAM,KAAK,GAAG,CAAC,eAAe,CAAC,CAAC;IAChC,IAAI,SAAS,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxE,IAAI,SAAS,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACvE,IAAI,SAAS,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxE,IAAI,SAAS,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxE,IAAI,SAAS,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,IAAI,SAAS,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACrE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAoB;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,IAAI,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,0CAA0C,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,6DAA6D,CAAC,CAAC;IACxF,CAAC;IACD,IAAI,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,2CAA2C,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,kDAAkD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,iDAAiD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,4DAA4D,CAAC,CAAC;QACrF,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,+CAA+C,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,2CAA2C,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,qDAAqD,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,uDAAuD,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,EAAE,0DAA0D,CAAC,CAAC;IACrF,CAAC;IAED,wDAAwD;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;QACtE,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,CAAC,uBAAuB,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,iBAAiB;QACjB,sCAAsC;QACtC,mEAAmE;QACnE,wDAAwD;QACxD,yCAAyC;QACzC,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB;IACzB,OAAO;QACL,qBAAqB;QACrB,uDAAuD;QACvD,4EAA4E;QAC5E,kEAAkE;QAClE,4DAA4D;QAC5D,uEAAuE;QACvE,4DAA4D;QAC5D,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAwB,EACxB,eAAwB;IAExB,MAAM,KAAK,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAEzC,MAAM,eAAe,GAA6B;QAChD,MAAM,EAAE,CAAC,yBAAyB,EAAE,qDAAqD,CAAC;QAC1F,UAAU,EAAE,CAAC,wBAAwB,EAAE,+CAA+C,CAAC;QACvF,SAAS,EAAE;YACT,sDAAsD;YACtD,gDAAgD;SACjD;QACD,OAAO,EAAE,CAAC,wBAAwB,EAAE,gDAAgD,CAAC;QACrF,GAAG,EAAE;YACH,kEAAkE;YAClE,gDAAgD;SACjD;KACF,CAAC;IAEF,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC;IACxE,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;IAE3B,IAAI,eAAe,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB;IAC7B,OAAO;QACL,iBAAiB;QACjB,+DAA+D;QAC/D,2EAA2E;QAC3E,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-specific skill generation.
|
|
3
|
+
* Uses a single AI call to generate tailored system prompts for active roles,
|
|
4
|
+
* then writes them as .md files with YAML frontmatter to the project's skills/ dir.
|
|
5
|
+
* Falls back to defaults with project-specific constraints on AI failure.
|
|
6
|
+
*/
|
|
7
|
+
import type { PipelineRole } from '../types.js';
|
|
8
|
+
import type { ArtifactManager } from '../artifact-manager.js';
|
|
9
|
+
import type { SkillGenerationContext, SkillsGenerationMarker, TechStack } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Generate project-specific skill .md files for all active roles.
|
|
12
|
+
* Skips roles that already have a .md file in the skills directory.
|
|
13
|
+
* Stores the raw AI response as a skill_generation_log artifact.
|
|
14
|
+
*
|
|
15
|
+
* @param context - Skill generation context with project details
|
|
16
|
+
* @param artifactManager - Optional artifact manager for logging
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateProjectSkills(context: SkillGenerationContext, artifactManager?: ArtifactManager): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a skill file should be generated for a role.
|
|
21
|
+
* Returns false if the role already has a .md file (hand-written or prior run).
|
|
22
|
+
*
|
|
23
|
+
* @param skillsDir - Path to the skills directory
|
|
24
|
+
* @param role - Pipeline role to check
|
|
25
|
+
* @returns true if the role needs a generated skill file
|
|
26
|
+
*/
|
|
27
|
+
export declare function shouldGenerateSkill(skillsDir: string, role: PipelineRole): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Build the AI prompt that requests system prompts for all roles at once.
|
|
30
|
+
*
|
|
31
|
+
* @param context - Generation context
|
|
32
|
+
* @param roles - Roles needing prompts
|
|
33
|
+
* @param techStack - Inferred tech stack
|
|
34
|
+
* @returns Formatted prompt string
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildSkillGenPrompt(context: SkillGenerationContext, roles: PipelineRole[], techStack: TechStack): string;
|
|
37
|
+
/**
|
|
38
|
+
* Parse and validate the AI response as a JSON record of role prompts.
|
|
39
|
+
* Falls back per-role: missing or invalid entries are excluded.
|
|
40
|
+
*
|
|
41
|
+
* @param response - Raw AI response text
|
|
42
|
+
* @param expectedRoles - Roles we requested prompts for
|
|
43
|
+
* @returns Validated record of role -> system prompt
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseSkillPrompts(response: string, expectedRoles: PipelineRole[]): Record<string, string>;
|
|
46
|
+
/**
|
|
47
|
+
* Render a skill definition as a Markdown file with YAML frontmatter.
|
|
48
|
+
* Format matches what the SkillLoader's parseSkillMarkdown() expects.
|
|
49
|
+
*
|
|
50
|
+
* @param role - Pipeline role
|
|
51
|
+
* @param systemPrompt - The system prompt body
|
|
52
|
+
* @param constraints - Combined constraint identifiers
|
|
53
|
+
* @param requiredOutputs - Required output types
|
|
54
|
+
* @param dependsOn - Upstream role dependencies
|
|
55
|
+
* @returns Complete markdown string
|
|
56
|
+
*/
|
|
57
|
+
export declare function renderSkillMarkdown(role: PipelineRole, systemPrompt: string, constraints: string[], requiredOutputs: string[], dependsOn: PipelineRole[]): string;
|
|
58
|
+
/**
|
|
59
|
+
* Write the generation marker file to track what was generated.
|
|
60
|
+
*
|
|
61
|
+
* @param skillsDir - Path to the skills directory
|
|
62
|
+
* @param marker - Marker data to persist
|
|
63
|
+
*/
|
|
64
|
+
export declare function writeGenerationMarker(skillsDir: string, marker: SkillsGenerationMarker): void;
|
|
65
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../src/pipeline/skills/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAY5F;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,sBAAsB,EAC/B,eAAe,CAAC,EAAE,eAAe,GAChC,OAAO,CAAC,IAAI,CAAC,CAuFf;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAGlF;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,sBAAsB,EAC/B,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,SAAS,GACnB,MAAM,CAmCR;AAID;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,YAAY,EAAE,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoBxB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,YAAY,EAClB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,EAAE,MAAM,EAAE,EACzB,SAAS,EAAE,YAAY,EAAE,GACxB,MAAM,CAuBR;AAID;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,sBAAsB,GAC7B,IAAI,CAGN"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-specific skill generation.
|
|
3
|
+
* Uses a single AI call to generate tailored system prompts for active roles,
|
|
4
|
+
* then writes them as .md files with YAML frontmatter to the project's skills/ dir.
|
|
5
|
+
* Falls back to defaults with project-specific constraints on AI failure.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { DEFAULT_SKILLS } from './defaults.js';
|
|
11
|
+
import { inferTechStack, getTemplateConstraints } from './role-map.js';
|
|
12
|
+
// ─── Constants ──────────────────────────────────────────
|
|
13
|
+
const PIPELINE_VERSION = '1.0';
|
|
14
|
+
const MARKER_FILENAME = '.popeye-skills-generated.json';
|
|
15
|
+
/** Zod schema for validating AI-generated skill prompts */
|
|
16
|
+
const SkillPromptsResponseSchema = z.record(z.string(), z.string());
|
|
17
|
+
// ─── Public API ─────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Generate project-specific skill .md files for all active roles.
|
|
20
|
+
* Skips roles that already have a .md file in the skills directory.
|
|
21
|
+
* Stores the raw AI response as a skill_generation_log artifact.
|
|
22
|
+
*
|
|
23
|
+
* @param context - Skill generation context with project details
|
|
24
|
+
* @param artifactManager - Optional artifact manager for logging
|
|
25
|
+
*/
|
|
26
|
+
export async function generateProjectSkills(context, artifactManager) {
|
|
27
|
+
const { activeRoles, skillsDir } = context;
|
|
28
|
+
// Ensure skills directory exists
|
|
29
|
+
if (!existsSync(skillsDir)) {
|
|
30
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
// Determine which roles need generation
|
|
33
|
+
const rolesToGenerate = activeRoles.filter((role) => shouldGenerateSkill(skillsDir, role));
|
|
34
|
+
if (rolesToGenerate.length === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Infer tech stack
|
|
38
|
+
const techStack = inferTechStack(context.language, context.snapshot, context.expandedSpec);
|
|
39
|
+
// Attempt AI generation
|
|
40
|
+
let aiPrompts = {};
|
|
41
|
+
let aiGenerated = false;
|
|
42
|
+
try {
|
|
43
|
+
const prompt = buildSkillGenPrompt(context, rolesToGenerate, techStack);
|
|
44
|
+
const { createClient } = await import('../../adapters/openai.js');
|
|
45
|
+
const client = await createClient();
|
|
46
|
+
const completion = await client.chat.completions.create({
|
|
47
|
+
model: 'gpt-4.1',
|
|
48
|
+
messages: [{ role: 'user', content: prompt }],
|
|
49
|
+
temperature: 0.4,
|
|
50
|
+
max_tokens: 4096,
|
|
51
|
+
});
|
|
52
|
+
const rawResponse = completion.choices[0]?.message?.content ?? '';
|
|
53
|
+
// Store raw AI response as artifact
|
|
54
|
+
if (artifactManager) {
|
|
55
|
+
artifactManager.createAndStoreText('skill_generation_log', rawResponse, 'INTAKE');
|
|
56
|
+
}
|
|
57
|
+
aiPrompts = parseSkillPrompts(rawResponse, rolesToGenerate);
|
|
58
|
+
aiGenerated = Object.keys(aiPrompts).length > 0;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// AI failure is non-fatal — fall through to defaults with project constraints
|
|
62
|
+
aiGenerated = false;
|
|
63
|
+
}
|
|
64
|
+
// Write skill files
|
|
65
|
+
for (const role of rolesToGenerate) {
|
|
66
|
+
const defaultSkill = DEFAULT_SKILLS[role];
|
|
67
|
+
const systemPrompt = aiPrompts[role] ?? defaultSkill?.systemPrompt ?? '';
|
|
68
|
+
const constraints = getTemplateConstraints(role, techStack);
|
|
69
|
+
const allConstraints = [
|
|
70
|
+
...(defaultSkill?.constraints ?? []),
|
|
71
|
+
...constraints,
|
|
72
|
+
];
|
|
73
|
+
// Deduplicate constraints
|
|
74
|
+
const uniqueConstraints = [...new Set(allConstraints)];
|
|
75
|
+
const dependsOn = defaultSkill?.depends_on ?? [];
|
|
76
|
+
const requiredOutputs = defaultSkill?.required_outputs ?? [];
|
|
77
|
+
const markdown = renderSkillMarkdown(role, systemPrompt, uniqueConstraints, requiredOutputs, dependsOn);
|
|
78
|
+
const filePath = join(skillsDir, `${role}.md`);
|
|
79
|
+
writeFileSync(filePath, markdown, 'utf-8');
|
|
80
|
+
}
|
|
81
|
+
// Write generation marker
|
|
82
|
+
const marker = {
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
pipelineVersion: PIPELINE_VERSION,
|
|
85
|
+
activeRoles: activeRoles.map(String),
|
|
86
|
+
techStack,
|
|
87
|
+
aiGenerated,
|
|
88
|
+
};
|
|
89
|
+
writeGenerationMarker(skillsDir, marker);
|
|
90
|
+
}
|
|
91
|
+
// ─── Skip Logic ─────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Check if a skill file should be generated for a role.
|
|
94
|
+
* Returns false if the role already has a .md file (hand-written or prior run).
|
|
95
|
+
*
|
|
96
|
+
* @param skillsDir - Path to the skills directory
|
|
97
|
+
* @param role - Pipeline role to check
|
|
98
|
+
* @returns true if the role needs a generated skill file
|
|
99
|
+
*/
|
|
100
|
+
export function shouldGenerateSkill(skillsDir, role) {
|
|
101
|
+
const mdPath = join(skillsDir, `${role}.md`);
|
|
102
|
+
return !existsSync(mdPath);
|
|
103
|
+
}
|
|
104
|
+
// ─── Prompt Building ────────────────────────────────────
|
|
105
|
+
/**
|
|
106
|
+
* Build the AI prompt that requests system prompts for all roles at once.
|
|
107
|
+
*
|
|
108
|
+
* @param context - Generation context
|
|
109
|
+
* @param roles - Roles needing prompts
|
|
110
|
+
* @param techStack - Inferred tech stack
|
|
111
|
+
* @returns Formatted prompt string
|
|
112
|
+
*/
|
|
113
|
+
export function buildSkillGenPrompt(context, roles, techStack) {
|
|
114
|
+
const techDesc = Object.entries(techStack)
|
|
115
|
+
.filter(([, v]) => v)
|
|
116
|
+
.map(([k, v]) => `- ${k}: ${v}`)
|
|
117
|
+
.join('\n');
|
|
118
|
+
const roleDescriptions = roles.map((role) => {
|
|
119
|
+
const defaultSkill = DEFAULT_SKILLS[role];
|
|
120
|
+
return `- ${role}: ${defaultSkill?.systemPrompt.slice(0, 100) ?? 'Pipeline role'}...`;
|
|
121
|
+
}).join('\n');
|
|
122
|
+
return `You are generating project-specific skill definitions for an AI pipeline.
|
|
123
|
+
|
|
124
|
+
## Project: ${context.projectName}
|
|
125
|
+
## Tech Stack:
|
|
126
|
+
${techDesc}
|
|
127
|
+
|
|
128
|
+
## Expanded Specification (summary):
|
|
129
|
+
${context.expandedSpec.slice(0, 3000)}
|
|
130
|
+
|
|
131
|
+
${context.sessionGuidance ? `## Session Guidance:\n${context.sessionGuidance.slice(0, 1000)}\n` : ''}
|
|
132
|
+
## Roles needing prompts:
|
|
133
|
+
${roleDescriptions}
|
|
134
|
+
|
|
135
|
+
## Instructions:
|
|
136
|
+
Generate a tailored system prompt for each role listed above. Each prompt should:
|
|
137
|
+
1. Reference the specific tech stack (e.g., "FastAPI async endpoints" not "API endpoints")
|
|
138
|
+
2. Reference the project name
|
|
139
|
+
3. Be 3-6 sentences
|
|
140
|
+
4. Focus on the role's responsibilities in this specific project context
|
|
141
|
+
|
|
142
|
+
Respond with ONLY a JSON object mapping role names to their system prompts. Example:
|
|
143
|
+
{"BACKEND_PROGRAMMER": "You are the Backend Programmer for ProjectName. You implement..."}
|
|
144
|
+
|
|
145
|
+
JSON response:`;
|
|
146
|
+
}
|
|
147
|
+
// ─── Response Parsing ───────────────────────────────────
|
|
148
|
+
/**
|
|
149
|
+
* Parse and validate the AI response as a JSON record of role prompts.
|
|
150
|
+
* Falls back per-role: missing or invalid entries are excluded.
|
|
151
|
+
*
|
|
152
|
+
* @param response - Raw AI response text
|
|
153
|
+
* @param expectedRoles - Roles we requested prompts for
|
|
154
|
+
* @returns Validated record of role -> system prompt
|
|
155
|
+
*/
|
|
156
|
+
export function parseSkillPrompts(response, expectedRoles) {
|
|
157
|
+
try {
|
|
158
|
+
// Extract JSON from response (may be wrapped in markdown code fences)
|
|
159
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
160
|
+
if (!jsonMatch)
|
|
161
|
+
return {};
|
|
162
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
163
|
+
const validated = SkillPromptsResponseSchema.parse(parsed);
|
|
164
|
+
// Filter to only expected roles with non-empty prompts
|
|
165
|
+
const result = {};
|
|
166
|
+
for (const role of expectedRoles) {
|
|
167
|
+
if (validated[role] && validated[role].trim().length > 10) {
|
|
168
|
+
result[role] = validated[role].trim();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return {};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ─── Markdown Rendering ─────────────────────────────────
|
|
178
|
+
/**
|
|
179
|
+
* Render a skill definition as a Markdown file with YAML frontmatter.
|
|
180
|
+
* Format matches what the SkillLoader's parseSkillMarkdown() expects.
|
|
181
|
+
*
|
|
182
|
+
* @param role - Pipeline role
|
|
183
|
+
* @param systemPrompt - The system prompt body
|
|
184
|
+
* @param constraints - Combined constraint identifiers
|
|
185
|
+
* @param requiredOutputs - Required output types
|
|
186
|
+
* @param dependsOn - Upstream role dependencies
|
|
187
|
+
* @returns Complete markdown string
|
|
188
|
+
*/
|
|
189
|
+
export function renderSkillMarkdown(role, systemPrompt, constraints, requiredOutputs, dependsOn) {
|
|
190
|
+
const lines = [
|
|
191
|
+
'---',
|
|
192
|
+
`role: ${role}`,
|
|
193
|
+
'version: 1.0-project',
|
|
194
|
+
'required_outputs:',
|
|
195
|
+
...requiredOutputs.map((o) => ` - ${o}`),
|
|
196
|
+
'constraints:',
|
|
197
|
+
...constraints.map((c) => ` - ${c}`),
|
|
198
|
+
];
|
|
199
|
+
if (dependsOn.length > 0) {
|
|
200
|
+
lines.push('depends_on:');
|
|
201
|
+
for (const dep of dependsOn) {
|
|
202
|
+
lines.push(` - ${dep}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
lines.push('---');
|
|
206
|
+
lines.push(systemPrompt);
|
|
207
|
+
lines.push('');
|
|
208
|
+
return lines.join('\n');
|
|
209
|
+
}
|
|
210
|
+
// ─── Marker File ────────────────────────────────────────
|
|
211
|
+
/**
|
|
212
|
+
* Write the generation marker file to track what was generated.
|
|
213
|
+
*
|
|
214
|
+
* @param skillsDir - Path to the skills directory
|
|
215
|
+
* @param marker - Marker data to persist
|
|
216
|
+
*/
|
|
217
|
+
export function writeGenerationMarker(skillsDir, marker) {
|
|
218
|
+
const markerPath = join(skillsDir, MARKER_FILENAME);
|
|
219
|
+
writeFileSync(markerPath, JSON.stringify(marker, null, 2), 'utf-8');
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../src/pipeline/skills/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared role mapping and tech stack inference.
|
|
3
|
+
* Extracted from migration.ts to be the single source of truth for
|
|
4
|
+
* language-to-role mapping and tech stack detection.
|
|
5
|
+
*/
|
|
6
|
+
import type { OutputLanguage } from '../../types/project.js';
|
|
7
|
+
import type { PipelineRole, RepoSnapshot } from '../types.js';
|
|
8
|
+
import type { TechStack } from './types.js';
|
|
9
|
+
/** Roles that always participate regardless of language */
|
|
10
|
+
export declare const SUPPORT_ROLES: PipelineRole[];
|
|
11
|
+
/** All possible implementation roles across all languages */
|
|
12
|
+
export declare const IMPLEMENTATION_ROLES: PipelineRole[];
|
|
13
|
+
/**
|
|
14
|
+
* Determine the active roles for a given language.
|
|
15
|
+
*
|
|
16
|
+
* @param language - The project's output language
|
|
17
|
+
* @returns All roles (support + implementation) active for this language
|
|
18
|
+
*/
|
|
19
|
+
export declare function getActiveRoles(language: OutputLanguage): PipelineRole[];
|
|
20
|
+
/**
|
|
21
|
+
* Infer the project's tech stack from available signals.
|
|
22
|
+
* Priority: snapshot deps > spec mentions > language defaults.
|
|
23
|
+
*
|
|
24
|
+
* @param language - The project's output language
|
|
25
|
+
* @param snapshot - Optional repo snapshot with config file data
|
|
26
|
+
* @param expandedSpec - Optional expanded specification text
|
|
27
|
+
* @returns Inferred tech stack
|
|
28
|
+
*/
|
|
29
|
+
export declare function inferTechStack(language: OutputLanguage, snapshot?: RepoSnapshot, expandedSpec?: string): TechStack;
|
|
30
|
+
/**
|
|
31
|
+
* Get deterministic template constraints for a role based on tech stack.
|
|
32
|
+
*
|
|
33
|
+
* @param role - Pipeline role
|
|
34
|
+
* @param techStack - Inferred tech stack
|
|
35
|
+
* @returns Array of constraint identifiers
|
|
36
|
+
*/
|
|
37
|
+
export declare function getTemplateConstraints(role: PipelineRole, techStack: TechStack): string[];
|
|
38
|
+
//# sourceMappingURL=role-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-map.d.ts","sourceRoot":"","sources":["../../../src/pipeline/skills/role-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI5C,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,YAAY,EAUvC,CAAC;AAcF,6DAA6D;AAC7D,eAAO,MAAM,oBAAoB,EAAE,YAAY,EAG9C,CAAC;AAIF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,EAAE,CAGvE;AAuED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,cAAc,EACxB,QAAQ,CAAC,EAAE,YAAY,EACvB,YAAY,CAAC,EAAE,MAAM,GACpB,SAAS,CAsDX;AA4CD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,GAAG,MAAM,EAAE,CAIzF"}
|