x-ipe 1.0.24__py3-none-any.whl → 1.0.25__py3-none-any.whl
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.
- x_ipe/app.py +25 -3
- x_ipe/handlers/terminal_handlers.py +6 -0
- x_ipe/handlers/voice_handlers.py +5 -0
- x_ipe/resources/copilot-instructions.md +19 -6
- x_ipe/resources/skills/lesson-learned/SKILL.md +208 -0
- x_ipe/resources/skills/lesson-learned/references/examples.md +238 -0
- x_ipe/resources/skills/project-quality-board-management/SKILL.md +135 -298
- x_ipe/resources/skills/project-quality-board-management/references/evaluation-principles.md +213 -0
- x_ipe/resources/skills/project-quality-board-management/references/evaluation-procedures.md +214 -0
- x_ipe/resources/skills/project-quality-board-management/templates/quality-report.md +70 -18
- x_ipe/resources/skills/task-execution-guideline/SKILL.md +2 -2
- x_ipe/resources/skills/task-execution-guideline/templates/task-record.yaml +1 -1
- x_ipe/resources/skills/task-type-code-implementation/SKILL.md +72 -270
- x_ipe/resources/skills/task-type-code-implementation/references/implementation-guidelines.md +432 -0
- x_ipe/resources/skills/task-type-code-refactor-v2/SKILL.md +127 -353
- x_ipe/resources/skills/task-type-code-refactor-v2/references/refactoring-techniques.md +373 -0
- x_ipe/resources/skills/task-type-feature-breakdown/SKILL.md +31 -243
- x_ipe/resources/skills/task-type-feature-breakdown/references/breakdown-guidelines.md +330 -0
- x_ipe/resources/skills/task-type-feature-refinement/SKILL.md +27 -180
- x_ipe/resources/skills/task-type-feature-refinement/references/specification-writing-guide.md +267 -0
- x_ipe/resources/skills/task-type-idea-mockup/SKILL.md +38 -276
- x_ipe/resources/skills/task-type-idea-mockup/references/mockup-guidelines.md +299 -0
- x_ipe/resources/skills/task-type-idea-to-architecture/SKILL.md +20 -218
- x_ipe/resources/skills/task-type-idea-to-architecture/references/architecture-patterns.md +342 -0
- x_ipe/resources/skills/task-type-ideation/SKILL.md +10 -266
- x_ipe/resources/skills/task-type-ideation/references/folder-naming-guide.md +55 -0
- x_ipe/resources/skills/task-type-ideation/references/tool-usage-guide.md +236 -0
- x_ipe/resources/skills/task-type-ideation-v2/SKILL.md +488 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/examples.md +377 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/folder-naming-guide.md +74 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/tool-usage-guide.md +145 -0
- x_ipe/resources/skills/task-type-ideation-v2/references/visualization-guide.md +160 -0
- x_ipe/resources/skills/task-type-ideation-v2/templates/idea-summary.md +86 -0
- x_ipe/resources/skills/task-type-refactoring-analysis/SKILL.md +83 -145
- x_ipe/resources/skills/task-type-refactoring-analysis/references/output-schema.md +172 -0
- x_ipe/resources/skills/task-type-technical-design/SKILL.md +28 -214
- x_ipe/resources/skills/task-type-technical-design/references/design-templates.md +422 -0
- x_ipe/resources/skills/task-type-test-generation/SKILL.md +47 -332
- x_ipe/resources/skills/task-type-test-generation/references/test-patterns.md +368 -0
- x_ipe/resources/skills/tool-tracing-creator/SKILL.md +312 -0
- x_ipe/resources/skills/tool-tracing-creator/references/examples.md +324 -0
- x_ipe/resources/skills/tool-tracing-instrumentation/SKILL.md +373 -0
- x_ipe/resources/skills/tool-tracing-instrumentation/references/examples.md +264 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/SKILL.md +486 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/10. example-gate-conditions.md +73 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/11. reference-quality-standards.md +127 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/2. reference-section-order.md +127 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/3. example-step-based-code-review.md +84 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/4. example-step-based-feature-implementation.md +113 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/5. example-function-based-validation.md +73 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/6. example-function-based-analysis.md +94 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/7. example-task-io-code-implementation.md +36 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/8. example-structured-summary.md +43 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/9. example-dor-dod.md +77 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/examples.md +429 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/references/skill-general-guidelines-v2.md +611 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-meta.md +153 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-based.md +324 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-task-category.md +109 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/skill-meta-x-ipe-tool.md +205 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-meta.md +334 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-task-based.md +279 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-tool.md +175 -0
- x_ipe/resources/skills/x-ipe-skill-creator-v3/templates/x-ipe-workflow-orchestration.md +329 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/SKILL.md +487 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/examples.md +377 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/folder-naming-guide.md +74 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/tool-usage-guide.md +145 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/references/visualization-guide.md +160 -0
- x_ipe/resources/skills/x-ipe-task-based-ideation/templates/idea-summary.md +86 -0
- x_ipe/routes/__init__.py +2 -0
- x_ipe/routes/ideas_routes.py +17 -0
- x_ipe/routes/kb_routes.py +80 -0
- x_ipe/routes/main_routes.py +18 -0
- x_ipe/routes/project_routes.py +7 -0
- x_ipe/routes/proxy_routes.py +2 -0
- x_ipe/routes/quality_evaluation_routes.py +193 -0
- x_ipe/routes/settings_routes.py +6 -0
- x_ipe/routes/tools_routes.py +6 -0
- x_ipe/routes/tracing_routes.py +232 -0
- x_ipe/routes/uiux_feedback_routes.py +30 -0
- x_ipe/services/__init__.py +5 -0
- x_ipe/services/config_service.py +6 -0
- x_ipe/services/file_service.py +20 -0
- x_ipe/services/homepage_service.py +160 -0
- x_ipe/services/ideas_service.py +19 -0
- x_ipe/services/kb_service.py +378 -0
- x_ipe/services/proxy_service.py +4 -0
- x_ipe/services/settings_service.py +13 -0
- x_ipe/services/skills_service.py +4 -0
- x_ipe/services/terminal_service.py +24 -0
- x_ipe/services/themes_service.py +4 -0
- x_ipe/services/tools_config_service.py +4 -0
- x_ipe/services/tracing_service.py +333 -0
- x_ipe/services/uiux_feedback_service.py +32 -0
- x_ipe/services/voice_input_service_v2.py +11 -0
- x_ipe/static/css/base.css +7 -0
- x_ipe/static/css/homepage-infinity.css +330 -0
- x_ipe/static/css/kb-core.css +301 -0
- x_ipe/static/css/quality-evaluation.css +345 -0
- x_ipe/static/css/sidebar.css +14 -4
- x_ipe/static/css/terminal.css +1 -0
- x_ipe/static/css/tracing-dashboard.css +796 -0
- x_ipe/static/css/workplace.css +20 -0
- x_ipe/static/img/homepage-infinity-loop.png +0 -0
- x_ipe/static/js/features/homepage-infinity.js +314 -0
- x_ipe/static/js/features/kb-core.js +371 -0
- x_ipe/static/js/features/quality-evaluation.js +387 -0
- x_ipe/static/js/features/sidebar.js +255 -12
- x_ipe/static/js/features/tracing-dashboard.js +855 -0
- x_ipe/static/js/features/tracing-graph.js +1031 -0
- x_ipe/static/js/features/tree-search.js +6 -2
- x_ipe/static/js/features/workplace.js +200 -6
- x_ipe/static/js/init.js +76 -0
- x_ipe/static/js/uiux-feedback.js +18 -2
- x_ipe/templates/base.html +19 -0
- x_ipe/templates/index.html +7 -1
- x_ipe/templates/knowledge-base.html +110 -0
- x_ipe/templates/workplace.html +4 -0
- x_ipe/tracing/__init__.py +37 -0
- x_ipe/tracing/buffer.py +135 -0
- x_ipe/tracing/context.py +125 -0
- x_ipe/tracing/decorator.py +288 -0
- x_ipe/tracing/middleware.py +197 -0
- x_ipe/tracing/parser.py +235 -0
- x_ipe/tracing/redactor.py +111 -0
- x_ipe/tracing/writer.py +122 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/METADATA +2 -2
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/RECORD +132 -62
- x_ipe/resources/skills/x-ipe-skill-creator/SKILL.md +0 -329
- x_ipe/resources/skills/x-ipe-skill-creator/references/output-patterns.md +0 -169
- x_ipe/resources/skills/x-ipe-skill-creator/references/skill-structure.md +0 -162
- x_ipe/resources/skills/x-ipe-skill-creator/references/workflows.md +0 -110
- x_ipe/resources/skills/x-ipe-skill-creator/templates/references/examples.md +0 -113
- x_ipe/resources/skills/x-ipe-skill-creator/templates/skill-category-skill.md +0 -296
- x_ipe/resources/skills/x-ipe-skill-creator/templates/task-type-skill.md +0 -269
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/WHEEL +0 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/entry_points.txt +0 -0
- {x_ipe-1.0.24.dist-info → x_ipe-1.0.25.dist-info}/licenses/LICENSE +0 -0
x_ipe/services/file_service.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
FEATURE-001: Project Navigation
|
|
3
|
+
FEATURE-002: Content Viewer
|
|
4
|
+
FEATURE-003: Content Editor
|
|
3
5
|
|
|
4
6
|
FileNode: Represents a file or folder in the project structure
|
|
5
7
|
Section: Represents a top-level section in the sidebar
|
|
@@ -16,6 +18,8 @@ from dataclasses import dataclass
|
|
|
16
18
|
from watchdog.observers import Observer
|
|
17
19
|
from watchdog.events import FileSystemEventHandler, FileSystemEvent
|
|
18
20
|
|
|
21
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
22
|
+
|
|
19
23
|
|
|
20
24
|
@dataclass
|
|
21
25
|
class FileNode:
|
|
@@ -96,6 +100,12 @@ class ProjectService:
|
|
|
96
100
|
'path': 'x-ipe-docs/requirements',
|
|
97
101
|
'icon': 'bi-file-text'
|
|
98
102
|
},
|
|
103
|
+
{
|
|
104
|
+
'id': 'skill-meta',
|
|
105
|
+
'label': 'Skill Meta',
|
|
106
|
+
'path': 'x-ipe-docs/skill-meta',
|
|
107
|
+
'icon': 'bi-stars'
|
|
108
|
+
},
|
|
99
109
|
{
|
|
100
110
|
'id': 'code',
|
|
101
111
|
'label': 'Code',
|
|
@@ -121,6 +131,7 @@ class ProjectService:
|
|
|
121
131
|
self.project_root = Path(project_root).resolve()
|
|
122
132
|
self.sections_config = sections or self.DEFAULT_SECTIONS
|
|
123
133
|
|
|
134
|
+
@x_ipe_tracing(level="INFO")
|
|
124
135
|
def get_structure(self) -> Dict[str, Any]:
|
|
125
136
|
"""
|
|
126
137
|
Get the complete project structure for sidebar navigation.
|
|
@@ -155,6 +166,7 @@ class ProjectService:
|
|
|
155
166
|
'sections': sections
|
|
156
167
|
}
|
|
157
168
|
|
|
169
|
+
@x_ipe_tracing(level="DEBUG")
|
|
158
170
|
def _scan_directory(self, directory: Path, relative_base: str) -> List[FileNode]:
|
|
159
171
|
"""
|
|
160
172
|
Recursively scan a directory and build file tree.
|
|
@@ -323,6 +335,7 @@ class FileWatcher:
|
|
|
323
335
|
self._running = False
|
|
324
336
|
self.ignore_patterns = self._load_gitignore()
|
|
325
337
|
|
|
338
|
+
@x_ipe_tracing(level="DEBUG")
|
|
326
339
|
def _load_gitignore(self) -> List[str]:
|
|
327
340
|
"""Load and parse .gitignore patterns."""
|
|
328
341
|
gitignore_path = self.project_root / '.gitignore'
|
|
@@ -341,6 +354,7 @@ class FileWatcher:
|
|
|
341
354
|
|
|
342
355
|
return patterns
|
|
343
356
|
|
|
357
|
+
@x_ipe_tracing(level="DEBUG")
|
|
344
358
|
def _emit_event(self, event_data: Dict):
|
|
345
359
|
"""Emit file system event via WebSocket"""
|
|
346
360
|
if self.socketio:
|
|
@@ -363,6 +377,7 @@ class FileWatcher:
|
|
|
363
377
|
}
|
|
364
378
|
self.socketio.emit('content_changed', content_event)
|
|
365
379
|
|
|
380
|
+
@x_ipe_tracing(level="INFO")
|
|
366
381
|
def start(self):
|
|
367
382
|
"""Start watching project directories"""
|
|
368
383
|
if self._running:
|
|
@@ -381,6 +396,7 @@ class FileWatcher:
|
|
|
381
396
|
self.observer.start()
|
|
382
397
|
self._running = True
|
|
383
398
|
|
|
399
|
+
@x_ipe_tracing(level="INFO")
|
|
384
400
|
def stop(self):
|
|
385
401
|
"""Stop watching"""
|
|
386
402
|
if self.observer and self._running:
|
|
@@ -433,6 +449,7 @@ class ContentService:
|
|
|
433
449
|
"""
|
|
434
450
|
self.project_root = Path(project_root).resolve()
|
|
435
451
|
|
|
452
|
+
@x_ipe_tracing(level="DEBUG")
|
|
436
453
|
def detect_file_type(self, extension: str) -> str:
|
|
437
454
|
"""
|
|
438
455
|
Detect file type from extension.
|
|
@@ -445,6 +462,7 @@ class ContentService:
|
|
|
445
462
|
"""
|
|
446
463
|
return self.FILE_TYPES.get(extension.lower(), 'text')
|
|
447
464
|
|
|
465
|
+
@x_ipe_tracing(level="INFO")
|
|
448
466
|
def get_content(self, relative_path: str) -> Dict[str, Any]:
|
|
449
467
|
"""
|
|
450
468
|
Get file content with metadata.
|
|
@@ -487,6 +505,7 @@ class ContentService:
|
|
|
487
505
|
'size': size
|
|
488
506
|
}
|
|
489
507
|
|
|
508
|
+
@x_ipe_tracing(level="DEBUG")
|
|
490
509
|
def _validate_path_for_write(self, relative_path: str) -> tuple:
|
|
491
510
|
"""
|
|
492
511
|
Validate a path for write operations.
|
|
@@ -543,6 +562,7 @@ class ContentService:
|
|
|
543
562
|
|
|
544
563
|
return (True, full_path)
|
|
545
564
|
|
|
565
|
+
@x_ipe_tracing(level="INFO")
|
|
546
566
|
def save_content(self, relative_path: str, content: str) -> Dict[str, Any]:
|
|
547
567
|
"""
|
|
548
568
|
Save content to a file.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Homepage Service
|
|
3
|
+
FEATURE-026: Homepage Infinity Loop
|
|
4
|
+
|
|
5
|
+
Provides stage mapping configuration and template generation
|
|
6
|
+
for the interactive homepage infinity loop visualization.
|
|
7
|
+
"""
|
|
8
|
+
from x_ipe.services.tracing_service import x_ipe_tracing
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class HomepageService:
|
|
12
|
+
"""Service for homepage infinity loop functionality"""
|
|
13
|
+
|
|
14
|
+
# Stage-to-sidebar mapping configuration
|
|
15
|
+
STAGE_MAPPING = {
|
|
16
|
+
'ideation': {
|
|
17
|
+
'icon': '💡',
|
|
18
|
+
'label': 'IDEATION',
|
|
19
|
+
'theme': 'control',
|
|
20
|
+
'status': 'ready',
|
|
21
|
+
'section': 'workplace',
|
|
22
|
+
'selector': '[data-path="x-ipe-docs/ideas"]',
|
|
23
|
+
'position': {'left': '4.5%', 'top': '60%'}
|
|
24
|
+
},
|
|
25
|
+
'requirement': {
|
|
26
|
+
'icon': '📋',
|
|
27
|
+
'label': 'REQUIREMENT',
|
|
28
|
+
'theme': 'control',
|
|
29
|
+
'status': 'ready',
|
|
30
|
+
'section': 'project',
|
|
31
|
+
'selector': '[data-path="x-ipe-docs/requirements"]',
|
|
32
|
+
'position': {'left': '12%', 'top': '12%'}
|
|
33
|
+
},
|
|
34
|
+
'implementation': {
|
|
35
|
+
'icon': '⚙️',
|
|
36
|
+
'label': 'IMPLEMENT',
|
|
37
|
+
'theme': 'control',
|
|
38
|
+
'status': 'ready',
|
|
39
|
+
'section': 'project',
|
|
40
|
+
'selector': '[data-path="x-ipe-docs/requirements"]',
|
|
41
|
+
'position': {'left': '30%', 'top': '73%'}
|
|
42
|
+
},
|
|
43
|
+
'deployment': {
|
|
44
|
+
'icon': '🚀',
|
|
45
|
+
'label': 'DEPLOY',
|
|
46
|
+
'theme': 'control',
|
|
47
|
+
'status': 'tbd',
|
|
48
|
+
'section': 'management',
|
|
49
|
+
'selector': None,
|
|
50
|
+
'position': {'left': '56%', 'top': '19%'}
|
|
51
|
+
},
|
|
52
|
+
'validation': {
|
|
53
|
+
'icon': '✅',
|
|
54
|
+
'label': 'VALIDATION',
|
|
55
|
+
'theme': 'transparency',
|
|
56
|
+
'status': 'ready',
|
|
57
|
+
'section': 'quality',
|
|
58
|
+
'selector': '[data-section="quality-report"]',
|
|
59
|
+
'position': {'left': '80%', 'top': '13%'}
|
|
60
|
+
},
|
|
61
|
+
'monitoring': {
|
|
62
|
+
'icon': '📊',
|
|
63
|
+
'label': 'MONITORING',
|
|
64
|
+
'theme': 'transparency',
|
|
65
|
+
'status': 'ready',
|
|
66
|
+
'section': 'quality',
|
|
67
|
+
'selector': '[data-section="behavior-tracing"]',
|
|
68
|
+
'position': {'left': '85%', 'top': '65%'}
|
|
69
|
+
},
|
|
70
|
+
'feedback': {
|
|
71
|
+
'icon': '💬',
|
|
72
|
+
'label': 'FEEDBACK',
|
|
73
|
+
'theme': 'transparency',
|
|
74
|
+
'status': 'ready',
|
|
75
|
+
'section': 'feedback',
|
|
76
|
+
'selector': '[data-section="uiux-feedback"]',
|
|
77
|
+
'position': {'left': '58%', 'top': '70%'}
|
|
78
|
+
},
|
|
79
|
+
'planning': {
|
|
80
|
+
'icon': '📅',
|
|
81
|
+
'label': 'PLANNING',
|
|
82
|
+
'theme': 'transparency',
|
|
83
|
+
'status': 'ready',
|
|
84
|
+
'section': 'management',
|
|
85
|
+
'selector': '[data-path="x-ipe-docs/planning"]',
|
|
86
|
+
'position': {'left': '38%', 'top': '25%'}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@x_ipe_tracing(level="INFO")
|
|
91
|
+
def get_stage_mapping(self) -> dict:
|
|
92
|
+
"""
|
|
93
|
+
Get the stage-to-sidebar mapping configuration.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
dict: Stage mapping with icons, labels, themes, selectors, and positions
|
|
97
|
+
"""
|
|
98
|
+
return self.STAGE_MAPPING.copy()
|
|
99
|
+
|
|
100
|
+
@x_ipe_tracing(level="INFO")
|
|
101
|
+
def get_template(self) -> str:
|
|
102
|
+
"""
|
|
103
|
+
Generate HTML template for homepage infinity loop.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
str: HTML template string
|
|
107
|
+
"""
|
|
108
|
+
stage_buttons = self._render_stage_buttons()
|
|
109
|
+
|
|
110
|
+
return f'''
|
|
111
|
+
<div class="homepage-infinity-container">
|
|
112
|
+
<header class="homepage-header">
|
|
113
|
+
<h1>X-IPE</h1>
|
|
114
|
+
<p>AI-Powered Development Lifecycle</p>
|
|
115
|
+
</header>
|
|
116
|
+
|
|
117
|
+
<div class="infinity-loop-container">
|
|
118
|
+
<div class="infinity-loop">
|
|
119
|
+
<img src="/api/file/content?path=x-ipe-docs%2Fideas%2FTBC008.%20Feature-Homepage%2FControl%26Transparency.png&raw=true"
|
|
120
|
+
alt="Development Lifecycle"
|
|
121
|
+
class="infinity-bg"
|
|
122
|
+
onerror="this.style.display='none'">
|
|
123
|
+
|
|
124
|
+
{stage_buttons}
|
|
125
|
+
|
|
126
|
+
<span class="loop-label control">CONTROL</span>
|
|
127
|
+
<span class="loop-label transparency">TRANSPARENCY</span>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<footer class="homepage-legend">
|
|
132
|
+
<span>Control (What we decide)</span>
|
|
133
|
+
<span>Transparency (What we see)</span>
|
|
134
|
+
</footer>
|
|
135
|
+
</div>
|
|
136
|
+
'''
|
|
137
|
+
|
|
138
|
+
def _render_stage_buttons(self) -> str:
|
|
139
|
+
"""Render HTML for all stage buttons"""
|
|
140
|
+
buttons = []
|
|
141
|
+
for stage_id, config in self.STAGE_MAPPING.items():
|
|
142
|
+
tbd_class = ' tbd' if config['status'] == 'tbd' else ''
|
|
143
|
+
tbd_attr = ' data-tbd="true"' if config['status'] == 'tbd' else ''
|
|
144
|
+
tbd_badge = '<span class="tbd-badge">TBD</span>' if config['status'] == 'tbd' else ''
|
|
145
|
+
|
|
146
|
+
button = f'''
|
|
147
|
+
<button class="stage-btn {config['theme']}{tbd_class}"
|
|
148
|
+
data-stage="{stage_id}"
|
|
149
|
+
data-section="{config['section']}"
|
|
150
|
+
data-selector="{config['selector'] or ''}"
|
|
151
|
+
style="left: {config['position']['left']}; top: {config['position']['top']};"
|
|
152
|
+
{tbd_attr}>
|
|
153
|
+
<span class="stage-icon">{config['icon']}</span>
|
|
154
|
+
<span class="stage-label">{config['label']}</span>
|
|
155
|
+
{tbd_badge}
|
|
156
|
+
</button>
|
|
157
|
+
'''
|
|
158
|
+
buttons.append(button)
|
|
159
|
+
|
|
160
|
+
return '\n'.join(buttons)
|
x_ipe/services/ideas_service.py
CHANGED
|
@@ -11,6 +11,8 @@ from datetime import datetime
|
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Dict, List, Any
|
|
13
13
|
|
|
14
|
+
from x_ipe.tracing import x_ipe_tracing
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
class IdeasService:
|
|
16
18
|
"""
|
|
@@ -48,6 +50,7 @@ class IdeasService:
|
|
|
48
50
|
self.project_root = Path(project_root).resolve()
|
|
49
51
|
self.ideas_root = self.project_root / self.IDEAS_PATH
|
|
50
52
|
|
|
53
|
+
@x_ipe_tracing()
|
|
51
54
|
def get_tree(self) -> List[Dict]:
|
|
52
55
|
"""
|
|
53
56
|
Scan x-ipe-docs/ideas/ and return tree structure.
|
|
@@ -93,6 +96,7 @@ class IdeasService:
|
|
|
93
96
|
|
|
94
97
|
return items
|
|
95
98
|
|
|
99
|
+
@x_ipe_tracing()
|
|
96
100
|
def upload(self, files: List[tuple], date: str = None, target_folder: str = None) -> Dict[str, Any]:
|
|
97
101
|
"""
|
|
98
102
|
Upload files to a new or existing idea folder.
|
|
@@ -155,6 +159,7 @@ class IdeasService:
|
|
|
155
159
|
'files_uploaded': uploaded_files
|
|
156
160
|
}
|
|
157
161
|
|
|
162
|
+
@x_ipe_tracing()
|
|
158
163
|
def create_folder(self, folder_name: str, parent_folder: str = None) -> Dict[str, Any]:
|
|
159
164
|
"""
|
|
160
165
|
Create an empty folder in ideas directory.
|
|
@@ -220,6 +225,7 @@ class IdeasService:
|
|
|
220
225
|
'folder_path': relative_path
|
|
221
226
|
}
|
|
222
227
|
|
|
228
|
+
@x_ipe_tracing()
|
|
223
229
|
def rename_folder(self, old_name: str, new_name: str) -> Dict[str, Any]:
|
|
224
230
|
"""
|
|
225
231
|
Rename an idea folder.
|
|
@@ -272,6 +278,7 @@ class IdeasService:
|
|
|
272
278
|
'new_path': f'{self.IDEAS_PATH}/{final_name}'
|
|
273
279
|
}
|
|
274
280
|
|
|
281
|
+
@x_ipe_tracing()
|
|
275
282
|
def rename_file(self, file_path: str, new_name: str) -> Dict[str, Any]:
|
|
276
283
|
"""
|
|
277
284
|
Rename a file within x-ipe-docs/ideas/.
|
|
@@ -398,6 +405,7 @@ class IdeasService:
|
|
|
398
405
|
|
|
399
406
|
return name
|
|
400
407
|
|
|
408
|
+
@x_ipe_tracing()
|
|
401
409
|
def delete_item(self, path: str) -> Dict[str, Any]:
|
|
402
410
|
"""
|
|
403
411
|
Delete a file or folder within x-ipe-docs/ideas/.
|
|
@@ -458,6 +466,7 @@ class IdeasService:
|
|
|
458
466
|
'error': f'Failed to delete: {str(e)}'
|
|
459
467
|
}
|
|
460
468
|
|
|
469
|
+
@x_ipe_tracing()
|
|
461
470
|
def get_next_version_number(self, folder_path: str, base_name: str = 'idea-summary') -> int:
|
|
462
471
|
"""
|
|
463
472
|
Get the next version number for a versioned file.
|
|
@@ -486,6 +495,7 @@ class IdeasService:
|
|
|
486
495
|
|
|
487
496
|
return max_version + 1
|
|
488
497
|
|
|
498
|
+
@x_ipe_tracing()
|
|
489
499
|
def create_versioned_summary(self, folder_path: str, content: str, base_name: str = 'idea-summary') -> Dict[str, Any]:
|
|
490
500
|
"""
|
|
491
501
|
Create a new versioned idea summary file.
|
|
@@ -544,6 +554,7 @@ class IdeasService:
|
|
|
544
554
|
'error': f'Failed to create file: {str(e)}'
|
|
545
555
|
}
|
|
546
556
|
|
|
557
|
+
@x_ipe_tracing()
|
|
547
558
|
def get_toolbox(self) -> Dict:
|
|
548
559
|
"""
|
|
549
560
|
Read toolbox configuration from JSON file.
|
|
@@ -561,6 +572,7 @@ class IdeasService:
|
|
|
561
572
|
return copy.deepcopy(self.DEFAULT_TOOLBOX)
|
|
562
573
|
return copy.deepcopy(self.DEFAULT_TOOLBOX)
|
|
563
574
|
|
|
575
|
+
@x_ipe_tracing()
|
|
564
576
|
def save_toolbox(self, config: Dict) -> Dict:
|
|
565
577
|
"""
|
|
566
578
|
Save toolbox configuration to JSON file.
|
|
@@ -587,6 +599,7 @@ class IdeasService:
|
|
|
587
599
|
# CR-006: Folder Tree UX Enhancement
|
|
588
600
|
# =========================================================================
|
|
589
601
|
|
|
602
|
+
@x_ipe_tracing()
|
|
590
603
|
def move_item(self, source_path: str, target_folder: str) -> Dict[str, Any]:
|
|
591
604
|
"""
|
|
592
605
|
Move file or folder to target folder.
|
|
@@ -657,6 +670,7 @@ class IdeasService:
|
|
|
657
670
|
except OSError as e:
|
|
658
671
|
return {'success': False, 'error': f'Failed to move: {str(e)}'}
|
|
659
672
|
|
|
673
|
+
@x_ipe_tracing()
|
|
660
674
|
def duplicate_item(self, path: str) -> Dict[str, Any]:
|
|
661
675
|
"""
|
|
662
676
|
Duplicate file or folder with -copy suffix.
|
|
@@ -729,6 +743,7 @@ class IdeasService:
|
|
|
729
743
|
new_path = str(copy_path.relative_to(self.ideas_root))
|
|
730
744
|
return {'success': True, 'new_path': new_path}
|
|
731
745
|
|
|
746
|
+
@x_ipe_tracing()
|
|
732
747
|
def get_folder_contents(self, folder_path: str) -> Dict[str, Any]:
|
|
733
748
|
"""
|
|
734
749
|
Get contents of a specific folder for folder view panel.
|
|
@@ -793,6 +808,7 @@ class IdeasService:
|
|
|
793
808
|
folder_path_result = str(full_path.relative_to(self.project_root)) if full_path != self.ideas_root else self.IDEAS_PATH
|
|
794
809
|
return {'success': True, 'items': items, 'folder_path': folder_path_result}
|
|
795
810
|
|
|
811
|
+
@x_ipe_tracing()
|
|
796
812
|
def is_valid_drop_target(self, source_path: str, target_folder: str) -> bool:
|
|
797
813
|
"""
|
|
798
814
|
Validate that target is not source or child of source.
|
|
@@ -837,6 +853,7 @@ class IdeasService:
|
|
|
837
853
|
|
|
838
854
|
return True
|
|
839
855
|
|
|
856
|
+
@x_ipe_tracing()
|
|
840
857
|
def filter_tree(self, query: str) -> List[Dict]:
|
|
841
858
|
"""
|
|
842
859
|
Filter tree by search query, returning matching items with parent context.
|
|
@@ -890,6 +907,7 @@ class IdeasService:
|
|
|
890
907
|
|
|
891
908
|
return any_match
|
|
892
909
|
|
|
910
|
+
@x_ipe_tracing()
|
|
893
911
|
def get_download_info(self, path: str) -> Dict[str, Any]:
|
|
894
912
|
"""
|
|
895
913
|
Get file content and mime type for download.
|
|
@@ -962,6 +980,7 @@ class IdeasService:
|
|
|
962
980
|
except OSError as e:
|
|
963
981
|
return {'success': False, 'error': f'Failed to read file: {str(e)}'}
|
|
964
982
|
|
|
983
|
+
@x_ipe_tracing()
|
|
965
984
|
def get_delete_info(self, path: str) -> Dict[str, Any]:
|
|
966
985
|
"""
|
|
967
986
|
Get item info for delete confirmation dialog.
|