or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-api.mdindex.mdmodels.mdprogrammatic-api.mdreporters.mdutilities.md

models.mddocs/

0

# History and Models

1

2

Data models for tracking code quality metrics over time and maintaining historical analysis data. These models provide the foundation for trend analysis and longitudinal code quality reporting.

3

4

## Capabilities

5

6

### Base History Model

7

8

Foundation class for tracking analysis data over time with basic operations for adding and retrieving historical entries.

9

10

```javascript { .api }

11

/**

12

* Base history tracking model for analysis data over time

13

* @param {Array} data - Initial history data (optional)

14

*/

15

class History {

16

constructor(data);

17

18

/** Number of history entries */

19

length: number;

20

21

/**

22

* Add entry to history

23

* @param {Object} obj - Object to add to history

24

*/

25

push(obj): void;

26

27

/**

28

* Convert history to JSON array

29

* @returns {Array} JSON representation of history

30

*/

31

toJSON(): Array;

32

}

33

```

34

35

**Constructor Parameters:**

36

37

- `data` (Array, optional): Initial history data to populate the instance

38

39

**Properties:**

40

41

- `length` (Number): Number of entries currently stored in history

42

43

**Methods:**

44

45

- `push(obj)`: Add a new entry to the history

46

- `toJSON()`: Convert the entire history to a JSON-serializable array

47

48

**Usage Examples:**

49

50

```javascript

51

const History = require('plato/lib/models/History');

52

53

// Create new history

54

const history = new History();

55

56

// Add entries

57

history.push({ date: '2024-01-01', complexity: 5.2 });

58

history.push({ date: '2024-01-02', complexity: 4.8 });

59

60

console.log(history.length); // 2

61

62

// Convert to JSON

63

const jsonHistory = history.toJSON();

64

console.log(jsonHistory); // [{ date: '2024-01-01', complexity: 5.2 }, ...]

65

66

// Initialize with existing data

67

const existingData = [

68

{ date: '2024-01-01', value: 100 },

69

{ date: '2024-01-02', value: 95 }

70

];

71

const populatedHistory = new History(existingData);

72

console.log(populatedHistory.length); // 2

73

```

74

75

### Overview History Model

76

77

Specialized history tracking for project-wide overview reports with aggregated metrics across all analyzed files.

78

79

```javascript { .api }

80

/**

81

* History tracking for overview reports (extends History)

82

* @param {Array} data - Initial history data (optional)

83

*/

84

class OverviewHistory extends History {

85

constructor(data);

86

87

/**

88

* Add overview report to history with timestamp

89

* @param {Object} report - Overview report object

90

* @param {String} date - Report date (optional, defaults to current date)

91

*/

92

addReport(report, date): void;

93

}

94

```

95

96

**Constructor Parameters:**

97

98

- `data` (Array, optional): Initial overview history data

99

100

**Methods:**

101

102

- `addReport(report, date)`: Add an overview report with automatic timestamping

103

104

**Usage Examples:**

105

106

```javascript

107

const OverviewHistory = require('plato/lib/models/OverviewHistory');

108

109

// Create overview history

110

const overviewHistory = new OverviewHistory();

111

112

// Add overview reports

113

const overviewReport = {

114

summary: {

115

total: { sloc: 1000, maintainability: 85.5 },

116

average: { sloc: 50, maintainability: 85.5 }

117

},

118

reports: []

119

};

120

121

overviewHistory.addReport(overviewReport, '2024-01-01');

122

overviewHistory.addReport(overviewReport, '2024-01-02');

123

124

// Track trends over time

125

const history = overviewHistory.toJSON();

126

history.forEach(entry => {

127

console.log(`${entry.date}: ${entry.summary.average.maintainability} maintainability`);

128

});

129

130

// Initialize with existing overview data

131

const existingOverviews = [

132

{ date: '2024-01-01', summary: { average: { maintainability: 85 } } }

133

];

134

const preloadedHistory = new OverviewHistory(existingOverviews);

135

```

136

137

### File History Model

138

139

Specialized history tracking for individual file analysis reports with file-specific metrics over time.

140

141

```javascript { .api }

142

/**

143

* History tracking for individual file reports (extends History)

144

* @param {Array} data - Initial history data (optional)

145

*/

146

class FileHistory extends History {

147

constructor(data);

148

149

/**

150

* Add file analysis report to history with timestamp

151

* @param {Object} report - File analysis report object

152

* @param {String} date - Report date (optional, defaults to current date)

153

*/

154

addReport(report, date): void;

155

}

156

```

157

158

**Constructor Parameters:**

159

160

- `data` (Array, optional): Initial file history data

161

162

**Methods:**

163

164

- `addReport(report, date)`: Add a file analysis report with automatic timestamping

165

166

**Usage Examples:**

167

168

```javascript

169

const FileHistory = require('plato/lib/models/FileHistory');

170

171

// Create file history

172

const fileHistory = new FileHistory();

173

174

// Add file reports

175

const fileReport = {

176

info: { file: 'src/app.js' },

177

complexity: {

178

cyclomatic: 8,

179

maintainability: 82.5,

180

sloc: { physical: 150, logical: 120 }

181

}

182

};

183

184

fileHistory.addReport(fileReport, '2024-01-01');

185

fileHistory.addReport(fileReport, '2024-01-02');

186

187

// Analyze file trends

188

const fileHistoryData = fileHistory.toJSON();

189

fileHistoryData.forEach(entry => {

190

console.log(`${entry.date}: Complexity ${entry.complexity.cyclomatic}`);

191

});

192

193

// Load existing file history

194

const existingFileData = [

195

{ date: '2024-01-01', complexity: { cyclomatic: 5 } }

196

];

197

const existingFileHistory = new FileHistory(existingFileData);

198

```

199

200

## Integration with Analysis Workflow

201

202

These models integrate with Plato's analysis workflow to provide historical tracking:

203

204

### Overview Tracking

205

206

```javascript

207

const plato = require('plato');

208

const OverviewHistory = require('plato/lib/models/OverviewHistory');

209

210

// Load existing overview history

211

const overviewHistory = new OverviewHistory();

212

213

// Perform analysis

214

plato.inspect(['src/**/*.js'], 'reports', {}, function(reports) {

215

// Generate overview

216

const overview = plato.getOverviewReport(reports);

217

218

// Add to history

219

const today = new Date().toISOString().split('T')[0];

220

overviewHistory.addReport(overview, today);

221

222

// Save history for future runs

223

const historyData = overviewHistory.toJSON();

224

require('fs').writeFileSync('overview-history.json', JSON.stringify(historyData));

225

});

226

```

227

228

### File-Level Tracking

229

230

```javascript

231

const plato = require('plato');

232

const FileHistory = require('plato/lib/models/FileHistory');

233

234

// Track individual files over time

235

const fileHistories = new Map();

236

237

plato.inspect(['src/**/*.js'], 'reports', {}, function(reports) {

238

const today = new Date().toISOString().split('T')[0];

239

240

reports.forEach(report => {

241

const fileName = report.info.file;

242

243

// Get or create history for this file

244

if (!fileHistories.has(fileName)) {

245

fileHistories.set(fileName, new FileHistory());

246

}

247

248

const fileHistory = fileHistories.get(fileName);

249

fileHistory.addReport(report, today);

250

});

251

252

// Identify files with increasing complexity

253

fileHistories.forEach((history, fileName) => {

254

const entries = history.toJSON();

255

if (entries.length >= 2) {

256

const latest = entries[entries.length - 1];

257

const previous = entries[entries.length - 2];

258

259

if (latest.complexity.cyclomatic > previous.complexity.cyclomatic) {

260

console.log(`${fileName}: Complexity increased from ${previous.complexity.cyclomatic} to ${latest.complexity.cyclomatic}`);

261

}

262

}

263

});

264

});

265

```

266

267

## Data Persistence

268

269

The models are designed to work with persistent storage for long-term trend analysis:

270

271

### JSON Serialization

272

273

```javascript

274

const OverviewHistory = require('plato/lib/models/OverviewHistory');

275

const fs = require('fs');

276

277

// Save history

278

function saveHistory(history, filename) {

279

const data = history.toJSON();

280

fs.writeFileSync(filename, JSON.stringify(data, null, 2));

281

}

282

283

// Load history

284

function loadHistory(filename, HistoryClass) {

285

if (fs.existsSync(filename)) {

286

const data = JSON.parse(fs.readFileSync(filename, 'utf8'));

287

return new HistoryClass(data);

288

}

289

return new HistoryClass();

290

}

291

292

// Usage

293

const overviewHistory = loadHistory('overview.json', OverviewHistory);

294

// ... perform analysis and add reports ...

295

saveHistory(overviewHistory, 'overview.json');

296

```

297

298

### Database Integration

299

300

```javascript

301

// Example database integration

302

class DatabaseHistory extends History {

303

constructor(tableName) {

304

super();

305

this.tableName = tableName;

306

this.loadFromDatabase();

307

}

308

309

async loadFromDatabase() {

310

// Load history from database

311

const rows = await db.query(`SELECT * FROM ${this.tableName} ORDER BY date`);

312

rows.forEach(row => this.push(row));

313

}

314

315

async push(obj) {

316

super.push(obj);

317

// Also save to database

318

await db.query(`INSERT INTO ${this.tableName} VALUES (?, ?)`, [obj.date, JSON.stringify(obj)]);

319

}

320

}

321

```

322

323

## Historical Analysis Patterns

324

325

Common patterns for analyzing historical data:

326

327

### Trend Analysis

328

329

```javascript

330

function analyzeTrends(history) {

331

const data = history.toJSON();

332

333

if (data.length < 2) return null;

334

335

const latest = data[data.length - 1];

336

const previous = data[data.length - 2];

337

338

return {

339

maintainabilityTrend: latest.complexity.maintainability - previous.complexity.maintainability,

340

complexityTrend: latest.complexity.cyclomatic - previous.complexity.cyclomatic,

341

slocTrend: latest.complexity.sloc.logical - previous.complexity.sloc.logical

342

};

343

}

344

```

345

346

### Quality Gates

347

348

```javascript

349

function checkQualityGates(overviewHistory) {

350

const data = overviewHistory.toJSON();

351

const latest = data[data.length - 1];

352

353

const alerts = [];

354

355

if (latest.summary.average.maintainability < 70) {

356

alerts.push('Low maintainability detected');

357

}

358

359

if (data.length >= 2) {

360

const previous = data[data.length - 2];

361

const maintainabilityChange = latest.summary.average.maintainability - previous.summary.average.maintainability;

362

363

if (maintainabilityChange < -5) {

364

alerts.push('Significant maintainability decrease');

365

}

366

}

367

368

return alerts;

369

}

370

```