timsquad 2.0.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/LICENSE +21 -0
- package/README.md +347 -0
- package/bin/tsq.js +6 -0
- package/dist/commands/feedback.d.ts +3 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +142 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/full.d.ts +3 -0
- package/dist/commands/full.d.ts.map +1 -0
- package/dist/commands/full.js +87 -0
- package/dist/commands/full.js.map +1 -0
- package/dist/commands/git/commit.d.ts +3 -0
- package/dist/commands/git/commit.d.ts.map +1 -0
- package/dist/commands/git/commit.js +88 -0
- package/dist/commands/git/commit.js.map +1 -0
- package/dist/commands/git/index.d.ts +5 -0
- package/dist/commands/git/index.d.ts.map +1 -0
- package/dist/commands/git/index.js +5 -0
- package/dist/commands/git/index.js.map +1 -0
- package/dist/commands/git/pr.d.ts +3 -0
- package/dist/commands/git/pr.d.ts.map +1 -0
- package/dist/commands/git/pr.js +138 -0
- package/dist/commands/git/pr.js.map +1 -0
- package/dist/commands/git/release.d.ts +3 -0
- package/dist/commands/git/release.d.ts.map +1 -0
- package/dist/commands/git/release.js +158 -0
- package/dist/commands/git/release.js.map +1 -0
- package/dist/commands/git/sync.d.ts +3 -0
- package/dist/commands/git/sync.d.ts.map +1 -0
- package/dist/commands/git/sync.js +132 -0
- package/dist/commands/git/sync.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +150 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/log.d.ts +3 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +271 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/metrics.d.ts +3 -0
- package/dist/commands/metrics.d.ts.map +1 -0
- package/dist/commands/metrics.js +299 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/quick.d.ts +3 -0
- package/dist/commands/quick.d.ts.map +1 -0
- package/dist/commands/quick.js +136 -0
- package/dist/commands/quick.js.map +1 -0
- package/dist/commands/retro.d.ts +3 -0
- package/dist/commands/retro.d.ts.map +1 -0
- package/dist/commands/retro.js +280 -0
- package/dist/commands/retro.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +127 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +3 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +213 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +108 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/project.d.ts +47 -0
- package/dist/lib/project.d.ts.map +1 -0
- package/dist/lib/project.js +191 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/template.d.ts +33 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js +151 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/types/config.d.ts +75 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +66 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/feedback.d.ts +59 -0
- package/dist/types/feedback.d.ts.map +1 -0
- package/dist/types/feedback.js +26 -0
- package/dist/types/feedback.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/project.d.ts +89 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +44 -0
- package/dist/types/project.js.map +1 -0
- package/dist/utils/colors.d.ts +30 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/colors.js +54 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/date.d.ts +25 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +65 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/fs.d.ts +49 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +84 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/prompts.d.ts +31 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +95 -0
- package/dist/utils/prompts.js.map +1 -0
- package/dist/utils/yaml.d.ts +21 -0
- package/dist/utils/yaml.d.ts.map +1 -0
- package/dist/utils/yaml.js +40 -0
- package/dist/utils/yaml.js.map +1 -0
- package/package.json +71 -0
- package/templates/common/CLAUDE.md.template +254 -0
- package/templates/common/claude/agents/tsq-dba.md +290 -0
- package/templates/common/claude/agents/tsq-designer.md +304 -0
- package/templates/common/claude/agents/tsq-developer.md +118 -0
- package/templates/common/claude/agents/tsq-planner.md +90 -0
- package/templates/common/claude/agents/tsq-prompter.md +336 -0
- package/templates/common/claude/agents/tsq-qa.md +134 -0
- package/templates/common/claude/agents/tsq-retro.md +168 -0
- package/templates/common/claude/agents/tsq-security.md +190 -0
- package/templates/common/claude/skills/architecture/SKILL.md +123 -0
- package/templates/common/claude/skills/backend/node/SKILL.md +1015 -0
- package/templates/common/claude/skills/coding/SKILL.md +171 -0
- package/templates/common/claude/skills/database/prisma/SKILL.md +357 -0
- package/templates/common/claude/skills/frontend/nextjs/SKILL.md +279 -0
- package/templates/common/claude/skills/frontend/react/SKILL.md +1729 -0
- package/templates/common/claude/skills/methodology/bdd/SKILL.md +234 -0
- package/templates/common/claude/skills/methodology/ddd/SKILL.md +311 -0
- package/templates/common/claude/skills/methodology/tdd/SKILL.md +512 -0
- package/templates/common/claude/skills/planning/SKILL.md +90 -0
- package/templates/common/claude/skills/security/SKILL.md +234 -0
- package/templates/common/claude/skills/testing/SKILL.md +146 -0
- package/templates/common/claude/skills/typescript/SKILL.md +435 -0
- package/templates/common/config.template.yaml +131 -0
- package/templates/common/timsquad/architectures/clean/ARCHITECTURE.md +49 -0
- package/templates/common/timsquad/architectures/clean/backend.xml +210 -0
- package/templates/common/timsquad/architectures/clean/frontend.xml +148 -0
- package/templates/common/timsquad/architectures/fsd/ARCHITECTURE.md +67 -0
- package/templates/common/timsquad/architectures/fsd/frontend.xml +288 -0
- package/templates/common/timsquad/architectures/hexagonal/ARCHITECTURE.md +60 -0
- package/templates/common/timsquad/architectures/hexagonal/backend.xml +300 -0
- package/templates/common/timsquad/constraints/competency-framework.xml +501 -0
- package/templates/common/timsquad/constraints/ssot-schema.xml +433 -0
- package/templates/common/timsquad/feedback/feedback-router.sh +341 -0
- package/templates/common/timsquad/feedback/routing-rules.yaml +352 -0
- package/templates/common/timsquad/generators/data-design.xml +290 -0
- package/templates/common/timsquad/generators/prd.xml +280 -0
- package/templates/common/timsquad/generators/requirements.xml +220 -0
- package/templates/common/timsquad/generators/service-spec.xml +266 -0
- package/templates/common/timsquad/logs/_example.md +81 -0
- package/templates/common/timsquad/logs/_template.md +46 -0
- package/templates/common/timsquad/patterns/cqrs.xml +127 -0
- package/templates/common/timsquad/patterns/event-sourcing.xml +85 -0
- package/templates/common/timsquad/patterns/repository.xml +64 -0
- package/templates/common/timsquad/process/state-machine.xml +343 -0
- package/templates/common/timsquad/process/validation-rules.xml +308 -0
- package/templates/common/timsquad/process/workflow-base.xml +202 -0
- package/templates/common/timsquad/retrospective/cycle-report.template.md +205 -0
- package/templates/common/timsquad/retrospective/metrics/metrics-schema.json +203 -0
- package/templates/common/timsquad/retrospective/patterns/failure-patterns.md +199 -0
- package/templates/common/timsquad/retrospective/patterns/success-patterns.md +262 -0
- package/templates/common/timsquad/retrospective/retrospective-config.xml +294 -0
- package/templates/common/timsquad/retrospective/retrospective-state.xml +210 -0
- package/templates/common/timsquad/ssot/adr/ADR-000-template.md +121 -0
- package/templates/common/timsquad/ssot/adr/ADR-001-example.md +115 -0
- package/templates/common/timsquad/ssot/data-design.template.md +132 -0
- package/templates/common/timsquad/ssot/deployment-spec.template.md +384 -0
- package/templates/common/timsquad/ssot/env-config.template.md +346 -0
- package/templates/common/timsquad/ssot/error-codes.template.md +114 -0
- package/templates/common/timsquad/ssot/functional-spec.template.md +185 -0
- package/templates/common/timsquad/ssot/glossary.template.md +148 -0
- package/templates/common/timsquad/ssot/integration-spec.template.md +391 -0
- package/templates/common/timsquad/ssot/planning.template.md +94 -0
- package/templates/common/timsquad/ssot/prd.template.md +102 -0
- package/templates/common/timsquad/ssot/requirements.template.md +117 -0
- package/templates/common/timsquad/ssot/security-spec.template.md +309 -0
- package/templates/common/timsquad/ssot/service-spec.template.md +194 -0
- package/templates/common/timsquad/ssot/test-spec.template.md +264 -0
- package/templates/common/timsquad/ssot/ui-ux-spec.template.md +262 -0
- package/templates/common/timsquad/state/workspace.xml +217 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { colors, printHeader, printError, printSuccess, printKeyValue } from '../utils/colors.js';
|
|
4
|
+
import { findProjectRoot } from '../lib/project.js';
|
|
5
|
+
import { exists, writeFile, listFiles } from '../utils/fs.js';
|
|
6
|
+
import { getTimestamp } from '../utils/date.js';
|
|
7
|
+
export function registerRetroCommand(program) {
|
|
8
|
+
const retroCmd = program
|
|
9
|
+
.command('retro')
|
|
10
|
+
.description('Retrospective learning system');
|
|
11
|
+
// tsq retro start
|
|
12
|
+
retroCmd
|
|
13
|
+
.command('start')
|
|
14
|
+
.description('Start a new retrospective cycle')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
try {
|
|
17
|
+
await startRetro();
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
printError(error.message);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
// tsq retro collect
|
|
25
|
+
retroCmd
|
|
26
|
+
.command('collect')
|
|
27
|
+
.description('Collect logs and metrics')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
try {
|
|
30
|
+
await collectRetro();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
printError(error.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// tsq retro analyze
|
|
38
|
+
retroCmd
|
|
39
|
+
.command('analyze')
|
|
40
|
+
.description('Analyze patterns (requires Claude)')
|
|
41
|
+
.action(async () => {
|
|
42
|
+
try {
|
|
43
|
+
await analyzeRetro();
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
printError(error.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// tsq retro report
|
|
51
|
+
retroCmd
|
|
52
|
+
.command('report')
|
|
53
|
+
.description('Generate retrospective report')
|
|
54
|
+
.action(async () => {
|
|
55
|
+
try {
|
|
56
|
+
await generateReport();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
printError(error.message);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// tsq retro apply
|
|
64
|
+
retroCmd
|
|
65
|
+
.command('apply')
|
|
66
|
+
.description('Apply improvements')
|
|
67
|
+
.action(async () => {
|
|
68
|
+
try {
|
|
69
|
+
await applyImprovements();
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
printError(error.message);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
// tsq retro status
|
|
77
|
+
retroCmd
|
|
78
|
+
.command('status')
|
|
79
|
+
.description('Show retrospective status')
|
|
80
|
+
.action(async () => {
|
|
81
|
+
try {
|
|
82
|
+
await showRetroStatus();
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
printError(error.message);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function getRetroState(projectRoot) {
|
|
91
|
+
const statePath = path.join(projectRoot, '.timsquad', 'retrospective', 'state.json');
|
|
92
|
+
if (!await exists(statePath)) {
|
|
93
|
+
return { currentCycle: 0, status: 'idle' };
|
|
94
|
+
}
|
|
95
|
+
return fs.readJson(statePath);
|
|
96
|
+
}
|
|
97
|
+
async function saveRetroState(projectRoot, state) {
|
|
98
|
+
const statePath = path.join(projectRoot, '.timsquad', 'retrospective', 'state.json');
|
|
99
|
+
await fs.ensureDir(path.dirname(statePath));
|
|
100
|
+
await fs.writeJson(statePath, state, { spaces: 2 });
|
|
101
|
+
}
|
|
102
|
+
async function startRetro() {
|
|
103
|
+
const projectRoot = await findProjectRoot();
|
|
104
|
+
if (!projectRoot) {
|
|
105
|
+
throw new Error('Not a TimSquad project');
|
|
106
|
+
}
|
|
107
|
+
const state = await getRetroState(projectRoot);
|
|
108
|
+
if (state.status !== 'idle') {
|
|
109
|
+
throw new Error(`Retrospective cycle ${state.currentCycle} is already in progress (${state.status})`);
|
|
110
|
+
}
|
|
111
|
+
state.currentCycle += 1;
|
|
112
|
+
state.status = 'collecting';
|
|
113
|
+
state.startedAt = getTimestamp();
|
|
114
|
+
await saveRetroState(projectRoot, state);
|
|
115
|
+
printSuccess(`Started retrospective cycle ${state.currentCycle}`);
|
|
116
|
+
console.log(colors.dim('\nNext: Run "tsq retro collect" to collect metrics'));
|
|
117
|
+
}
|
|
118
|
+
async function collectRetro() {
|
|
119
|
+
const projectRoot = await findProjectRoot();
|
|
120
|
+
if (!projectRoot) {
|
|
121
|
+
throw new Error('Not a TimSquad project');
|
|
122
|
+
}
|
|
123
|
+
const state = await getRetroState(projectRoot);
|
|
124
|
+
if (state.status !== 'collecting') {
|
|
125
|
+
throw new Error('No active retrospective. Run "tsq retro start" first');
|
|
126
|
+
}
|
|
127
|
+
printHeader(`Collecting Metrics - Cycle ${state.currentCycle}`);
|
|
128
|
+
// Collect log stats
|
|
129
|
+
const logsDir = path.join(projectRoot, '.timsquad', 'logs');
|
|
130
|
+
const logFiles = await listFiles('*.md', logsDir);
|
|
131
|
+
const recentLogs = logFiles.filter(f => !f.startsWith('_'));
|
|
132
|
+
// Count by agent
|
|
133
|
+
const agentStats = {};
|
|
134
|
+
for (const file of recentLogs) {
|
|
135
|
+
const match = file.match(/-([a-z]+)\.md$/);
|
|
136
|
+
if (match) {
|
|
137
|
+
const agent = match[1];
|
|
138
|
+
agentStats[agent] = (agentStats[agent] || 0) + 1;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Create metrics JSON
|
|
142
|
+
const metrics = {
|
|
143
|
+
cycle: state.currentCycle,
|
|
144
|
+
collectedAt: getTimestamp(),
|
|
145
|
+
raw_data: {
|
|
146
|
+
log_files: recentLogs.length,
|
|
147
|
+
agents: agentStats,
|
|
148
|
+
},
|
|
149
|
+
summary: {
|
|
150
|
+
total_logs: recentLogs.length,
|
|
151
|
+
agents_active: Object.keys(agentStats).length,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
const metricsPath = path.join(projectRoot, '.timsquad', 'retrospective', 'metrics', `cycle-${state.currentCycle}.json`);
|
|
155
|
+
await fs.ensureDir(path.dirname(metricsPath));
|
|
156
|
+
await fs.writeJson(metricsPath, metrics, { spaces: 2 });
|
|
157
|
+
state.status = 'analyzing';
|
|
158
|
+
state.collectedAt = getTimestamp();
|
|
159
|
+
await saveRetroState(projectRoot, state);
|
|
160
|
+
printSuccess('Metrics collected');
|
|
161
|
+
printKeyValue('Log files', String(recentLogs.length));
|
|
162
|
+
printKeyValue('Active agents', String(Object.keys(agentStats).length));
|
|
163
|
+
console.log(colors.dim('\nNext: Run "tsq retro analyze" to analyze patterns'));
|
|
164
|
+
}
|
|
165
|
+
async function analyzeRetro() {
|
|
166
|
+
const projectRoot = await findProjectRoot();
|
|
167
|
+
if (!projectRoot) {
|
|
168
|
+
throw new Error('Not a TimSquad project');
|
|
169
|
+
}
|
|
170
|
+
const state = await getRetroState(projectRoot);
|
|
171
|
+
if (state.status !== 'analyzing') {
|
|
172
|
+
throw new Error('Collect metrics first. Run "tsq retro collect"');
|
|
173
|
+
}
|
|
174
|
+
console.log(colors.warning('\n⚠ Pattern analysis requires Claude integration'));
|
|
175
|
+
console.log(colors.dim(' This feature will analyze logs and suggest improvements'));
|
|
176
|
+
console.log(colors.dim(' For now, marking as analyzed for manual review\n'));
|
|
177
|
+
state.status = 'reporting';
|
|
178
|
+
state.analyzedAt = getTimestamp();
|
|
179
|
+
await saveRetroState(projectRoot, state);
|
|
180
|
+
printSuccess('Analysis phase completed (manual review mode)');
|
|
181
|
+
console.log(colors.dim('\nNext: Run "tsq retro report" to generate report'));
|
|
182
|
+
}
|
|
183
|
+
async function generateReport() {
|
|
184
|
+
const projectRoot = await findProjectRoot();
|
|
185
|
+
if (!projectRoot) {
|
|
186
|
+
throw new Error('Not a TimSquad project');
|
|
187
|
+
}
|
|
188
|
+
const state = await getRetroState(projectRoot);
|
|
189
|
+
if (state.status !== 'reporting') {
|
|
190
|
+
throw new Error('Analyze patterns first. Run "tsq retro analyze"');
|
|
191
|
+
}
|
|
192
|
+
// Load metrics
|
|
193
|
+
const metricsPath = path.join(projectRoot, '.timsquad', 'retrospective', 'metrics', `cycle-${state.currentCycle}.json`);
|
|
194
|
+
const metrics = await fs.readJson(metricsPath);
|
|
195
|
+
// Generate report
|
|
196
|
+
const report = `# Cycle ${state.currentCycle} Retrospective Report
|
|
197
|
+
|
|
198
|
+
## Period
|
|
199
|
+
- Started: ${state.startedAt}
|
|
200
|
+
- Collected: ${state.collectedAt}
|
|
201
|
+
- Generated: ${getTimestamp()}
|
|
202
|
+
|
|
203
|
+
## Metrics Summary
|
|
204
|
+
|
|
205
|
+
| Metric | Value |
|
|
206
|
+
|--------|-------|
|
|
207
|
+
| Total Logs | ${metrics.summary.total_logs} |
|
|
208
|
+
| Active Agents | ${metrics.summary.agents_active} |
|
|
209
|
+
|
|
210
|
+
## Agent Activity
|
|
211
|
+
|
|
212
|
+
${Object.entries(metrics.raw_data.agents).map(([agent, count]) => `- ${agent}: ${count} logs`).join('\n')}
|
|
213
|
+
|
|
214
|
+
## Patterns Identified
|
|
215
|
+
|
|
216
|
+
### Success Patterns
|
|
217
|
+
_Manual review required_
|
|
218
|
+
|
|
219
|
+
### Failure Patterns
|
|
220
|
+
_Manual review required_
|
|
221
|
+
|
|
222
|
+
## Improvement Suggestions
|
|
223
|
+
_Manual review required_
|
|
224
|
+
|
|
225
|
+
## Next Cycle Goals
|
|
226
|
+
- [ ] Review and update SSOT documents
|
|
227
|
+
- [ ] Address identified patterns
|
|
228
|
+
- [ ] Apply approved improvements
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
Generated by TimSquad v2.0.0
|
|
232
|
+
`;
|
|
233
|
+
const reportPath = path.join(projectRoot, '.timsquad', 'retrospective', 'cycles', `cycle-${state.currentCycle}.md`);
|
|
234
|
+
await fs.ensureDir(path.dirname(reportPath));
|
|
235
|
+
await writeFile(reportPath, report);
|
|
236
|
+
state.status = 'applying';
|
|
237
|
+
await saveRetroState(projectRoot, state);
|
|
238
|
+
printSuccess(`Report generated: cycle-${state.currentCycle}.md`);
|
|
239
|
+
console.log(colors.path(` ${reportPath}`));
|
|
240
|
+
console.log(colors.dim('\nNext: Review report and run "tsq retro apply" to complete'));
|
|
241
|
+
}
|
|
242
|
+
async function applyImprovements() {
|
|
243
|
+
const projectRoot = await findProjectRoot();
|
|
244
|
+
if (!projectRoot) {
|
|
245
|
+
throw new Error('Not a TimSquad project');
|
|
246
|
+
}
|
|
247
|
+
const state = await getRetroState(projectRoot);
|
|
248
|
+
if (state.status !== 'applying') {
|
|
249
|
+
throw new Error('Generate report first. Run "tsq retro report"');
|
|
250
|
+
}
|
|
251
|
+
console.log(colors.warning('\n⚠ Improvement application requires manual review'));
|
|
252
|
+
console.log(colors.dim(' 1. Review the generated report'));
|
|
253
|
+
console.log(colors.dim(' 2. Update templates/prompts as needed'));
|
|
254
|
+
console.log(colors.dim(' 3. This cycle will be marked as complete\n'));
|
|
255
|
+
state.status = 'idle';
|
|
256
|
+
await saveRetroState(projectRoot, state);
|
|
257
|
+
printSuccess(`Retrospective cycle ${state.currentCycle} completed!`);
|
|
258
|
+
}
|
|
259
|
+
async function showRetroStatus() {
|
|
260
|
+
const projectRoot = await findProjectRoot();
|
|
261
|
+
if (!projectRoot) {
|
|
262
|
+
throw new Error('Not a TimSquad project');
|
|
263
|
+
}
|
|
264
|
+
const state = await getRetroState(projectRoot);
|
|
265
|
+
printHeader('Retrospective Status');
|
|
266
|
+
printKeyValue('Current Cycle', String(state.currentCycle));
|
|
267
|
+
printKeyValue('Status', state.status);
|
|
268
|
+
if (state.startedAt) {
|
|
269
|
+
printKeyValue('Started', state.startedAt.split('T')[0]);
|
|
270
|
+
}
|
|
271
|
+
// List completed cycles
|
|
272
|
+
const cyclesDir = path.join(projectRoot, '.timsquad', 'retrospective', 'cycles');
|
|
273
|
+
if (await exists(cyclesDir)) {
|
|
274
|
+
const cycles = await listFiles('cycle-*.md', cyclesDir);
|
|
275
|
+
if (cycles.length > 0) {
|
|
276
|
+
console.log(colors.dim(`\nCompleted cycles: ${cycles.length}`));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=retro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retro.js","sourceRoot":"","sources":["../../src/commands/retro.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgB5D"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { colors, printHeader, printError, printKeyValue } from '../utils/colors.js';
|
|
2
|
+
import { findProjectRoot, getProjectStatus } from '../lib/project.js';
|
|
3
|
+
import { PROJECT_TYPE_DESCRIPTIONS, PROJECT_LEVEL_DESCRIPTIONS } from '../types/project.js';
|
|
4
|
+
export function registerStatusCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('status')
|
|
7
|
+
.description('Show project status')
|
|
8
|
+
.option('-a, --all', 'Show all details')
|
|
9
|
+
.option('-s, --ssot', 'Show SSOT status only')
|
|
10
|
+
.option('-p, --phase', 'Show phase status only')
|
|
11
|
+
.option('-m, --metrics', 'Show metrics only')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
try {
|
|
14
|
+
await runStatus(options);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
printError(error.message);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async function runStatus(options) {
|
|
23
|
+
// Find project root
|
|
24
|
+
const projectRoot = await findProjectRoot();
|
|
25
|
+
if (!projectRoot) {
|
|
26
|
+
throw new Error('Not a TimSquad project. Run "tsq init" first.');
|
|
27
|
+
}
|
|
28
|
+
// Get full status
|
|
29
|
+
const status = await getProjectStatus(projectRoot);
|
|
30
|
+
// Show based on options
|
|
31
|
+
if (options.ssot) {
|
|
32
|
+
showSSOTStatus(status);
|
|
33
|
+
}
|
|
34
|
+
else if (options.phase) {
|
|
35
|
+
showPhaseStatus(status);
|
|
36
|
+
}
|
|
37
|
+
else if (options.metrics) {
|
|
38
|
+
showMetrics(status);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Show all or default
|
|
42
|
+
showFullStatus(status, options.all);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function showFullStatus(status, showAll = false) {
|
|
46
|
+
printHeader('TimSquad Project Status');
|
|
47
|
+
// Project info
|
|
48
|
+
console.log(colors.subheader('Project'));
|
|
49
|
+
printKeyValue('Name', status.project.name);
|
|
50
|
+
printKeyValue('Type', `${status.project.type} (${PROJECT_TYPE_DESCRIPTIONS[status.project.type]})`);
|
|
51
|
+
printKeyValue('Level', `${status.project.level} (${PROJECT_LEVEL_DESCRIPTIONS[status.project.level]})`);
|
|
52
|
+
console.log('');
|
|
53
|
+
// Phase
|
|
54
|
+
showPhaseStatus(status);
|
|
55
|
+
// SSOT
|
|
56
|
+
showSSOTStatus(status);
|
|
57
|
+
// Agents
|
|
58
|
+
if (showAll || status.agents.length > 0) {
|
|
59
|
+
console.log(colors.subheader('Agents'));
|
|
60
|
+
if (status.agents.length === 0) {
|
|
61
|
+
console.log(colors.dim(' No agents configured'));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
status.agents.forEach(agent => {
|
|
65
|
+
const modelColor = agent.model === 'opus' ? colors.primary : colors.dim;
|
|
66
|
+
console.log(` ${colors.agent(agent.name)} ${modelColor(`(${agent.model})`)}`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
console.log('');
|
|
70
|
+
}
|
|
71
|
+
// Logs
|
|
72
|
+
if (showAll || status.logs.total > 0) {
|
|
73
|
+
console.log(colors.subheader('Logs'));
|
|
74
|
+
printKeyValue('Total', String(status.logs.total));
|
|
75
|
+
if (status.logs.recent.length > 0) {
|
|
76
|
+
console.log(colors.dim(' Recent:'));
|
|
77
|
+
status.logs.recent.forEach(log => {
|
|
78
|
+
console.log(` ${colors.path(log)}`);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
console.log('');
|
|
82
|
+
}
|
|
83
|
+
// Retrospective
|
|
84
|
+
if (showAll) {
|
|
85
|
+
showMetrics(status);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function showPhaseStatus(status) {
|
|
89
|
+
console.log(colors.subheader('Phase'));
|
|
90
|
+
const { phase } = status;
|
|
91
|
+
const progressBar = createProgressBar(phase.progress);
|
|
92
|
+
printKeyValue('Current', colors.phase(phase.current));
|
|
93
|
+
printKeyValue('Started', phase.startedAt.split('T')[0]);
|
|
94
|
+
console.log(` ${colors.label('Progress:')} ${progressBar} ${phase.progress}%`);
|
|
95
|
+
console.log('');
|
|
96
|
+
}
|
|
97
|
+
function showSSOTStatus(status) {
|
|
98
|
+
console.log(colors.subheader('SSOT Documents'));
|
|
99
|
+
const required = status.ssot.filter(d => d.required);
|
|
100
|
+
const optional = status.ssot.filter(d => !d.required);
|
|
101
|
+
const filledCount = required.filter(d => d.filled).length;
|
|
102
|
+
console.log(` Required: ${colors.success(String(filledCount))}/${required.length}`);
|
|
103
|
+
// Show required documents
|
|
104
|
+
required.forEach(doc => {
|
|
105
|
+
const icon = doc.filled ? colors.success('✓') : colors.warning('○');
|
|
106
|
+
const name = doc.filled ? colors.value(doc.name) : colors.dim(doc.name);
|
|
107
|
+
console.log(` ${icon} ${name}`);
|
|
108
|
+
});
|
|
109
|
+
if (optional.length > 0) {
|
|
110
|
+
const optionalFilled = optional.filter(d => d.filled).length;
|
|
111
|
+
console.log(` Optional: ${optionalFilled}/${optional.length}`);
|
|
112
|
+
}
|
|
113
|
+
console.log('');
|
|
114
|
+
}
|
|
115
|
+
function showMetrics(status) {
|
|
116
|
+
console.log(colors.subheader('Retrospective'));
|
|
117
|
+
printKeyValue('Completed Cycles', String(status.retrospective.cycles));
|
|
118
|
+
printKeyValue('Success Patterns', String(status.retrospective.patterns.success));
|
|
119
|
+
printKeyValue('Failure Patterns', String(status.retrospective.patterns.failure));
|
|
120
|
+
console.log('');
|
|
121
|
+
}
|
|
122
|
+
function createProgressBar(progress, width = 20) {
|
|
123
|
+
const filled = Math.round((progress / 100) * width);
|
|
124
|
+
const empty = width - filled;
|
|
125
|
+
return colors.success('█'.repeat(filled)) + colors.dim('░'.repeat(empty));
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2C3D"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import chokidar from 'chokidar';
|
|
3
|
+
import { colors, printHeader, printError, printSuccess, printKeyValue } from '../utils/colors.js';
|
|
4
|
+
import { findProjectRoot } from '../lib/project.js';
|
|
5
|
+
import { exists, writeFile, readFile } from '../utils/fs.js';
|
|
6
|
+
import { getTimestamp } from '../utils/date.js';
|
|
7
|
+
export function registerWatchCommand(program) {
|
|
8
|
+
const watchCmd = program
|
|
9
|
+
.command('watch')
|
|
10
|
+
.description('SSOT file watcher');
|
|
11
|
+
// tsq watch start
|
|
12
|
+
watchCmd
|
|
13
|
+
.command('start')
|
|
14
|
+
.description('Start watching SSOT files')
|
|
15
|
+
.action(async () => {
|
|
16
|
+
try {
|
|
17
|
+
await startWatch();
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
printError(error.message);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
// tsq watch stop
|
|
25
|
+
watchCmd
|
|
26
|
+
.command('stop')
|
|
27
|
+
.description('Stop watching')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
try {
|
|
30
|
+
await stopWatch();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
printError(error.message);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// tsq watch status
|
|
38
|
+
watchCmd
|
|
39
|
+
.command('status')
|
|
40
|
+
.description('Show watch status')
|
|
41
|
+
.action(async () => {
|
|
42
|
+
try {
|
|
43
|
+
await showWatchStatus();
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
printError(error.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function getWatchState(projectRoot) {
|
|
52
|
+
const statePath = path.join(projectRoot, '.timsquad', 'state', 'watch-state.json');
|
|
53
|
+
if (!await exists(statePath)) {
|
|
54
|
+
return {
|
|
55
|
+
running: false,
|
|
56
|
+
watchedPaths: [],
|
|
57
|
+
changeCount: 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const content = await readFile(statePath);
|
|
62
|
+
return JSON.parse(content);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return {
|
|
66
|
+
running: false,
|
|
67
|
+
watchedPaths: [],
|
|
68
|
+
changeCount: 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function saveWatchState(projectRoot, state) {
|
|
73
|
+
const statePath = path.join(projectRoot, '.timsquad', 'state', 'watch-state.json');
|
|
74
|
+
await writeFile(statePath, JSON.stringify(state, null, 2));
|
|
75
|
+
}
|
|
76
|
+
async function startWatch() {
|
|
77
|
+
const projectRoot = await findProjectRoot();
|
|
78
|
+
if (!projectRoot) {
|
|
79
|
+
throw new Error('Not a TimSquad project');
|
|
80
|
+
}
|
|
81
|
+
const state = await getWatchState(projectRoot);
|
|
82
|
+
if (state.running) {
|
|
83
|
+
console.log(colors.warning('Watch already running'));
|
|
84
|
+
console.log(colors.dim(`Started at: ${state.startedAt}`));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
printHeader('SSOT File Watcher');
|
|
88
|
+
const ssotDir = path.join(projectRoot, '.timsquad', 'ssot');
|
|
89
|
+
const watchPaths = [
|
|
90
|
+
path.join(ssotDir, '**/*.md'),
|
|
91
|
+
path.join(ssotDir, '**/*.yaml'),
|
|
92
|
+
];
|
|
93
|
+
console.log(colors.subheader('Watching:'));
|
|
94
|
+
console.log(colors.path(` ${ssotDir}`));
|
|
95
|
+
console.log('');
|
|
96
|
+
// Initialize watcher
|
|
97
|
+
const watcher = chokidar.watch(watchPaths, {
|
|
98
|
+
persistent: true,
|
|
99
|
+
ignoreInitial: true,
|
|
100
|
+
awaitWriteFinish: {
|
|
101
|
+
stabilityThreshold: 500,
|
|
102
|
+
pollInterval: 100,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
let changeCount = 0;
|
|
106
|
+
const changeLog = [];
|
|
107
|
+
watcher
|
|
108
|
+
.on('change', (filePath) => {
|
|
109
|
+
changeCount++;
|
|
110
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
111
|
+
const timestamp = getTimestamp();
|
|
112
|
+
const logEntry = `[${timestamp}] Modified: ${relativePath}`;
|
|
113
|
+
console.log(colors.warning(`📝 ${logEntry}`));
|
|
114
|
+
changeLog.push(logEntry);
|
|
115
|
+
// Log to file
|
|
116
|
+
logChange(projectRoot, 'modified', relativePath);
|
|
117
|
+
})
|
|
118
|
+
.on('add', (filePath) => {
|
|
119
|
+
changeCount++;
|
|
120
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
121
|
+
const timestamp = getTimestamp();
|
|
122
|
+
const logEntry = `[${timestamp}] Added: ${relativePath}`;
|
|
123
|
+
console.log(colors.success(`➕ ${logEntry}`));
|
|
124
|
+
changeLog.push(logEntry);
|
|
125
|
+
logChange(projectRoot, 'added', relativePath);
|
|
126
|
+
})
|
|
127
|
+
.on('unlink', (filePath) => {
|
|
128
|
+
changeCount++;
|
|
129
|
+
const relativePath = path.relative(projectRoot, filePath);
|
|
130
|
+
const timestamp = getTimestamp();
|
|
131
|
+
const logEntry = `[${timestamp}] Deleted: ${relativePath}`;
|
|
132
|
+
console.log(colors.error(`➖ ${logEntry}`));
|
|
133
|
+
changeLog.push(logEntry);
|
|
134
|
+
logChange(projectRoot, 'deleted', relativePath);
|
|
135
|
+
})
|
|
136
|
+
.on('error', (error) => {
|
|
137
|
+
printError(`Watcher error: ${error.message}`);
|
|
138
|
+
});
|
|
139
|
+
// Update state
|
|
140
|
+
state.running = true;
|
|
141
|
+
state.startedAt = getTimestamp();
|
|
142
|
+
state.watchedPaths = watchPaths;
|
|
143
|
+
state.changeCount = 0;
|
|
144
|
+
await saveWatchState(projectRoot, state);
|
|
145
|
+
printSuccess('Watcher started');
|
|
146
|
+
console.log(colors.dim('\nPress Ctrl+C to stop'));
|
|
147
|
+
console.log(colors.dim('Or run: tsq watch stop'));
|
|
148
|
+
// Handle process termination
|
|
149
|
+
const cleanup = async () => {
|
|
150
|
+
console.log(colors.dim('\n\nStopping watcher...'));
|
|
151
|
+
await watcher.close();
|
|
152
|
+
state.running = false;
|
|
153
|
+
state.changeCount = changeCount;
|
|
154
|
+
await saveWatchState(projectRoot, state);
|
|
155
|
+
printSuccess(`Watcher stopped. ${changeCount} changes detected.`);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
};
|
|
158
|
+
process.on('SIGINT', cleanup);
|
|
159
|
+
process.on('SIGTERM', cleanup);
|
|
160
|
+
}
|
|
161
|
+
async function stopWatch() {
|
|
162
|
+
const projectRoot = await findProjectRoot();
|
|
163
|
+
if (!projectRoot) {
|
|
164
|
+
throw new Error('Not a TimSquad project');
|
|
165
|
+
}
|
|
166
|
+
const state = await getWatchState(projectRoot);
|
|
167
|
+
if (!state.running) {
|
|
168
|
+
console.log(colors.dim('No watcher running'));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Mark as stopped (actual process should handle cleanup)
|
|
172
|
+
state.running = false;
|
|
173
|
+
await saveWatchState(projectRoot, state);
|
|
174
|
+
printSuccess('Watcher marked as stopped');
|
|
175
|
+
console.log(colors.dim('If the process is still running, press Ctrl+C'));
|
|
176
|
+
}
|
|
177
|
+
async function showWatchStatus() {
|
|
178
|
+
const projectRoot = await findProjectRoot();
|
|
179
|
+
if (!projectRoot) {
|
|
180
|
+
throw new Error('Not a TimSquad project');
|
|
181
|
+
}
|
|
182
|
+
const state = await getWatchState(projectRoot);
|
|
183
|
+
printHeader('Watch Status');
|
|
184
|
+
printKeyValue('Status', state.running ? 'Running' : 'Stopped');
|
|
185
|
+
if (state.startedAt) {
|
|
186
|
+
printKeyValue('Started at', state.startedAt);
|
|
187
|
+
}
|
|
188
|
+
printKeyValue('Changes detected', String(state.changeCount));
|
|
189
|
+
if (state.watchedPaths.length > 0) {
|
|
190
|
+
console.log(colors.subheader('\nWatched paths:'));
|
|
191
|
+
state.watchedPaths.forEach(p => {
|
|
192
|
+
console.log(colors.dim(` ${p}`));
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function logChange(projectRoot, action, filePath) {
|
|
197
|
+
const logDir = path.join(projectRoot, '.timsquad', 'logs');
|
|
198
|
+
const logFile = path.join(logDir, 'ssot-changes.log');
|
|
199
|
+
const timestamp = getTimestamp();
|
|
200
|
+
const logEntry = `${timestamp} | ${action.toUpperCase().padEnd(8)} | ${filePath}\n`;
|
|
201
|
+
try {
|
|
202
|
+
let content = '';
|
|
203
|
+
if (await exists(logFile)) {
|
|
204
|
+
content = await readFile(logFile);
|
|
205
|
+
}
|
|
206
|
+
content += logEntry;
|
|
207
|
+
await writeFile(logFile, content);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Ignore logging errors
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=watch.js.map
|