viepilot 3.11.0 → 3.12.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.
- package/CHANGELOG.md +21 -0
- package/bin/vp-tools.cjs +112 -0
- package/docs/skills-reference.md +36 -0
- package/lib/tracker-compact.cjs +124 -0
- package/lib/viepilot-update.cjs +1 -1
- package/package.json +1 -1
- package/workflows/autonomous.md +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## [3.12.1] - 2026-05-26
|
|
13
|
+
### Fixed
|
|
14
|
+
- `bin/vp-tools.cjs` `check-update --silent`: OS session guard file (`/tmp/vp-update-check-{today}.done`) — subsequent skill invocations skip npm call entirely, exit with 0 stdout (0 tokens) (DEBT-003)
|
|
15
|
+
- `lib/viepilot-update.cjs`: reduce version cache TTL 24h → 6h for more timely update notices (DEBT-003)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## [3.12.0] - 2026-05-25
|
|
20
|
+
### Changed
|
|
21
|
+
- `workflows/autonomous.md`: tracker-agent now rewrites Current State block (find-and-replace)
|
|
22
|
+
instead of appending — TRACKER.md stays ≤ 20 lines regardless of phase count (DEBT-002)
|
|
23
|
+
- `workflows/autonomous.md`: auto-compact size guard — if TRACKER.md > 400 lines, runs
|
|
24
|
+
`vp-tools tracker compact` before reading (DEBT-002)
|
|
25
|
+
- `workflows/autonomous.md`: Decision Log capped at 20 rows; older rows archived to TRACKER-HISTORY.md
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- `lib/tracker-compact.cjs`: compact() + rewriteCurrentState() — rescue tool for bloated TRACKER.md files
|
|
29
|
+
- `bin/vp-tools.cjs`: `tracker compact [--keep N]` subcommand — compact bloated TRACKER.md, archive history to TRACKER-HISTORY.md
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
12
33
|
## [3.11.0] - 2026-05-25
|
|
13
34
|
|
|
14
35
|
### Added
|
package/bin/vp-tools.cjs
CHANGED
|
@@ -1174,10 +1174,43 @@ ${colors.cyan}Examples:${colors.reset}
|
|
|
1174
1174
|
const silent = args.includes('--silent');
|
|
1175
1175
|
const json = args.includes('--json');
|
|
1176
1176
|
const force = args.includes('--force');
|
|
1177
|
+
|
|
1178
|
+
// OS session guard — skip npm check if already done today (DEBT-003)
|
|
1179
|
+
if (!force && !json) {
|
|
1180
|
+
const _os = require('os');
|
|
1181
|
+
const _today = new Date().toISOString().split('T')[0];
|
|
1182
|
+
const _guardFile = require('path').join(_os.tmpdir(), `vp-update-check-${_today}.done`);
|
|
1183
|
+
if (fs.existsSync(_guardFile)) {
|
|
1184
|
+
try {
|
|
1185
|
+
const _g = JSON.parse(fs.readFileSync(_guardFile, 'utf8'));
|
|
1186
|
+
if (silent) {
|
|
1187
|
+
if (_g.updateAvailable) { process.stdout.write(_g.latest + '\n'); process.exit(1); }
|
|
1188
|
+
process.exit(0);
|
|
1189
|
+
}
|
|
1190
|
+
process.exit(0);
|
|
1191
|
+
} catch (_) { /* corrupt guard — fall through */ }
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1177
1195
|
const { checkLatestVersion } = require('../lib/viepilot-update.cjs');
|
|
1178
1196
|
|
|
1179
1197
|
checkLatestVersion({ force })
|
|
1180
1198
|
.then(({ upToDate, installed, latest }) => {
|
|
1199
|
+
// Write OS session guard for subsequent skill inits (DEBT-003)
|
|
1200
|
+
if (silent || !json) {
|
|
1201
|
+
try {
|
|
1202
|
+
const _os2 = require('os');
|
|
1203
|
+
const _today2 = new Date().toISOString().split('T')[0];
|
|
1204
|
+
const _gf = require('path').join(_os2.tmpdir(), `vp-update-check-${_today2}.done`);
|
|
1205
|
+
fs.writeFileSync(_gf, JSON.stringify({
|
|
1206
|
+
updateAvailable: !upToDate,
|
|
1207
|
+
latest,
|
|
1208
|
+
installed,
|
|
1209
|
+
checkedAt: new Date().toISOString()
|
|
1210
|
+
}));
|
|
1211
|
+
} catch (_) { /* non-fatal */ }
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1181
1214
|
const has_update = !upToDate;
|
|
1182
1215
|
if (json) {
|
|
1183
1216
|
process.stdout.write(JSON.stringify({ installed, latest, has_update }) + '\n');
|
|
@@ -1389,6 +1422,70 @@ ${colors.cyan}Examples:${colors.reset}
|
|
|
1389
1422
|
console.log();
|
|
1390
1423
|
},
|
|
1391
1424
|
|
|
1425
|
+
/**
|
|
1426
|
+
* Compact bloated TRACKER.md and archive history (DEBT-002)
|
|
1427
|
+
* Usage: vp-tools tracker compact [--keep N] [--dry-run] [--path <file>]
|
|
1428
|
+
*/
|
|
1429
|
+
tracker: (args) => {
|
|
1430
|
+
const sub = args[0];
|
|
1431
|
+
|
|
1432
|
+
if (!sub || sub === 'help') {
|
|
1433
|
+
console.log(`${colors.cyan}Usage:${colors.reset}
|
|
1434
|
+
vp-tools tracker compact [--keep N] [--dry-run] [--path <file>]
|
|
1435
|
+
|
|
1436
|
+
${colors.cyan}Subcommands:${colors.reset}
|
|
1437
|
+
compact Compact bloated TRACKER.md, archive history
|
|
1438
|
+
|
|
1439
|
+
${colors.cyan}Options:${colors.reset}
|
|
1440
|
+
--keep N Number of rows to keep (default: 5)
|
|
1441
|
+
--dry-run Preview changes without writing
|
|
1442
|
+
--path <file> Path to TRACKER.md (default: .viepilot/TRACKER.md)
|
|
1443
|
+
|
|
1444
|
+
${colors.cyan}Examples:${colors.reset}
|
|
1445
|
+
${colors.gray}$${colors.reset} vp-tools tracker compact
|
|
1446
|
+
${colors.gray}$${colors.reset} vp-tools tracker compact --keep 10 --dry-run
|
|
1447
|
+
${colors.gray}$${colors.reset} vp-tools tracker compact --path /path/to/TRACKER.md`);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
if (sub === 'compact') {
|
|
1452
|
+
// Parse options
|
|
1453
|
+
const keepIdx = args.indexOf('--keep');
|
|
1454
|
+
const keepN = keepIdx !== -1 ? parseInt(args[keepIdx + 1], 10) : 5;
|
|
1455
|
+
const isDryRun = args.includes('--dry-run');
|
|
1456
|
+
|
|
1457
|
+
const pathIdx = args.indexOf('--path');
|
|
1458
|
+
const argPath = pathIdx !== -1 ? args[pathIdx + 1] : null;
|
|
1459
|
+
|
|
1460
|
+
const trackerPath = argPath || path.join(process.cwd(), '.viepilot', 'TRACKER.md');
|
|
1461
|
+
|
|
1462
|
+
try {
|
|
1463
|
+
const { compact } = require(path.join(__dirname, '../lib/tracker-compact.cjs'));
|
|
1464
|
+
const result = compact(trackerPath, { keep: keepN, dryRun: isDryRun });
|
|
1465
|
+
|
|
1466
|
+
if (isDryRun) {
|
|
1467
|
+
console.log(`[dry-run] Would compact ${trackerPath}`);
|
|
1468
|
+
console.log(` Lines to remove: ${result.linesRemoved}`);
|
|
1469
|
+
console.log(` Rows to archive: ${result.rowsArchived}`);
|
|
1470
|
+
console.log(' No files written.');
|
|
1471
|
+
} else {
|
|
1472
|
+
console.log(formatSuccess(`Compacted ${trackerPath}`));
|
|
1473
|
+
console.log(` Lines removed: ${result.linesRemoved}`);
|
|
1474
|
+
console.log(` Rows archived: ${result.rowsArchived}`);
|
|
1475
|
+
console.log(` History file: ${result.historyFile}`);
|
|
1476
|
+
console.log(` Result: ${result.trackerLines} lines remaining`);
|
|
1477
|
+
}
|
|
1478
|
+
process.exit(0);
|
|
1479
|
+
} catch (err) {
|
|
1480
|
+
console.error(formatError('tracker compact error:', err.message));
|
|
1481
|
+
process.exit(1);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
console.error(formatError(`Unknown tracker subcommand: ${sub}`, 'Use: compact'));
|
|
1486
|
+
process.exit(1);
|
|
1487
|
+
},
|
|
1488
|
+
|
|
1392
1489
|
/**
|
|
1393
1490
|
* Validate adapter capability requirements (FEAT-021 Phase 127)
|
|
1394
1491
|
* Usage: vp-tools validate --adapter <id>
|
|
@@ -1618,6 +1715,20 @@ ${colors.cyan}Examples:${colors.reset}
|
|
|
1618
1715
|
'vp-tools update --global --dry-run',
|
|
1619
1716
|
],
|
|
1620
1717
|
},
|
|
1718
|
+
'tracker': {
|
|
1719
|
+
usage: 'vp-tools tracker compact [--keep N] [--dry-run] [--path <file>]',
|
|
1720
|
+
description: 'Compact bloated TRACKER.md and archive history',
|
|
1721
|
+
options: [
|
|
1722
|
+
'--keep N: Number of rows to keep (default: 5)',
|
|
1723
|
+
'--dry-run: Preview changes without writing',
|
|
1724
|
+
'--path <file>: Path to TRACKER.md (default: .viepilot/TRACKER.md)',
|
|
1725
|
+
],
|
|
1726
|
+
examples: [
|
|
1727
|
+
'vp-tools tracker compact',
|
|
1728
|
+
'vp-tools tracker compact --keep 10 --dry-run',
|
|
1729
|
+
'vp-tools tracker compact --path /path/to/TRACKER.md',
|
|
1730
|
+
],
|
|
1731
|
+
},
|
|
1621
1732
|
};
|
|
1622
1733
|
|
|
1623
1734
|
if (command && commandHelp[command]) {
|
|
@@ -1669,6 +1780,7 @@ ${colors.cyan}Commands:${colors.reset}
|
|
|
1669
1780
|
${colors.bold}persona${colors.reset} <op> Manage user personas (get|infer|list|set|auto-switch|context)
|
|
1670
1781
|
${colors.bold}detect-adapter${colors.reset} [--json] Detect active adapter (claude-code/cursor/antigravity/codex/copilot)
|
|
1671
1782
|
${colors.bold}validate${colors.reset} --adapter <id> Validate adapter capability requirements; exits 1 on critical gaps
|
|
1783
|
+
${colors.bold}tracker${colors.reset} compact [--keep N] Compact bloated TRACKER.md, archive history
|
|
1672
1784
|
${colors.bold}help${colors.reset} [command] Show help (optionally for specific command)
|
|
1673
1785
|
|
|
1674
1786
|
${colors.cyan}Examples:${colors.reset}
|
package/docs/skills-reference.md
CHANGED
|
@@ -643,3 +643,39 @@ controls output style, stack preferences, and team-size assumptions injected int
|
|
|
643
643
|
### Output
|
|
644
644
|
- `~/.viepilot/config.json` updated
|
|
645
645
|
- `## User Persona` injected into each skill session
|
|
646
|
+
|
|
647
|
+
---
|
|
648
|
+
|
|
649
|
+
## /vp-qa
|
|
650
|
+
|
|
651
|
+
**Version**: v1.0.0 (fw 2.19.0)
|
|
652
|
+
**Phase**: 148 (ENH-100)
|
|
653
|
+
|
|
654
|
+
Scan-first QA agent team generator. Researches the codebase first (stack detection, file sampling,
|
|
655
|
+
domain mapping), then generates a context-tailored QA agent team using the Write tool directly — no
|
|
656
|
+
templates. Number of agents and their domains are determined by research output.
|
|
657
|
+
|
|
658
|
+
### Triggers
|
|
659
|
+
`vp-qa`, `/vp-qa`, "qa agents", "generate qa team", "quality assurance agents"
|
|
660
|
+
|
|
661
|
+
### Flags
|
|
662
|
+
- `/vp-qa` — auto-detect adapter + stack, generate QA team
|
|
663
|
+
- `/vp-qa --run` — generate + immediately invoke qa-orchestrator
|
|
664
|
+
- `/vp-qa --focus sec` — bias research toward security domains
|
|
665
|
+
- `/vp-qa --focus perf` — bias research toward performance domains
|
|
666
|
+
- `/vp-qa --target <id>` — override adapter detection (claude-code / cursor-agent / antigravity / codex / copilot)
|
|
667
|
+
|
|
668
|
+
### Output by Adapter
|
|
669
|
+
| Adapter | Output Location | Format |
|
|
670
|
+
|---------|----------------|--------|
|
|
671
|
+
| claude-code | `.claude/agents/qa-orchestrator.md` + `*-scanner.md` | Multi-file, parallel fan-out |
|
|
672
|
+
| cursor-agent | `.cursor/rules/qa-checklist.mdc` | Single MDC rule file |
|
|
673
|
+
| codex | `AGENTS.md` (appended) | `## QA Agent Instructions` section |
|
|
674
|
+
| antigravity | `.agents/skills/qa-orchestrator/SKILL.md` | Multi-file skill |
|
|
675
|
+
| copilot | `.github/agents/qa-orchestrator.agent.md` | Single agent file |
|
|
676
|
+
|
|
677
|
+
### Flow
|
|
678
|
+
1. **Research phase**: reads codebase, detects stack, samples files, reads `agents/qa-templates/rules/{stack}.md`
|
|
679
|
+
2. **Adapter routing**: `lib/qa-router.cjs` determines output spec
|
|
680
|
+
3. **LLM generates**: Write tool creates agent files directly from research output
|
|
681
|
+
4. **Post-scan**: generated `qa-orchestrator` creates `.viepilot/requests/BUG-{N}.md` entries; `AskUserQuestion` for accept/decline
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
function rewriteCurrentState(content, newBlock) {
|
|
5
|
+
const match = content.match(/^## Current State\n/m);
|
|
6
|
+
if (!match) return content;
|
|
7
|
+
const start = match.index + match[0].length;
|
|
8
|
+
const after = content.slice(start).search(/^## /m);
|
|
9
|
+
const before = content.slice(0, match.index);
|
|
10
|
+
const nextSection = after === -1 ? '' : content.slice(start + after);
|
|
11
|
+
return before + '## Current State\n' + newBlock + nextSection;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function parseStanzas(lines) {
|
|
15
|
+
const stanzas = [];
|
|
16
|
+
let current = [];
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
if (line.match(/\*\*Current Phase\*\*/)) {
|
|
19
|
+
if (current.length > 0) stanzas.push(current);
|
|
20
|
+
current = [line];
|
|
21
|
+
} else if (current.length > 0) {
|
|
22
|
+
current.push(line);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (current.length > 0) stanzas.push(current);
|
|
26
|
+
return stanzas;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function compact(trackerPath, options = {}) {
|
|
30
|
+
if (!fs.existsSync(trackerPath)) {
|
|
31
|
+
throw new Error('TRACKER.md not found: ' + trackerPath);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { keep = 5, dryRun = false } = options;
|
|
35
|
+
const maxRows = Math.max(keep * 4, 20);
|
|
36
|
+
const content = fs.readFileSync(trackerPath, 'utf8');
|
|
37
|
+
const lines = content.split('\n');
|
|
38
|
+
|
|
39
|
+
let linesRemoved = 0;
|
|
40
|
+
let rowsArchived = 0;
|
|
41
|
+
let archiveBlock = '';
|
|
42
|
+
|
|
43
|
+
// Process Current State
|
|
44
|
+
const csIdx = lines.findIndex(l => l === '## Current State');
|
|
45
|
+
const nextIdx = lines.findIndex((l, i) => i > csIdx && l.match(/^## /));
|
|
46
|
+
|
|
47
|
+
if (csIdx !== -1 && nextIdx !== -1) {
|
|
48
|
+
const csLines = lines.slice(csIdx + 1, nextIdx);
|
|
49
|
+
const stanzas = parseStanzas(csLines);
|
|
50
|
+
if (stanzas.length > 1) {
|
|
51
|
+
const archived = stanzas.slice(0, -1).map(s => s.join('\n')).join('\n');
|
|
52
|
+
linesRemoved = archived.split('\n').length;
|
|
53
|
+
archiveBlock += '## Archived Current State\n' + archived + '\n\n';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Process Decision Log
|
|
58
|
+
const dlIdx = lines.findIndex(l => l === '## Decision Log');
|
|
59
|
+
const dlEnd = nextIdx > dlIdx ? nextIdx : lines.length;
|
|
60
|
+
|
|
61
|
+
if (dlIdx !== -1) {
|
|
62
|
+
const tlines = lines.slice(dlIdx + 1, dlEnd);
|
|
63
|
+
let hIdx = -1, sIdx = -1;
|
|
64
|
+
for (let i = 0; i < tlines.length; i++) {
|
|
65
|
+
if (tlines[i].match(/\|\s*Date\s*\|/)) hIdx = i;
|
|
66
|
+
if (hIdx !== -1 && tlines[i].match(/^\|\s*[-:]+/)) {
|
|
67
|
+
sIdx = i;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (hIdx !== -1 && sIdx !== -1) {
|
|
72
|
+
const rows = tlines.slice(sIdx + 1).filter(l => l.trim().match(/^\|/));
|
|
73
|
+
if (rows.length > maxRows) {
|
|
74
|
+
rowsArchived = rows.length - maxRows;
|
|
75
|
+
archiveBlock += '## Archived Decision Log Rows\n' + rows.slice(0, -maxRows).join('\n') + '\n';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!dryRun && archiveBlock) {
|
|
81
|
+
const histPath = path.join(path.dirname(trackerPath), 'TRACKER-HISTORY.md');
|
|
82
|
+
fs.appendFileSync(histPath, '\n---\n# TRACKER Archive — ' + new Date().toISOString().split('T')[0] + '\n\n' + archiveBlock);
|
|
83
|
+
|
|
84
|
+
// Rewrite TRACKER.md
|
|
85
|
+
let newContent = content;
|
|
86
|
+
if (csIdx !== -1 && nextIdx !== -1) {
|
|
87
|
+
const stanzas = parseStanzas(lines.slice(csIdx + 1, nextIdx));
|
|
88
|
+
if (stanzas.length > 0) {
|
|
89
|
+
newContent = rewriteCurrentState(newContent, stanzas[stanzas.length - 1].join('\n') + '\n');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (dlIdx !== -1) {
|
|
94
|
+
const tlines = lines.slice(dlIdx + 1, dlEnd);
|
|
95
|
+
let hIdx = -1, sIdx = -1;
|
|
96
|
+
for (let i = 0; i < tlines.length; i++) {
|
|
97
|
+
if (tlines[i].match(/\|\s*Date\s*\|/)) hIdx = i;
|
|
98
|
+
if (hIdx !== -1 && tlines[i].match(/^\|\s*[-:]+/)) {
|
|
99
|
+
sIdx = i;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (hIdx !== -1 && sIdx !== -1) {
|
|
104
|
+
const rows = tlines.slice(sIdx + 1).filter(l => l.trim().match(/^\|/));
|
|
105
|
+
const kept = rows.slice(-maxRows);
|
|
106
|
+
const newTable = [tlines[hIdx], tlines[sIdx], ...kept].join('\n');
|
|
107
|
+
const before = lines.slice(0, dlIdx + 1).join('\n');
|
|
108
|
+
const after = lines.slice(dlEnd).join('\n');
|
|
109
|
+
newContent = before + '\n' + newTable + '\n' + after;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fs.writeFileSync(trackerPath, newContent, 'utf8');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
linesRemoved,
|
|
118
|
+
rowsArchived,
|
|
119
|
+
historyFile: path.join(path.dirname(trackerPath), 'TRACKER-HISTORY.md'),
|
|
120
|
+
trackerLines: lines.length - linesRemoved
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = { compact, rewriteCurrentState };
|
package/lib/viepilot-update.cjs
CHANGED
|
@@ -161,7 +161,7 @@ function runNpmUpdate(plan) {
|
|
|
161
161
|
*/
|
|
162
162
|
async function checkLatestVersion(opts = {}) {
|
|
163
163
|
const SILENT_RESULT = { upToDate: true, installed: '', latest: '' };
|
|
164
|
-
const TTL_MS =
|
|
164
|
+
const TTL_MS = 6 * 60 * 60 * 1000; // 6 hours
|
|
165
165
|
|
|
166
166
|
try {
|
|
167
167
|
const cacheFile =
|
package/package.json
CHANGED
package/workflows/autonomous.md
CHANGED
|
@@ -74,6 +74,13 @@ Parse `{{VP_ARGS}}` for flags:
|
|
|
74
74
|
Load context:
|
|
75
75
|
```bash
|
|
76
76
|
cat .viepilot/AI-GUIDE.md
|
|
77
|
+
|
|
78
|
+
# Size guard — auto-compact if TRACKER.md is bloated (> 400 lines)
|
|
79
|
+
if [ -f ".viepilot/TRACKER.md" ] && [ "$(wc -l < .viepilot/TRACKER.md)" -gt 400 ]; then
|
|
80
|
+
echo "⚠️ TRACKER.md is large ($(wc -l < .viepilot/TRACKER.md) lines) — auto-compacting..."
|
|
81
|
+
node bin/vp-tools.cjs tracker compact --keep 5
|
|
82
|
+
fi
|
|
83
|
+
|
|
77
84
|
cat .viepilot/TRACKER.md
|
|
78
85
|
cat .viepilot/ROADMAP.md
|
|
79
86
|
```
|
|
@@ -907,9 +914,10 @@ After phase quality gate passes, send a desktop + phone alert:
|
|
|
907
914
|
```
|
|
908
915
|
Agent({ subagent_type: "tracker-agent",
|
|
909
916
|
description: "Update TRACKER.md — phase {N} complete",
|
|
910
|
-
prompt: "operation:
|
|
917
|
+
prompt: "operation: rewrite-current-state. data: Last completed phase {N} — {phase_name}. version: {version}. IMPORTANT: REPLACE the entire '## Current State' section (find the section, overwrite it) — do NOT append new lines. The section must stay ≤ 20 lines total. Also cap '## Decision Log' table at 20 rows — if > 20 rows exist, archive older rows to .viepilot/TRACKER-HISTORY.md."
|
|
911
918
|
})
|
|
912
919
|
```
|
|
920
|
+
> Rescue bloated TRACKER.md: `node bin/vp-tools.cjs tracker compact [--keep N]` (DEBT-002)
|
|
913
921
|
7. Push branch + tags — spawn vp-git-agent:
|
|
914
922
|
```
|
|
915
923
|
Agent({ subagent_type: "vp-git-agent",
|