@edcalderon/versioning 1.1.2 → 1.3.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/README.md +83 -17
- package/dist/extensions/cleanup-repo/index.d.ts +49 -0
- package/dist/extensions/cleanup-repo/index.js +649 -0
- package/dist/extensions/lifecycle-hooks/index.d.ts +4 -0
- package/dist/extensions/{lifecycle-hooks.js → lifecycle-hooks/index.js} +1 -1
- package/dist/extensions/npm-publish/index.d.ts +4 -0
- package/dist/extensions/{npm-publish.js → npm-publish/index.js} +1 -1
- package/dist/extensions/reentry-status/config-manager.js +3 -1
- package/dist/extensions/reentry-status/constants.d.ts +1 -1
- package/dist/extensions/reentry-status/constants.js +1 -1
- package/dist/extensions/reentry-status/extension.d.ts +4 -0
- package/dist/extensions/{reentry-status-extension.js → reentry-status/extension.js} +165 -18
- package/dist/extensions/reentry-status/git-context.d.ts +27 -0
- package/dist/extensions/reentry-status/git-context.js +94 -0
- package/dist/extensions/reentry-status/index.d.ts +3 -0
- package/dist/extensions/reentry-status/index.js +6 -0
- package/dist/extensions/reentry-status/roadmap-renderer.d.ts +7 -0
- package/dist/extensions/reentry-status/roadmap-renderer.js +27 -10
- package/dist/extensions/sample-extension/index.d.ts +4 -0
- package/dist/extensions/{sample-extension.js → sample-extension/index.js} +1 -1
- package/dist/extensions/secrets-check/index.d.ts +16 -0
- package/dist/extensions/secrets-check/index.js +264 -0
- package/dist/extensions.js +27 -15
- package/dist/versioning.d.ts +1 -0
- package/package.json +2 -2
- package/dist/extensions/lifecycle-hooks.d.ts +0 -4
- package/dist/extensions/npm-publish.d.ts +0 -4
- package/dist/extensions/reentry-status-extension.d.ts +0 -4
- package/dist/extensions/sample-extension.d.ts +0 -4
|
@@ -84,7 +84,9 @@ function defaultFilesConfigForProject(project) {
|
|
|
84
84
|
class ConfigManager {
|
|
85
85
|
static loadConfig(rootConfig, project) {
|
|
86
86
|
const canonicalProject = canonicalProjectKey(project);
|
|
87
|
-
|
|
87
|
+
// Try new extensionConfig location first, then fallback to root-level property
|
|
88
|
+
const extensionConfig = rootConfig?.extensionConfig?.['reentry-status'];
|
|
89
|
+
const raw = (extensionConfig ?? (rootConfig && typeof rootConfig === 'object' ? rootConfig.reentryStatus : undefined));
|
|
88
90
|
const basePartial = { ...(raw ?? {}) };
|
|
89
91
|
delete basePartial.projects;
|
|
90
92
|
const projectPartial = canonicalProject && raw && typeof raw === 'object' && raw.projects && typeof raw.projects === 'object'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const REENTRY_EXTENSION_NAME = "reentry-status
|
|
1
|
+
export declare const REENTRY_EXTENSION_NAME = "reentry-status";
|
|
2
2
|
export declare const REENTRY_STATUS_DIRNAME = ".versioning";
|
|
3
3
|
export declare const REENTRY_STATUS_JSON_FILENAME = "reentry.status.json";
|
|
4
4
|
export declare const REENTRY_STATUS_MD_FILENAME = "REENTRY.md";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ROADMAP_MD_FILENAME = exports.REENTRY_STATUS_MD_FILENAME = exports.REENTRY_STATUS_JSON_FILENAME = exports.REENTRY_STATUS_DIRNAME = exports.REENTRY_EXTENSION_NAME = void 0;
|
|
4
|
-
exports.REENTRY_EXTENSION_NAME = 'reentry-status
|
|
4
|
+
exports.REENTRY_EXTENSION_NAME = 'reentry-status';
|
|
5
5
|
exports.REENTRY_STATUS_DIRNAME = '.versioning';
|
|
6
6
|
exports.REENTRY_STATUS_JSON_FILENAME = 'reentry.status.json';
|
|
7
7
|
exports.REENTRY_STATUS_MD_FILENAME = 'REENTRY.md';
|
|
@@ -36,26 +36,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const commander_1 = require("commander");
|
|
37
37
|
const fs = __importStar(require("fs-extra"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
|
-
const config_manager_1 = require("./
|
|
40
|
-
const constants_1 = require("./
|
|
41
|
-
const file_manager_1 = require("./
|
|
42
|
-
const dirty_detection_1 = require("./
|
|
43
|
-
const github_rest_client_1 = require("./
|
|
44
|
-
const github_sync_adapter_1 = require("./
|
|
45
|
-
const obsidian_cli_client_1 = require("./
|
|
46
|
-
const obsidian_sync_adapter_1 = require("./
|
|
47
|
-
const roadmap_parser_1 = require("./
|
|
48
|
-
const roadmap_renderer_1 = require("./
|
|
49
|
-
const status_renderer_1 = require("./
|
|
50
|
-
const reentry_status_manager_1 = require("./reentry-status
|
|
39
|
+
const config_manager_1 = require("./config-manager");
|
|
40
|
+
const constants_1 = require("./constants");
|
|
41
|
+
const file_manager_1 = require("./file-manager");
|
|
42
|
+
const dirty_detection_1 = require("./dirty-detection");
|
|
43
|
+
const github_rest_client_1 = require("./github-rest-client");
|
|
44
|
+
const github_sync_adapter_1 = require("./github-sync-adapter");
|
|
45
|
+
const obsidian_cli_client_1 = require("./obsidian-cli-client");
|
|
46
|
+
const obsidian_sync_adapter_1 = require("./obsidian-sync-adapter");
|
|
47
|
+
const roadmap_parser_1 = require("./roadmap-parser");
|
|
48
|
+
const roadmap_renderer_1 = require("./roadmap-renderer");
|
|
49
|
+
const status_renderer_1 = require("./status-renderer");
|
|
50
|
+
const reentry_status_manager_1 = require("./reentry-status-manager");
|
|
51
|
+
const git_context_1 = require("./git-context");
|
|
51
52
|
const extension = {
|
|
52
53
|
name: constants_1.REENTRY_EXTENSION_NAME,
|
|
53
54
|
description: 'Maintains canonical re-entry status and synchronizes to files, GitHub Issues, and Obsidian notes',
|
|
54
|
-
version: '1.
|
|
55
|
+
version: '1.2.0',
|
|
55
56
|
hooks: {
|
|
56
57
|
postVersion: async (type, version, options) => {
|
|
57
58
|
try {
|
|
58
|
-
// Extensions are loaded before the CLI reads config per-command; use global config snapshot.
|
|
59
59
|
const configPath = options?.config ?? 'versioning.config.json';
|
|
60
60
|
if (!(await fs.pathExists(configPath)))
|
|
61
61
|
return;
|
|
@@ -65,15 +65,42 @@ const extension = {
|
|
|
65
65
|
return;
|
|
66
66
|
if (reentryCfg.hooks?.postVersion === false)
|
|
67
67
|
return;
|
|
68
|
+
// Auto-collect real git context
|
|
69
|
+
const gitCtx = await (0, git_context_1.collectGitContext)();
|
|
68
70
|
const manager = new reentry_status_manager_1.ReentryStatusManager({ fileManager: new file_manager_1.FileManager() });
|
|
69
71
|
await manager.applyContext(cfg, {
|
|
70
72
|
trigger: 'postVersion',
|
|
71
73
|
command: 'versioning bump',
|
|
72
74
|
options,
|
|
73
|
-
gitInfo: {
|
|
75
|
+
gitInfo: {
|
|
76
|
+
branch: gitCtx.branch,
|
|
77
|
+
commit: gitCtx.commit,
|
|
78
|
+
author: gitCtx.author,
|
|
79
|
+
timestamp: gitCtx.timestamp,
|
|
80
|
+
},
|
|
74
81
|
versioningInfo: { versionType: type, oldVersion: undefined, newVersion: version }
|
|
75
82
|
});
|
|
83
|
+
// Auto-update phase and suggest next step
|
|
84
|
+
const current = await manager.loadOrInit(cfg);
|
|
85
|
+
const phase = (0, git_context_1.inferPhase)(gitCtx, version);
|
|
86
|
+
const nextStep = (0, git_context_1.suggestNextStep)(gitCtx);
|
|
87
|
+
const updated = {
|
|
88
|
+
...current,
|
|
89
|
+
schemaVersion: '1.1',
|
|
90
|
+
currentPhase: phase,
|
|
91
|
+
nextSteps: [{ id: 'next', description: nextStep, priority: 1 }],
|
|
92
|
+
version: version,
|
|
93
|
+
versioning: {
|
|
94
|
+
...current.versioning,
|
|
95
|
+
currentVersion: version,
|
|
96
|
+
previousVersion: current.versioning.currentVersion,
|
|
97
|
+
versionType: type,
|
|
98
|
+
},
|
|
99
|
+
lastUpdated: new Date().toISOString(),
|
|
100
|
+
};
|
|
101
|
+
await manager.updateStatus(cfg, () => updated);
|
|
76
102
|
await manager.syncAll(cfg);
|
|
103
|
+
console.log(`📋 Re-entry auto-updated: phase=${phase}, next="${nextStep}"`);
|
|
77
104
|
}
|
|
78
105
|
catch (error) {
|
|
79
106
|
console.warn('⚠️ reentry-status postVersion hook failed:', error instanceof Error ? error.message : String(error));
|
|
@@ -90,12 +117,19 @@ const extension = {
|
|
|
90
117
|
return;
|
|
91
118
|
if (reentryCfg.hooks?.postRelease !== true)
|
|
92
119
|
return;
|
|
120
|
+
// Auto-collect real git context
|
|
121
|
+
const gitCtx = await (0, git_context_1.collectGitContext)();
|
|
93
122
|
const manager = new reentry_status_manager_1.ReentryStatusManager({ fileManager: new file_manager_1.FileManager() });
|
|
94
123
|
await manager.applyContext(cfg, {
|
|
95
124
|
trigger: 'postRelease',
|
|
96
125
|
command: 'versioning release',
|
|
97
126
|
options,
|
|
98
|
-
gitInfo: {
|
|
127
|
+
gitInfo: {
|
|
128
|
+
branch: gitCtx.branch,
|
|
129
|
+
commit: gitCtx.commit,
|
|
130
|
+
author: gitCtx.author,
|
|
131
|
+
timestamp: gitCtx.timestamp,
|
|
132
|
+
},
|
|
99
133
|
versioningInfo: { newVersion: version }
|
|
100
134
|
});
|
|
101
135
|
await manager.syncAll(cfg);
|
|
@@ -209,7 +243,6 @@ const extension = {
|
|
|
209
243
|
if (existingJson) {
|
|
210
244
|
const parsed = status_renderer_1.StatusRenderer.parseJson(existingJson);
|
|
211
245
|
if (migrate && parsed.schemaVersion === '1.0') {
|
|
212
|
-
// Explicit migration: rewrite as 1.1 without changing semantics.
|
|
213
246
|
const migrated = {
|
|
214
247
|
...parsed,
|
|
215
248
|
schemaVersion: '1.1',
|
|
@@ -257,6 +290,9 @@ const extension = {
|
|
|
257
290
|
await fileManager.writeStatusFiles(cfg, initial);
|
|
258
291
|
return { cfg, status: initial };
|
|
259
292
|
};
|
|
293
|
+
// ─────────────────────────────────────────────
|
|
294
|
+
// REENTRY COMMANDS
|
|
295
|
+
// ─────────────────────────────────────────────
|
|
260
296
|
program
|
|
261
297
|
.command('reentry')
|
|
262
298
|
.description('Manage re-entry status (fast layer)')
|
|
@@ -291,6 +327,114 @@ const extension = {
|
|
|
291
327
|
};
|
|
292
328
|
await manager.updateStatus(cfg, () => updated);
|
|
293
329
|
console.log('✅ Re-entry status updated');
|
|
330
|
+
}))
|
|
331
|
+
.addCommand(new commander_1.Command('update')
|
|
332
|
+
.description('Auto-fill re-entry status from last commit and current version (smart reentry)')
|
|
333
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
334
|
+
.option('-p, --project <name>', 'project scope')
|
|
335
|
+
.option('--phase <phase>', 'Override inferred phase')
|
|
336
|
+
.option('--next <text>', 'Override suggested next step')
|
|
337
|
+
.option('--dry-run', 'Show what would be updated without writing', false)
|
|
338
|
+
.action(async (options) => {
|
|
339
|
+
const { cfg, status } = await ensureReentryInitialized(options.config, false, options.project);
|
|
340
|
+
// Auto-collect git context
|
|
341
|
+
const gitCtx = await (0, git_context_1.collectGitContext)();
|
|
342
|
+
// Read current version from package.json
|
|
343
|
+
let currentVersion = status.versioning.currentVersion;
|
|
344
|
+
try {
|
|
345
|
+
const rootPkg = await fs.readJson('package.json');
|
|
346
|
+
currentVersion = rootPkg.version || currentVersion;
|
|
347
|
+
}
|
|
348
|
+
catch { /* keep existing */ }
|
|
349
|
+
// Infer phase or use override
|
|
350
|
+
const phase = options.phase || (0, git_context_1.inferPhase)(gitCtx, currentVersion);
|
|
351
|
+
// Suggest next step or use override
|
|
352
|
+
const nextStep = options.next || (0, git_context_1.suggestNextStep)(gitCtx);
|
|
353
|
+
const updated = {
|
|
354
|
+
...status,
|
|
355
|
+
schemaVersion: '1.1',
|
|
356
|
+
version: currentVersion,
|
|
357
|
+
currentPhase: phase,
|
|
358
|
+
nextSteps: [{ id: 'next', description: nextStep, priority: 1 }],
|
|
359
|
+
context: {
|
|
360
|
+
trigger: 'auto',
|
|
361
|
+
command: 'versioning reentry update',
|
|
362
|
+
gitInfo: {
|
|
363
|
+
branch: gitCtx.branch,
|
|
364
|
+
commit: gitCtx.commit,
|
|
365
|
+
author: gitCtx.author,
|
|
366
|
+
timestamp: gitCtx.timestamp,
|
|
367
|
+
},
|
|
368
|
+
versioningInfo: {
|
|
369
|
+
newVersion: currentVersion,
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
versioning: {
|
|
373
|
+
...status.versioning,
|
|
374
|
+
currentVersion: currentVersion,
|
|
375
|
+
previousVersion: status.versioning.currentVersion !== currentVersion
|
|
376
|
+
? status.versioning.currentVersion
|
|
377
|
+
: status.versioning.previousVersion,
|
|
378
|
+
},
|
|
379
|
+
lastUpdated: new Date().toISOString(),
|
|
380
|
+
updatedBy: gitCtx.author || 'auto',
|
|
381
|
+
};
|
|
382
|
+
if (options.dryRun) {
|
|
383
|
+
console.log('\n📋 Re-entry Update Preview (dry-run)\n');
|
|
384
|
+
console.log(` Branch: ${gitCtx.branch}`);
|
|
385
|
+
console.log(` Commit: ${gitCtx.commit}`);
|
|
386
|
+
console.log(` Message: ${gitCtx.commitMessage}`);
|
|
387
|
+
console.log(` Author: ${gitCtx.author}`);
|
|
388
|
+
console.log(` Version: ${currentVersion}`);
|
|
389
|
+
console.log(` Phase: ${phase}`);
|
|
390
|
+
console.log(` Next step: ${nextStep}`);
|
|
391
|
+
console.log(` Files changed: ${gitCtx.diffSummary.filesChanged} (+${gitCtx.diffSummary.insertions}/-${gitCtx.diffSummary.deletions})`);
|
|
392
|
+
console.log('\n Use without --dry-run to apply.\n');
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
await manager.updateStatus(cfg, () => updated);
|
|
396
|
+
console.log('\n📋 Re-entry Status Auto-Updated\n');
|
|
397
|
+
console.log(` ├─ Branch: ${gitCtx.branch}`);
|
|
398
|
+
console.log(` ├─ Commit: ${gitCtx.commit} — ${gitCtx.commitMessage}`);
|
|
399
|
+
console.log(` ├─ Version: ${currentVersion}`);
|
|
400
|
+
console.log(` ├─ Phase: ${phase}`);
|
|
401
|
+
console.log(` ├─ Next step: ${nextStep}`);
|
|
402
|
+
console.log(` └─ Updated by: ${gitCtx.author || 'auto'}\n`);
|
|
403
|
+
console.log(' 🔜 Suggested workflow:');
|
|
404
|
+
console.log(' 1. Review next step above');
|
|
405
|
+
console.log(' 2. Work on the task');
|
|
406
|
+
console.log(' 3. Commit & push');
|
|
407
|
+
console.log(' 4. Run `versioning reentry update` again\n');
|
|
408
|
+
}))
|
|
409
|
+
.addCommand(new commander_1.Command('show')
|
|
410
|
+
.description('Show current re-entry status summary')
|
|
411
|
+
.option('-c, --config <file>', 'config file path', 'versioning.config.json')
|
|
412
|
+
.option('-p, --project <name>', 'project scope')
|
|
413
|
+
.option('--json', 'Output as JSON', false)
|
|
414
|
+
.action(async (options) => {
|
|
415
|
+
const { status } = await ensureReentryInitialized(options.config, false, options.project);
|
|
416
|
+
if (options.json) {
|
|
417
|
+
console.log(JSON.stringify(status, null, 2));
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const milestoneText = status.milestone
|
|
421
|
+
? `${status.milestone.title} (${status.milestone.id})`
|
|
422
|
+
: '—';
|
|
423
|
+
const nextStep = status.nextSteps?.[0]?.description ?? '—';
|
|
424
|
+
const gitCommit = status.context?.gitInfo?.commit || '—';
|
|
425
|
+
const gitBranch = status.context?.gitInfo?.branch || '—';
|
|
426
|
+
console.log('\n┌───────────────────────────────────────────┐');
|
|
427
|
+
console.log('│ 📋 Re-entry Status Summary │');
|
|
428
|
+
console.log('├───────────────────────────────────────────┤');
|
|
429
|
+
console.log(`│ Version: ${status.version.padEnd(28)}│`);
|
|
430
|
+
console.log(`│ Phase: ${status.currentPhase.padEnd(28)}│`);
|
|
431
|
+
console.log(`│ Branch: ${gitBranch.padEnd(28)}│`);
|
|
432
|
+
console.log(`│ Commit: ${gitCommit.padEnd(28)}│`);
|
|
433
|
+
console.log(`│ Milestone: ${milestoneText.padEnd(28).substring(0, 28)}│`);
|
|
434
|
+
console.log(`│ Next step: ${nextStep.padEnd(28).substring(0, 28)}│`);
|
|
435
|
+
console.log(`│ Updated: ${status.lastUpdated.substring(0, 19).padEnd(28)}│`);
|
|
436
|
+
console.log(`│ Roadmap: ${status.roadmapFile.padEnd(28).substring(0, 28)}│`);
|
|
437
|
+
console.log('└───────────────────────────────────────────┘\n');
|
|
294
438
|
}))
|
|
295
439
|
.addCommand(new commander_1.Command('sync')
|
|
296
440
|
.description('Ensure generated status files exist and are up to date (idempotent)')
|
|
@@ -384,6 +528,9 @@ const extension = {
|
|
|
384
528
|
}
|
|
385
529
|
console.log('✅ Re-entry sync complete');
|
|
386
530
|
}));
|
|
531
|
+
// ─────────────────────────────────────────────
|
|
532
|
+
// ROADMAP COMMANDS (expanded with project identification)
|
|
533
|
+
// ─────────────────────────────────────────────
|
|
387
534
|
program
|
|
388
535
|
.command('roadmap')
|
|
389
536
|
.description('Manage roadmap/backlog (slow layer)')
|
|
@@ -525,4 +672,4 @@ const extension = {
|
|
|
525
672
|
}
|
|
526
673
|
};
|
|
527
674
|
exports.default = extension;
|
|
528
|
-
//# sourceMappingURL=
|
|
675
|
+
//# sourceMappingURL=extension.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface GitContextInfo {
|
|
2
|
+
branch: string;
|
|
3
|
+
commit: string;
|
|
4
|
+
commitMessage: string;
|
|
5
|
+
author: string;
|
|
6
|
+
timestamp: string;
|
|
7
|
+
changedFiles: string[];
|
|
8
|
+
diffSummary: {
|
|
9
|
+
insertions: number;
|
|
10
|
+
deletions: number;
|
|
11
|
+
filesChanged: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Collects the current git context automatically from the working directory.
|
|
16
|
+
* This is used to auto-fill the reentry status with real git data.
|
|
17
|
+
*/
|
|
18
|
+
export declare function collectGitContext(): Promise<GitContextInfo>;
|
|
19
|
+
/**
|
|
20
|
+
* Infer the current project phase based on git data and recent changes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function inferPhase(context: GitContextInfo, currentVersion: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Generate a suggested next step based on the last commit context.
|
|
25
|
+
*/
|
|
26
|
+
export declare function suggestNextStep(context: GitContextInfo): string;
|
|
27
|
+
//# sourceMappingURL=git-context.d.ts.map
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.collectGitContext = collectGitContext;
|
|
7
|
+
exports.inferPhase = inferPhase;
|
|
8
|
+
exports.suggestNextStep = suggestNextStep;
|
|
9
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
10
|
+
/**
|
|
11
|
+
* Collects the current git context automatically from the working directory.
|
|
12
|
+
* This is used to auto-fill the reentry status with real git data.
|
|
13
|
+
*/
|
|
14
|
+
async function collectGitContext() {
|
|
15
|
+
const git = (0, simple_git_1.default)();
|
|
16
|
+
try {
|
|
17
|
+
const [log, branch, diff] = await Promise.all([
|
|
18
|
+
git.log({ maxCount: 1 }),
|
|
19
|
+
git.branch(),
|
|
20
|
+
git.diffSummary(['HEAD~1', 'HEAD']).catch(() => null),
|
|
21
|
+
]);
|
|
22
|
+
const latest = log.latest;
|
|
23
|
+
const statusResult = await git.status();
|
|
24
|
+
return {
|
|
25
|
+
branch: branch.current || '',
|
|
26
|
+
commit: latest?.hash?.substring(0, 7) || '',
|
|
27
|
+
commitMessage: latest?.message || '',
|
|
28
|
+
author: latest?.author_name || '',
|
|
29
|
+
timestamp: latest?.date || new Date().toISOString(),
|
|
30
|
+
changedFiles: statusResult.files.map(f => f.path),
|
|
31
|
+
diffSummary: {
|
|
32
|
+
insertions: diff?.insertions ?? 0,
|
|
33
|
+
deletions: diff?.deletions ?? 0,
|
|
34
|
+
filesChanged: diff?.changed ?? 0,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return {
|
|
40
|
+
branch: '',
|
|
41
|
+
commit: '',
|
|
42
|
+
commitMessage: '',
|
|
43
|
+
author: '',
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
45
|
+
changedFiles: [],
|
|
46
|
+
diffSummary: { insertions: 0, deletions: 0, filesChanged: 0 },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Infer the current project phase based on git data and recent changes.
|
|
52
|
+
*/
|
|
53
|
+
function inferPhase(context, currentVersion) {
|
|
54
|
+
const msg = context.commitMessage.toLowerCase();
|
|
55
|
+
if (msg.startsWith('fix:') || msg.startsWith('hotfix:') || msg.includes('bugfix')) {
|
|
56
|
+
return 'maintenance';
|
|
57
|
+
}
|
|
58
|
+
if (msg.startsWith('test:') || msg.includes('test')) {
|
|
59
|
+
return 'testing';
|
|
60
|
+
}
|
|
61
|
+
if (msg.startsWith('feat:') || msg.startsWith('feature:')) {
|
|
62
|
+
return 'development';
|
|
63
|
+
}
|
|
64
|
+
if (msg.startsWith('chore: release') || msg.includes('deploy') || msg.includes('staging')) {
|
|
65
|
+
return 'staging';
|
|
66
|
+
}
|
|
67
|
+
if (msg.startsWith('docs:') || msg.startsWith('chore:')) {
|
|
68
|
+
return 'maintenance';
|
|
69
|
+
}
|
|
70
|
+
return 'development';
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Generate a suggested next step based on the last commit context.
|
|
74
|
+
*/
|
|
75
|
+
function suggestNextStep(context) {
|
|
76
|
+
const msg = context.commitMessage.toLowerCase();
|
|
77
|
+
if (msg.startsWith('feat:')) {
|
|
78
|
+
return `Write tests for: ${context.commitMessage.replace(/^feat:\s*/i, '').substring(0, 60)}`;
|
|
79
|
+
}
|
|
80
|
+
if (msg.startsWith('fix:')) {
|
|
81
|
+
return `Verify fix and add regression test for: ${context.commitMessage.replace(/^fix:\s*/i, '').substring(0, 50)}`;
|
|
82
|
+
}
|
|
83
|
+
if (msg.startsWith('test:')) {
|
|
84
|
+
return 'Review test coverage and consider edge cases';
|
|
85
|
+
}
|
|
86
|
+
if (msg.startsWith('chore: release')) {
|
|
87
|
+
return 'Verify deployment and update documentation';
|
|
88
|
+
}
|
|
89
|
+
if (msg.startsWith('docs:')) {
|
|
90
|
+
return 'Continue with next feature or bugfix';
|
|
91
|
+
}
|
|
92
|
+
return `Review changes from: ${context.commitMessage.substring(0, 60)}`;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=git-context.js.map
|
|
@@ -9,6 +9,9 @@ export * from './obsidian-sync-adapter';
|
|
|
9
9
|
export * from './obsidian-cli-client';
|
|
10
10
|
export * from './roadmap-parser';
|
|
11
11
|
export * from './roadmap-renderer';
|
|
12
|
+
export * from './git-context';
|
|
12
13
|
export * from './reentry-status-manager';
|
|
13
14
|
export * from './status-renderer';
|
|
15
|
+
import extension from './extension';
|
|
16
|
+
export default extension;
|
|
14
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -13,6 +13,9 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
13
13
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
16
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
20
|
__exportStar(require("./constants"), exports);
|
|
18
21
|
__exportStar(require("./config-manager"), exports);
|
|
@@ -25,6 +28,9 @@ __exportStar(require("./obsidian-sync-adapter"), exports);
|
|
|
25
28
|
__exportStar(require("./obsidian-cli-client"), exports);
|
|
26
29
|
__exportStar(require("./roadmap-parser"), exports);
|
|
27
30
|
__exportStar(require("./roadmap-renderer"), exports);
|
|
31
|
+
__exportStar(require("./git-context"), exports);
|
|
28
32
|
__exportStar(require("./reentry-status-manager"), exports);
|
|
29
33
|
__exportStar(require("./status-renderer"), exports);
|
|
34
|
+
const extension_1 = __importDefault(require("./extension"));
|
|
35
|
+
exports.default = extension_1.default;
|
|
30
36
|
//# sourceMappingURL=index.js.map
|
|
@@ -3,9 +3,16 @@ export declare const ROADMAP_MANAGED_START = "<!-- roadmap:managed:start -->";
|
|
|
3
3
|
export declare const ROADMAP_MANAGED_END = "<!-- roadmap:managed:end -->";
|
|
4
4
|
export interface RoadmapRenderOptions {
|
|
5
5
|
projectTitle?: string;
|
|
6
|
+
projectSlug?: string;
|
|
7
|
+
monorepoName?: string;
|
|
6
8
|
}
|
|
7
9
|
export declare class RoadmapRenderer {
|
|
8
10
|
static defaultRoadmapPath(baseDir?: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Extract the project name from the roadmap file path for auto-identification.
|
|
13
|
+
* e.g. ".versioning/projects/trader/ROADMAP.md" → "trader"
|
|
14
|
+
*/
|
|
15
|
+
static extractProjectFromPath(roadmapFile: string): string | null;
|
|
9
16
|
static renderManagedBlock(status?: Pick<ReentryStatus, 'milestone' | 'roadmapFile'>): string;
|
|
10
17
|
static renderTemplate(options?: RoadmapRenderOptions, status?: Pick<ReentryStatus, 'milestone' | 'roadmapFile'>): string;
|
|
11
18
|
/**
|
|
@@ -8,28 +8,45 @@ class RoadmapRenderer {
|
|
|
8
8
|
static defaultRoadmapPath(baseDir = constants_1.REENTRY_STATUS_DIRNAME) {
|
|
9
9
|
return `${baseDir}/${constants_1.ROADMAP_MD_FILENAME}`;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Extract the project name from the roadmap file path for auto-identification.
|
|
13
|
+
* e.g. ".versioning/projects/trader/ROADMAP.md" → "trader"
|
|
14
|
+
*/
|
|
15
|
+
static extractProjectFromPath(roadmapFile) {
|
|
16
|
+
const normalized = roadmapFile.replace(/\\/g, '/');
|
|
17
|
+
const match = /\.versioning\/projects\/([^/]+)\/ROADMAP\.md$/.exec(normalized);
|
|
18
|
+
return match ? match[1] : null;
|
|
19
|
+
}
|
|
11
20
|
static renderManagedBlock(status) {
|
|
12
21
|
const milestoneText = status?.milestone
|
|
13
22
|
? `${status.milestone.title} (id: ${status.milestone.id})`
|
|
14
23
|
: '—';
|
|
15
24
|
const roadmapFile = status?.roadmapFile ?? RoadmapRenderer.defaultRoadmapPath();
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
const projectSlug = RoadmapRenderer.extractProjectFromPath(roadmapFile);
|
|
26
|
+
// Build the managed block with project identification
|
|
27
|
+
const lines = [
|
|
18
28
|
exports.ROADMAP_MANAGED_START,
|
|
19
29
|
'> Managed by `@edcalderon/versioning` reentry-status-extension.',
|
|
20
30
|
`> Canonical roadmap file: ${roadmapFile}`,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
];
|
|
32
|
+
if (projectSlug) {
|
|
33
|
+
lines.push(`> Project: **${projectSlug}**`);
|
|
34
|
+
}
|
|
35
|
+
lines.push(`> Active milestone: ${milestoneText}`, '> ', '> Everything outside this block is user-editable.', exports.ROADMAP_MANAGED_END, '');
|
|
36
|
+
return lines.join('\n');
|
|
27
37
|
}
|
|
28
38
|
static renderTemplate(options = {}, status) {
|
|
29
39
|
const title = options.projectTitle?.trim() ? options.projectTitle.trim() : 'Untitled';
|
|
40
|
+
const roadmapFile = status?.roadmapFile ?? RoadmapRenderer.defaultRoadmapPath();
|
|
41
|
+
const projectSlug = options.projectSlug || RoadmapRenderer.extractProjectFromPath(roadmapFile);
|
|
42
|
+
const monorepo = options.monorepoName || '@ed/monorepo';
|
|
43
|
+
const headerLines = [`# Project Roadmap – ${title}`, ''];
|
|
44
|
+
// Add project metadata section
|
|
45
|
+
if (projectSlug) {
|
|
46
|
+
headerLines.push(`> 📦 **Project:** \`${projectSlug}\` | **Monorepo:** \`${monorepo}\``, '');
|
|
47
|
+
}
|
|
30
48
|
return [
|
|
31
|
-
|
|
32
|
-
'',
|
|
49
|
+
...headerLines,
|
|
33
50
|
RoadmapRenderer.renderManagedBlock(status),
|
|
34
51
|
'## North Star',
|
|
35
52
|
'',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { VersioningExtension } from '../../extensions';
|
|
2
|
+
export interface SecretCheckResult {
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
content: string;
|
|
6
|
+
pattern: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SecretsConfig {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
patterns?: string[];
|
|
11
|
+
allowlist?: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare function checkContentForSecrets(content: string, patterns: RegExp[], allowlist: string[], filename: string): SecretCheckResult[];
|
|
14
|
+
declare const extension: VersioningExtension;
|
|
15
|
+
export default extension;
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|