telos-framework 0.9.2 → 0.10.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.
@@ -1,89 +1,170 @@
1
1
  const fs = require('fs').promises;
2
2
  const path = require('path');
3
+ const {
4
+ COMMAND_METADATA,
5
+ getPlatformConfig,
6
+ hasNativeCommands,
7
+ transformForRulesFile
8
+ } = require('./platform-adapters');
3
9
 
10
+ /**
11
+ * Read centralized command template
12
+ */
13
+ async function readCommandTemplate(commandName) {
14
+ const templatePath = path.join(__dirname, '../../templates/commands', `${commandName}.md`);
15
+ return fs.readFile(templatePath, 'utf-8');
16
+ }
17
+
18
+ /**
19
+ * Ensure command directory exists
20
+ */
4
21
  async function ensureDirectories(projectRoot, platform) {
5
- const commandsDir = platform === 'claude'
6
- ? path.join(projectRoot, '.claude', 'commands', 'telos')
7
- : path.join(projectRoot, '.opencode', 'command');
22
+ const config = getPlatformConfig(platform);
23
+ if (!config || !config.hasNativeCommands) return null;
8
24
 
25
+ const commandsDir = path.join(projectRoot, config.commandDir);
9
26
  await fs.mkdir(commandsDir, { recursive: true });
10
27
  return commandsDir;
11
28
  }
12
29
 
13
- async function addFrontmatterToContent(content, filename) {
14
- const descriptions = {
15
- 'telos-init.md': 'Initialize Telos multi-agent system for this project',
16
- 'telos-quick.md': 'Quick Telos initialization with auto-accepted AI proposals',
17
- 'telos-validate.md': 'Validate current code against Telos purpose hierarchy',
18
- 'telos-status.md': 'Show current Telos configuration and hierarchy',
19
- 'telos-reset.md': 'Clear existing Telos installation and reinitialize'
20
- };
21
-
22
- const description = descriptions[filename] || 'Telos command';
23
-
24
- if (content.startsWith('---')) {
25
- return content;
30
+ /**
31
+ * Install slash commands for platforms with native command support
32
+ */
33
+ async function installNativeCommands(projectRoot, platform) {
34
+ const config = getPlatformConfig(platform);
35
+ if (!config || !config.hasNativeCommands) {
36
+ return [];
26
37
  }
27
-
28
- return `---\ndescription: ${description}\n---\n\n${content}`;
29
- }
30
38
 
31
- async function copyCommandFiles(projectRoot, platform) {
32
- const sourceDir = path.join(__dirname, '../../.claude/commands/telos');
33
39
  const targetDir = await ensureDirectories(projectRoot, platform);
34
-
35
- const commandFiles = [
36
- 'init.md',
37
- 'quick.md',
38
- 'reset.md',
39
- 'validate.md',
40
- 'status.md'
41
- ];
42
-
40
+ const commandNames = Object.keys(COMMAND_METADATA);
43
41
  const results = [];
44
- for (const file of commandFiles) {
45
- const sourcePath = path.join(sourceDir, file);
46
-
47
- let targetFile = file;
48
- if (platform === 'opencode') {
49
- targetFile = file.replace('.md', '').replace(/^/, 'telos-') + '.md';
50
- }
51
-
52
- const targetPath = path.join(targetDir, targetFile);
53
-
42
+
43
+ for (const commandName of commandNames) {
54
44
  try {
55
- let content = await fs.readFile(sourcePath, 'utf-8');
45
+ // Read centralized template
46
+ const content = await readCommandTemplate(commandName);
56
47
 
57
- if (platform === 'opencode') {
58
- content = await addFrontmatterToContent(content, targetFile);
59
- }
48
+ // Transform for platform
49
+ const transformed = config.transform(content, commandName);
60
50
 
61
- await fs.writeFile(targetPath, content);
51
+ // Write to target
52
+ const targetFile = config.fileNaming(commandName);
53
+ const targetPath = path.join(targetDir, targetFile);
54
+
55
+ await fs.writeFile(targetPath, transformed);
62
56
  results.push({ file: targetFile, success: true, path: targetPath });
63
57
  } catch (error) {
64
- results.push({ file: targetFile, success: false, error: error.message });
58
+ results.push({ file: commandName, success: false, error: error.message });
65
59
  }
66
60
  }
67
-
61
+
68
62
  return results;
69
63
  }
70
64
 
65
+ /**
66
+ * Generate embedded command instructions for platforms without native commands
67
+ */
68
+ async function generateEmbeddedCommands() {
69
+ const commands = {};
70
+ const commandNames = Object.keys(COMMAND_METADATA);
71
+
72
+ for (const commandName of commandNames) {
73
+ try {
74
+ commands[commandName] = await readCommandTemplate(commandName);
75
+ } catch (error) {
76
+ console.warn(`Warning: Could not read template for ${commandName}: ${error.message}`);
77
+ }
78
+ }
79
+
80
+ return transformForRulesFile(commands);
81
+ }
82
+
83
+ /**
84
+ * Embed commands into a config file for platforms without native slash commands
85
+ */
86
+ async function embedCommandsInConfig(projectRoot, platform) {
87
+ const config = getPlatformConfig(platform);
88
+ if (!config || config.hasNativeCommands) {
89
+ return { success: false, reason: 'platform-has-native-commands' };
90
+ }
91
+
92
+ const configPath = path.join(projectRoot, config.configFile);
93
+ const embeddedContent = await generateEmbeddedCommands();
94
+
95
+ try {
96
+ // Check if config file exists
97
+ let existingContent = '';
98
+ try {
99
+ existingContent = await fs.readFile(configPath, 'utf-8');
100
+ } catch (e) {
101
+ // File doesn't exist, will create new
102
+ }
103
+
104
+ // Check if commands already embedded
105
+ if (existingContent.includes('## Telos Commands')) {
106
+ // Replace existing Telos Commands section
107
+ const beforeTelos = existingContent.split('## Telos Commands')[0];
108
+ const afterTelos = existingContent.split('## Telos Commands')[1];
109
+
110
+ // Find end of Telos section (next ## heading or end of file)
111
+ const nextHeadingMatch = afterTelos?.match(/\n## [^T]/);
112
+ const afterTelosSection = nextHeadingMatch
113
+ ? afterTelos.substring(nextHeadingMatch.index)
114
+ : '';
115
+
116
+ const newContent = beforeTelos + embeddedContent + afterTelosSection;
117
+ await fs.writeFile(configPath, newContent);
118
+ return { success: true, updated: true, path: configPath };
119
+ } else {
120
+ // Append to existing content
121
+ const newContent = existingContent + '\n\n' + embeddedContent;
122
+ await fs.writeFile(configPath, newContent);
123
+ return { success: true, created: !existingContent, updated: !!existingContent, path: configPath };
124
+ }
125
+ } catch (error) {
126
+ return { success: false, error: error.message };
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Install slash commands for selected platforms
132
+ * - Platforms with native commands: Creates command files
133
+ * - Platforms without native commands: Embeds in config files
134
+ */
71
135
  async function installSlashCommands(projectRoot, selectedPlatforms = ['claude']) {
72
136
  const platforms = Array.isArray(selectedPlatforms) ? selectedPlatforms : [selectedPlatforms];
73
-
74
- const commandPlatforms = platforms.filter(p => p === 'claude' || p === 'opencode');
75
-
76
137
  const allResults = [];
77
- for (const platform of commandPlatforms) {
78
- const results = await copyCommandFiles(projectRoot, platform);
79
- allResults.push({ platform, results });
138
+
139
+ for (const platform of platforms) {
140
+ if (hasNativeCommands(platform)) {
141
+ // Install native command files
142
+ const results = await installNativeCommands(projectRoot, platform);
143
+ allResults.push({ platform, type: 'native', results });
144
+ } else if (getPlatformConfig(platform)) {
145
+ // Embed in config file
146
+ const result = await embedCommandsInConfig(projectRoot, platform);
147
+ allResults.push({ platform, type: 'embedded', results: [result] });
148
+ }
149
+ // Skip unknown platforms silently
80
150
  }
81
-
151
+
82
152
  return allResults;
83
153
  }
84
154
 
155
+ /**
156
+ * Copy command files (legacy API - kept for backwards compatibility)
157
+ */
158
+ async function copyCommandFiles(projectRoot, platform) {
159
+ return installNativeCommands(projectRoot, platform);
160
+ }
161
+
85
162
  module.exports = {
86
163
  ensureDirectories,
87
164
  copyCommandFiles,
88
- installSlashCommands
165
+ installSlashCommands,
166
+ installNativeCommands,
167
+ embedCommandsInConfig,
168
+ generateEmbeddedCommands,
169
+ readCommandTemplate
89
170
  };
@@ -244,43 +244,26 @@ function generateSpec(level, data = {}) {
244
244
  * @returns {string} TELOS.md content
245
245
  */
246
246
  function generateTelosEntry(data = {}) {
247
+ // Generate experiences list if provided
248
+ const experiencesList = data.experiences?.length > 0
249
+ ? data.experiences.map(e => `- [${e.title}](specs/L3-experience/${e.file})`).join('\n')
250
+ : '_No experiences defined yet. Run `/telos:init` to add user journeys._';
251
+
247
252
  return `# TELOS: ${data.projectName || 'Project Name'}
248
253
 
249
254
  > Purpose-driven development with spec-code traceability
250
255
 
251
- ## Quick Start
252
-
253
- \`\`\`bash
254
- telos validate # Validate all specs and links
255
- telos context <id> # Load recursive context for AI
256
- telos coverage # Show spec-test coverage
257
- telos orphans # Find unlinked code
258
- \`\`\`
259
-
260
256
  ## Purpose
261
257
 
262
258
  ${data.purpose || '[Your project purpose - see L4:purpose spec]'}
263
259
 
264
260
  See: [Full Purpose Spec](specs/L4-purpose/purpose.md)
265
261
 
266
- ## Spec Hierarchy
262
+ ## User Experiences (L3)
267
263
 
268
- \`\`\`
269
- L4:purpose ─────────────────────────────────────────────────────┐
270
- │ ${data.purposeTitle || 'Project Purpose'} │
271
- │ │
272
- ├── L3:experience ──────────────────────────────────────────────┤
273
- │ User journeys, UX requirements, analytics │
274
- │ │
275
- ├── L2:contract ────────────────────────────────────────────────┤
276
- │ API contracts, component interfaces │
277
- │ │
278
- └── L1:function ────────────────────────────────────────────────┤
279
- Individual functions with TDD scenarios │
280
- └────────────────────────────────────────────────────────────────┘
281
- \`\`\`
264
+ ${experiencesList}
282
265
 
283
- ## Spec Levels
266
+ ## Spec Hierarchy
284
267
 
285
268
  | Level | Name | Description | Count |
286
269
  |-------|------|-------------|-------|
@@ -289,43 +272,96 @@ L4:purpose ───────────────────────
289
272
  | L2 | Contract | APIs + component interfaces | ${data.l2Count || 0} |
290
273
  | L1 | Function | Functions with TDD | ${data.l1Count || 0} |
291
274
 
292
- ## Code Style
275
+ ---
276
+
277
+ ## 🚨 IMPORTANT: Feature Request Workflow
278
+
279
+ **When the user requests a new feature, you MUST follow this workflow:**
280
+
281
+ ### Step 1: Check Impact on Experiences (L3)
282
+
283
+ Ask: "Does this feature affect any existing user journeys, or create a new one?"
284
+
285
+ - If **new journey**: Create a new L3 spec in \`telos/specs/L3-experience/\`
286
+ - If **modifies journey**: Update the relevant L3 spec first
287
+ - If **no journey impact**: Proceed to Step 2
288
+
289
+ ### Step 2: Define or Update Contracts (L2)
290
+
291
+ Before writing ANY code, create/update L2 contract specs:
292
+
293
+ - **New API endpoint?** → Create \`telos/specs/L2-contract/api-[name].md\`
294
+ - **New component?** → Create \`telos/specs/L2-contract/component-[name].md\`
295
+ - **Modifying existing?** → Update the relevant L2 spec
296
+
297
+ L2 specs must include:
298
+ - Interface/API signature
299
+ - Input/output contracts
300
+ - Error handling
301
+ - Parent L3 experience reference
302
+
303
+ ### Step 3: Define Functions (L1)
293
304
 
294
- Style enforcement handled by existing tooling:
295
- ${data.linters?.map(l => `- **${l.name}**: \`${l.config}\``).join('\n') || `- **ESLint**: \`.eslintrc.js\`
296
- - **Prettier**: \`.prettierrc\`
297
- - **TypeScript**: \`tsconfig.json\``}
305
+ For each function needed to implement the L2 contracts:
298
306
 
299
- ## Annotation Format
307
+ 1. Create L1 spec in \`telos/specs/L1-function/\`
308
+ 2. Include TDD scenarios (given/when/then)
309
+ 3. Reference parent L2 contract
310
+
311
+ ### Step 4: Generate Tests
312
+
313
+ \`\`\`bash
314
+ telos spec generate-tests L1:function:[spec-id]
315
+ \`\`\`
316
+
317
+ Or manually create tests with \`@telos-test\` annotations.
318
+
319
+ ### Step 5: Implement with Annotations
300
320
 
301
321
  \`\`\`${data.primaryLanguage || 'typescript'}
302
322
  // @telos L1:function:src/module:functionName
303
323
  export function functionName() {
304
324
  // implementation
305
325
  }
326
+ \`\`\`
327
+
328
+ ### Step 6: Validate Before Commit
306
329
 
330
+ \`\`\`bash
331
+ telos validate
332
+ \`\`\`
333
+
334
+ ---
335
+
336
+ ## Quick Reference
337
+
338
+ **Commands:**
339
+ - \`/telos:validate\` - Validate specs, code links, and tests
340
+ - \`/telos:status\` - Show current spec counts and health
341
+ - \`/telos:sdd-discover\` - Generate specs from existing code
342
+ - \`/telos:sdd-context <spec-id>\` - Load context for a spec
343
+ - \`/telos:sdd-generate-tests <spec-id>\` - Generate tests from scenarios
344
+
345
+ **Annotation Format:**
346
+ \`\`\`${data.primaryLanguage || 'typescript'}
347
+ // @telos L1:function:src/module:functionName
307
348
  // @telos-test L1:function:src/module:functionName
308
- describe('functionName', () => {
309
- // @telos-scenario L1:function:src/module:functionName:success-case
310
- it('should handle success case', () => {
311
- // test
312
- });
313
- });
349
+ // @telos-scenario L1:function:src/module:functionName:scenario-name
314
350
  \`\`\`
315
351
 
316
- ## Workflow
352
+ **Spec ID Format:** \`L[level]:[type]:[path]:[name]\`
317
353
 
318
- 1. **Create Spec** → Define requirements and scenarios
319
- 2. **Generate Tests** → \`telos spec generate-tests <spec-id>\`
320
- 3. **Run Tests** → Tests fail (Red)
321
- 4. **Implement Code** → Add @telos annotation
322
- 5. **Run Tests** → Tests pass (Green)
323
- 6. **Validate** → \`telos validate\`
324
- 7. **Commit** → Pre-commit hook verifies
354
+ Examples:
355
+ - \`L4:purpose\`
356
+ - \`L3:experience:user-signup-flow\`
357
+ - \`L2:contract:api-auth\`
358
+ - \`L1:function:src/auth/validation:validateToken\`
359
+
360
+ ---
325
361
 
326
362
  ## Links
327
363
 
328
- - [Full Documentation](https://github.com/telos-framework/init)
364
+ - [Telos Documentation](https://github.com/telos-framework/init)
329
365
  - [Spec-Driven Development Guide](https://telos-framework.dev/sdd)
330
366
  `;
331
367
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "telos-framework",
3
- "version": "0.9.2",
3
+ "version": "0.10.1",
4
4
  "description": "Telos-driven Multi-Agent Development Framework - A philosophically-grounded AI collective for purpose-aligned software development",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -6,6 +6,15 @@ This project uses the **Telos Framework** with **Spec-Driven Development
6
6
  **CRITICAL**: All code must trace back to specifications. Every function needs a
7
7
  `@telos` annotation linking it to a spec.
8
8
 
9
+ ## ⚠️ IMPORTANT: Read telos/TELOS.md First
10
+
11
+ Before making any changes, **always read `telos/TELOS.md`** for:
12
+
13
+ - Project purpose and success metrics
14
+ - User experiences (L3 journeys)
15
+ - Feature request workflow (MUST follow for new features)
16
+ - Current spec counts and health
17
+
9
18
  ## Spec-Driven Development (SDD)
10
19
 
11
20
  This project enforces a 4-level spec hierarchy: