atris 1.9.6 → 2.0.2
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/GETTING_STARTED.md +10 -7
- package/PERSONA.md +2 -2
- package/README.md +6 -7
- package/atris/GETTING_STARTED.md +37 -32
- package/atris/PERSONA.md +2 -2
- package/atris/agent_team/navigator.md +4 -4
- package/atris/agent_team/validator.md +1 -1
- package/atris/atris.md +84 -17
- package/atris.md +81 -14
- package/bin/atris.js +359 -2506
- package/commands/analytics.js +150 -0
- package/commands/brainstorm.js +1291 -0
- package/commands/init.js +33 -6
- package/commands/status.js +159 -0
- package/commands/sync.js +8 -0
- package/commands/visualize.js +74 -0
- package/commands/workflow.js +834 -0
- package/lib/journal.js +35 -0
- package/lib/state-detection.js +10 -6
- package/package.json +1 -1
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function analyticsAtris() {
|
|
5
|
+
const targetDir = path.join(process.cwd(), 'atris');
|
|
6
|
+
|
|
7
|
+
if (!fs.existsSync(targetDir)) {
|
|
8
|
+
console.log('✗ atris/ folder not found. Run "atris init" first.');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Get date range (today + last 7 days)
|
|
13
|
+
const today = new Date();
|
|
14
|
+
const dates = [];
|
|
15
|
+
for (let i = 0; i < 7; i++) {
|
|
16
|
+
const date = new Date(today);
|
|
17
|
+
date.setDate(date.getDate() - i);
|
|
18
|
+
dates.push(date);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Parse journals and collect data
|
|
22
|
+
let totalCompletions = 0;
|
|
23
|
+
let todayCompletions = 0;
|
|
24
|
+
let todayInbox = 0;
|
|
25
|
+
let oldestInbox = 0;
|
|
26
|
+
const completionsByDay = {};
|
|
27
|
+
const hourCounts = {};
|
|
28
|
+
|
|
29
|
+
dates.forEach((date, index) => {
|
|
30
|
+
const year = date.getFullYear();
|
|
31
|
+
// Use local timezone, not UTC (fixes timezone bug)
|
|
32
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
33
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
34
|
+
const dateFormatted = `${year}-${month}-${day}`;
|
|
35
|
+
const logPath = path.join(targetDir, 'logs', year.toString(), `${dateFormatted}.md`);
|
|
36
|
+
|
|
37
|
+
if (!fs.existsSync(logPath)) {
|
|
38
|
+
completionsByDay[dateFormatted] = 0;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const content = fs.readFileSync(logPath, 'utf8');
|
|
43
|
+
|
|
44
|
+
// Count completions (C# pattern)
|
|
45
|
+
const completionMatches = content.match(/- \*\*C\d+:/g);
|
|
46
|
+
const completionCount = completionMatches ? completionMatches.length : 0;
|
|
47
|
+
completionsByDay[dateFormatted] = completionCount;
|
|
48
|
+
totalCompletions += completionCount;
|
|
49
|
+
|
|
50
|
+
if (index === 0) {
|
|
51
|
+
todayCompletions = completionCount;
|
|
52
|
+
|
|
53
|
+
// Count today's inbox
|
|
54
|
+
const inboxMatch = content.match(/## Inbox\n([\s\S]*?)(?=\n##|---)/);
|
|
55
|
+
if (inboxMatch && inboxMatch[1].trim()) {
|
|
56
|
+
const inboxMatches = inboxMatch[1].match(/- \*\*I\d+:/g);
|
|
57
|
+
todayInbox = inboxMatches ? inboxMatches.length : 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (index === 6) {
|
|
62
|
+
// Count oldest day's inbox for trend
|
|
63
|
+
const inboxMatch = content.match(/## Inbox\n([\s\S]*?)(?=\n##|---)/);
|
|
64
|
+
if (inboxMatch && inboxMatch[1].trim()) {
|
|
65
|
+
const inboxMatches = inboxMatch[1].match(/- \*\*I\d+:/g);
|
|
66
|
+
oldestInbox = inboxMatches ? inboxMatches.length : 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Parse timestamps for productivity hours
|
|
71
|
+
const timestampMatches = content.match(/\*\*(\d{2}):(\d{2}):(\d{2})\*\*/g);
|
|
72
|
+
if (timestampMatches) {
|
|
73
|
+
timestampMatches.forEach(ts => {
|
|
74
|
+
const hour = parseInt(ts.match(/\d{2}/)[0]);
|
|
75
|
+
hourCounts[hour] = (hourCounts[hour] || 0) + 1;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Calculate metrics
|
|
81
|
+
const velocity = (totalCompletions / 7).toFixed(1);
|
|
82
|
+
const inboxTrend = todayInbox > oldestInbox ? 'Growing ⬆' :
|
|
83
|
+
todayInbox < oldestInbox ? 'Shrinking ⬇' :
|
|
84
|
+
'Stable →';
|
|
85
|
+
|
|
86
|
+
// Find most productive hour
|
|
87
|
+
let mostProductiveHour = null;
|
|
88
|
+
let maxCount = 0;
|
|
89
|
+
Object.keys(hourCounts).forEach(hour => {
|
|
90
|
+
if (hourCounts[hour] > maxCount) {
|
|
91
|
+
maxCount = hourCounts[hour];
|
|
92
|
+
mostProductiveHour = hour;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const productiveHours = mostProductiveHour !== null ?
|
|
97
|
+
`${mostProductiveHour}:00 - ${(parseInt(mostProductiveHour) + 1) % 24}:00` :
|
|
98
|
+
'No data';
|
|
99
|
+
|
|
100
|
+
// Display analytics
|
|
101
|
+
// Use local timezone, not UTC (fixes timezone bug)
|
|
102
|
+
const year = today.getFullYear();
|
|
103
|
+
const month = String(today.getMonth() + 1).padStart(2, '0');
|
|
104
|
+
const day = String(today.getDate()).padStart(2, '0');
|
|
105
|
+
const dateFormatted = `${year}-${month}-${day}`;
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('┌─────────────────────────────────────────────────────────────┐');
|
|
108
|
+
console.log(`│ ATRIS Analytics — ${dateFormatted}${' '.repeat(33 - dateFormatted.length)}│`);
|
|
109
|
+
console.log('└─────────────────────────────────────────────────────────────┘');
|
|
110
|
+
console.log('');
|
|
111
|
+
|
|
112
|
+
// Today's performance
|
|
113
|
+
console.log(`📊 Today's Performance`);
|
|
114
|
+
console.log(` Completions: ${todayCompletions}`);
|
|
115
|
+
console.log(` Inbox items: ${todayInbox}`);
|
|
116
|
+
console.log('');
|
|
117
|
+
|
|
118
|
+
// Weekly trends
|
|
119
|
+
console.log(`📈 Weekly Trends (Last 7 Days)`);
|
|
120
|
+
console.log(` Total completions: ${totalCompletions}`);
|
|
121
|
+
console.log(` Average velocity: ${velocity} completions/day`);
|
|
122
|
+
console.log(` Inbox trend: ${inboxTrend}`);
|
|
123
|
+
console.log('');
|
|
124
|
+
|
|
125
|
+
// Productivity patterns
|
|
126
|
+
console.log(`⏰ Productivity Patterns`);
|
|
127
|
+
console.log(` Most active hour: ${productiveHours}`);
|
|
128
|
+
console.log(` Activity count: ${maxCount} timestamps`);
|
|
129
|
+
console.log('');
|
|
130
|
+
|
|
131
|
+
// Daily breakdown
|
|
132
|
+
console.log(`📅 Daily Breakdown`);
|
|
133
|
+
const sortedDates = Object.keys(completionsByDay).sort().reverse();
|
|
134
|
+
sortedDates.forEach((date, index) => {
|
|
135
|
+
const count = completionsByDay[date];
|
|
136
|
+
const bar = '█'.repeat(count);
|
|
137
|
+
const label = index === 0 ? ' (today)' : '';
|
|
138
|
+
console.log(` ${date}: ${bar} ${count}${label}`);
|
|
139
|
+
});
|
|
140
|
+
console.log('');
|
|
141
|
+
|
|
142
|
+
console.log('─────────────────────────────────────────────────────────────');
|
|
143
|
+
console.log('💡 Insight: This data syncs to backend via "atris log sync"');
|
|
144
|
+
console.log('');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
module.exports = {
|
|
149
|
+
analyticsAtris
|
|
150
|
+
};
|