@ktpartners/dgs-platform 2.9.0 → 3.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/CHANGELOG.md +197 -0
- package/README.md +34 -2
- package/agents/dgs-executor.md +124 -3
- package/agents/dgs-idea-researcher.md +447 -0
- package/agents/dgs-plan-checker.md +61 -3
- package/agents/dgs-planner.md +51 -8
- package/bin/install.js +44 -0
- package/commands/dgs/abandon-quick.md +28 -0
- package/commands/dgs/add-tests.md +2 -2
- package/commands/dgs/audit-milestone.md +4 -3
- package/commands/dgs/capture-principle.md +11 -11
- package/commands/dgs/cleanup.md +2 -2
- package/commands/dgs/complete-milestone.md +11 -11
- package/commands/dgs/complete-quick.md +28 -0
- package/commands/dgs/create-milestone-job.md +2 -2
- package/commands/dgs/debug.md +3 -3
- package/commands/dgs/develop-idea.md +1 -1
- package/commands/dgs/diff-report.md +124 -0
- package/commands/dgs/fast.md +3 -1
- package/commands/dgs/health.md +1 -1
- package/commands/dgs/map-codebase.md +6 -6
- package/commands/dgs/new-milestone.md +5 -5
- package/commands/dgs/new-project.md +8 -21
- package/commands/dgs/package-scan.md +43 -0
- package/commands/dgs/plan-milestone-gaps.md +1 -1
- package/commands/dgs/progress.md +3 -3
- package/commands/dgs/quick-abandon.md +8 -0
- package/commands/dgs/quick-complete.md +8 -0
- package/commands/dgs/quick.md +10 -3
- package/commands/dgs/research-idea.md +3 -2
- package/commands/dgs/research-phase.md +3 -3
- package/commands/dgs/switch-project.md +14 -1
- package/commands/dgs/write-spec.md +3 -3
- package/deliver-great-systems/bin/dgs-tools.cjs +401 -32
- package/deliver-great-systems/bin/lib/audit-tolerance.cjs +77 -0
- package/deliver-great-systems/bin/lib/audit-tolerance.test.cjs +101 -0
- package/deliver-great-systems/bin/lib/commands.cjs +626 -46
- package/deliver-great-systems/bin/lib/commands.test.cjs +451 -0
- package/deliver-great-systems/bin/lib/commit-verify.test.cjs +236 -0
- package/deliver-great-systems/bin/lib/config.cjs +80 -6
- package/deliver-great-systems/bin/lib/config.test.cjs +309 -0
- package/deliver-great-systems/bin/lib/context.cjs +120 -0
- package/deliver-great-systems/bin/lib/core.cjs +35 -14
- package/deliver-great-systems/bin/lib/core.test.cjs +79 -1
- package/deliver-great-systems/bin/lib/execution.cjs +49 -17
- package/deliver-great-systems/bin/lib/fast-routing.cjs +199 -0
- package/deliver-great-systems/bin/lib/fast-routing.test.cjs +108 -0
- package/deliver-great-systems/bin/lib/final-commit-precondition.test.cjs +87 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/bundler-audit-gemfile.json +21 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-expected.md +186 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/gate-parity-runresult.json +235 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/govulncheck-import.json +3 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/npm-audit-v10.json +37 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-clean.json +3 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/osv-vulns.json +77 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/pip-audit-requirements.json +28 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-lodash.json +30 -0
- package/deliver-great-systems/bin/lib/fixtures/package-scan/snyk-workspaces.json +55 -0
- package/deliver-great-systems/bin/lib/flat-migration.test.cjs +396 -0
- package/deliver-great-systems/bin/lib/frontmatter.cjs +1 -1
- package/deliver-great-systems/bin/lib/governance.cjs +211 -0
- package/deliver-great-systems/bin/lib/governance.test.cjs +339 -0
- package/deliver-great-systems/bin/lib/health-untracked-phase.test.cjs +269 -0
- package/deliver-great-systems/bin/lib/ideas.cjs +206 -91
- package/deliver-great-systems/bin/lib/ideas.test.cjs +244 -1
- package/deliver-great-systems/bin/lib/init.cjs +357 -61
- package/deliver-great-systems/bin/lib/init.test.cjs +625 -8
- package/deliver-great-systems/bin/lib/jobs.cjs +131 -25
- package/deliver-great-systems/bin/lib/jobs.test.cjs +193 -74
- package/deliver-great-systems/bin/lib/migration.cjs +409 -1
- package/deliver-great-systems/bin/lib/migration.test.cjs +158 -1
- package/deliver-great-systems/bin/lib/milestone.cjs +154 -31
- package/deliver-great-systems/bin/lib/milestone.test.cjs +203 -0
- package/deliver-great-systems/bin/lib/package-adapters.cjs +530 -0
- package/deliver-great-systems/bin/lib/package-adapters.test.cjs +618 -0
- package/deliver-great-systems/bin/lib/package-ecosystems.cjs +350 -0
- package/deliver-great-systems/bin/lib/package-ecosystems.test.cjs +348 -0
- package/deliver-great-systems/bin/lib/package-runner.cjs +199 -0
- package/deliver-great-systems/bin/lib/package-runner.test.cjs +198 -0
- package/deliver-great-systems/bin/lib/package-scan-provenance.cjs +56 -0
- package/deliver-great-systems/bin/lib/package-scan-provenance.test.cjs +103 -0
- package/deliver-great-systems/bin/lib/package-scan-report.cjs +1140 -0
- package/deliver-great-systems/bin/lib/package-scan-report.test.cjs +1963 -0
- package/deliver-great-systems/bin/lib/package-scan-skill.cjs +96 -0
- package/deliver-great-systems/bin/lib/package-scan-skill.test.cjs +136 -0
- package/deliver-great-systems/bin/lib/package-scan.cjs +919 -0
- package/deliver-great-systems/bin/lib/package-scan.test.cjs +2147 -0
- package/deliver-great-systems/bin/lib/phase.cjs +146 -3
- package/deliver-great-systems/bin/lib/phase.test.cjs +420 -0
- package/deliver-great-systems/bin/lib/plan-number-validity.test.cjs +48 -0
- package/deliver-great-systems/bin/lib/projects.cjs +65 -10
- package/deliver-great-systems/bin/lib/projects.test.cjs +198 -2
- package/deliver-great-systems/bin/lib/quick.cjs +739 -0
- package/deliver-great-systems/bin/lib/quick.test.cjs +730 -0
- package/deliver-great-systems/bin/lib/repos.cjs +37 -13
- package/deliver-great-systems/bin/lib/review.cjs +1821 -0
- package/deliver-great-systems/bin/lib/roadmap.cjs +34 -13
- package/deliver-great-systems/bin/lib/specs.cjs +3 -81
- package/deliver-great-systems/bin/lib/state-transition-gate.test.cjs +160 -0
- package/deliver-great-systems/bin/lib/state.cjs +147 -55
- package/deliver-great-systems/bin/lib/summary-frontmatter.cjs +54 -0
- package/deliver-great-systems/bin/lib/summary-frontmatter.test.cjs +78 -0
- package/deliver-great-systems/bin/lib/sweep-scope.test.cjs +263 -0
- package/deliver-great-systems/bin/lib/sync.cjs +75 -0
- package/deliver-great-systems/bin/lib/verify.cjs +198 -7
- package/deliver-great-systems/bin/lib/verify.test.cjs +82 -0
- package/deliver-great-systems/bin/lib/wave-0-template-rename.test.cjs +40 -0
- package/deliver-great-systems/bin/lib/worktrees.cjs +790 -0
- package/deliver-great-systems/bin/lib/worktrees.test.cjs +963 -0
- package/deliver-great-systems/references/agent-step-reliability.md +60 -0
- package/deliver-great-systems/references/conflict-resolution.md +4 -0
- package/deliver-great-systems/references/context-tiers.md +4 -0
- package/deliver-great-systems/references/package-scan-config.md +151 -0
- package/deliver-great-systems/references/questioning.md +0 -30
- package/deliver-great-systems/references/spec-review-loop.md +1 -2
- package/deliver-great-systems/references/workflow-conventions.md +29 -0
- package/deliver-great-systems/skills/dgs-tests/package-scan.md +44 -0
- package/deliver-great-systems/templates/REVIEW.md +35 -0
- package/deliver-great-systems/templates/VALIDATION.md +1 -1
- package/deliver-great-systems/templates/claude-md.md +27 -0
- package/deliver-great-systems/templates/package-scan-report.md +108 -0
- package/deliver-great-systems/templates/project.md +6 -170
- package/deliver-great-systems/templates/summary.md +3 -1
- package/deliver-great-systems/workflows/abandon-quick.md +89 -0
- package/deliver-great-systems/workflows/add-idea.md +3 -3
- package/deliver-great-systems/workflows/add-phase.md +5 -0
- package/deliver-great-systems/workflows/add-tests.md +14 -0
- package/deliver-great-systems/workflows/add-todo.md +1 -0
- package/deliver-great-systems/workflows/approve-spec.md +25 -4
- package/deliver-great-systems/workflows/audit-milestone.md +66 -10
- package/deliver-great-systems/workflows/audit-phase.md +15 -5
- package/deliver-great-systems/workflows/cancel-job.md +2 -2
- package/deliver-great-systems/workflows/check-todos.md +2 -3
- package/deliver-great-systems/workflows/codereview.md +103 -9
- package/deliver-great-systems/workflows/complete-milestone.md +218 -24
- package/deliver-great-systems/workflows/complete-quick.md +106 -0
- package/deliver-great-systems/workflows/consolidate-ideas.md +1 -1
- package/deliver-great-systems/workflows/create-milestone-job.md +4 -4
- package/deliver-great-systems/workflows/develop-idea.md +11 -11
- package/deliver-great-systems/workflows/diagnose-issues.md +14 -0
- package/deliver-great-systems/workflows/discuss-idea.md +1 -1
- package/deliver-great-systems/workflows/discuss-phase.md +3 -2
- package/deliver-great-systems/workflows/execute-phase.md +209 -33
- package/deliver-great-systems/workflows/execute-plan.md +22 -22
- package/deliver-great-systems/workflows/help.md +53 -20
- package/deliver-great-systems/workflows/import-spec.md +65 -7
- package/deliver-great-systems/workflows/init-product.md +45 -167
- package/deliver-great-systems/workflows/new-milestone.md +140 -33
- package/deliver-great-systems/workflows/new-project.md +60 -331
- package/deliver-great-systems/workflows/package-scan.md +59 -0
- package/deliver-great-systems/workflows/plan-phase.md +79 -1
- package/deliver-great-systems/workflows/progress-all.md +133 -0
- package/deliver-great-systems/workflows/quick-abandon.md +89 -0
- package/deliver-great-systems/workflows/quick-complete.md +106 -0
- package/deliver-great-systems/workflows/quick.md +328 -26
- package/deliver-great-systems/workflows/refine-spec.md +1 -1
- package/deliver-great-systems/workflows/research-idea.md +77 -139
- package/deliver-great-systems/workflows/resume-project.md +2 -2
- package/deliver-great-systems/workflows/run-job.md +29 -43
- package/deliver-great-systems/workflows/settings.md +13 -77
- package/deliver-great-systems/workflows/validate-phase.md +39 -1
- package/deliver-great-systems/workflows/verify-work.md +14 -0
- package/deliver-great-systems/workflows/write-spec.md +11 -13
- package/hooks/dist/dgs-enforce-discipline.js +196 -0
- package/package.json +1 -1
- package/scripts/build-hooks.js +1 -0
|
@@ -33,6 +33,7 @@ const { execSync } = require('child_process');
|
|
|
33
33
|
const { output, error, getProjectRoot } = require('./core.cjs');
|
|
34
34
|
const { getPlanningRoot } = require('./paths.cjs');
|
|
35
35
|
const { requireGitIdentity, formatAuthorString } = require('./identity.cjs');
|
|
36
|
+
const { extractFrontmatter, spliceFrontmatter, reconstructFrontmatter } = require('./frontmatter.cjs');
|
|
36
37
|
|
|
37
38
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
38
39
|
|
|
@@ -48,6 +49,7 @@ const KNOWN_COMMANDS = new Set([
|
|
|
48
49
|
'plan-milestone-gaps',
|
|
49
50
|
'discuss-phase',
|
|
50
51
|
'research-phase',
|
|
52
|
+
'validate-phase',
|
|
51
53
|
'verify-phase',
|
|
52
54
|
]);
|
|
53
55
|
|
|
@@ -92,6 +94,8 @@ const STATUS_TO_MARKER = {
|
|
|
92
94
|
'pending': ' ',
|
|
93
95
|
};
|
|
94
96
|
|
|
97
|
+
const JOB_STATUSES = ['pending', 'in-progress', 'completed', 'failed', 'rolled_back'];
|
|
98
|
+
|
|
95
99
|
// ─── Internal Helpers ───────────────────────────────────────────────────────
|
|
96
100
|
|
|
97
101
|
/**
|
|
@@ -339,6 +343,9 @@ function updateJobStep(filePath, stepIndex, status, options) {
|
|
|
339
343
|
}
|
|
340
344
|
|
|
341
345
|
/**
|
|
346
|
+
* @deprecated Use setJobStatus() for state transitions instead of physical file moves.
|
|
347
|
+
* Kept for backward compatibility with legacy directory-based job layouts.
|
|
348
|
+
*
|
|
342
349
|
* Move a job file from its current location to a target directory.
|
|
343
350
|
*
|
|
344
351
|
* @param {string} filePath - Absolute path to the job file
|
|
@@ -374,13 +381,31 @@ function moveJobFile(filePath, targetDir) {
|
|
|
374
381
|
}
|
|
375
382
|
|
|
376
383
|
/**
|
|
377
|
-
*
|
|
384
|
+
* Read status from a job file: YAML frontmatter first, then bold-key header fallback.
|
|
378
385
|
*
|
|
379
|
-
*
|
|
386
|
+
* @param {string} content - File content
|
|
387
|
+
* @returns {string|null} Status value or null
|
|
388
|
+
*/
|
|
389
|
+
function _readJobStatus(content) {
|
|
390
|
+
// Try YAML frontmatter first
|
|
391
|
+
const fmMatch = content.match(/^---\n([\s\S]+?)\n---/);
|
|
392
|
+
if (fmMatch) {
|
|
393
|
+
const statusMatch = fmMatch[1].match(/^status:\s*(.+)$/m);
|
|
394
|
+
if (statusMatch) return statusMatch[1].trim();
|
|
395
|
+
}
|
|
396
|
+
// Fall back to bold-key header: **Status:** value
|
|
397
|
+
const headerMatch = content.match(/\*\*Status:\*\*\s*(.+)/);
|
|
398
|
+
if (headerMatch) return headerMatch[1].trim().toLowerCase();
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Locate a job file by milestone version.
|
|
404
|
+
* Scans flat jobs/ directory first (frontmatter status), then falls back to legacy subdirectories.
|
|
380
405
|
*
|
|
381
406
|
* @param {string} cwd - Working directory
|
|
382
407
|
* @param {string} version - Milestone version (e.g., "v6.0" or "6.0")
|
|
383
|
-
* @returns {{ found: boolean, path?: string, directory?: string }}
|
|
408
|
+
* @returns {{ found: boolean, path?: string, directory?: string, status?: string }}
|
|
384
409
|
*/
|
|
385
410
|
function findJobFile(cwd, version) {
|
|
386
411
|
// Normalize version: ensure 'v' prefix
|
|
@@ -388,25 +413,56 @@ function findJobFile(cwd, version) {
|
|
|
388
413
|
const fileName = `milestone-${normalized}.md`;
|
|
389
414
|
const jobsDir = path.join(getPlanningRoot(cwd), 'jobs');
|
|
390
415
|
|
|
391
|
-
//
|
|
416
|
+
// Flat-first scan: check jobs/ root directory
|
|
417
|
+
const flatPath = path.join(jobsDir, fileName);
|
|
418
|
+
if (fs.existsSync(flatPath)) {
|
|
419
|
+
const content = fs.readFileSync(flatPath, 'utf-8');
|
|
420
|
+
const status = _readJobStatus(content);
|
|
421
|
+
return { found: true, path: flatPath, directory: null, status: status || 'pending' };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Legacy subdirectory scan
|
|
392
425
|
for (const dir of ['in-progress', 'pending', 'completed']) {
|
|
393
426
|
const filePath = path.join(jobsDir, dir, fileName);
|
|
394
427
|
if (fs.existsSync(filePath)) {
|
|
395
|
-
|
|
428
|
+
// Legacy fallback warning
|
|
429
|
+
process.stderr.write(`[DGS] Warning: job '${fileName}' found in legacy ${dir}/ directory. Run migration to flatten.\n`);
|
|
430
|
+
|
|
431
|
+
// Read frontmatter status if available
|
|
432
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
433
|
+
const fmStatus = _readJobStatus(content);
|
|
434
|
+
|
|
435
|
+
if (fmStatus && fmStatus !== dir && fmStatus !== dir.replace(/-/g, '_')) {
|
|
436
|
+
process.stderr.write(`[DGS] Warning: job '${fileName}' frontmatter status '${fmStatus}' disagrees with directory '${dir}'. Frontmatter wins.\n`);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const effectiveStatus = fmStatus || dir;
|
|
440
|
+
return { found: true, path: filePath, directory: dir, status: effectiveStatus };
|
|
396
441
|
}
|
|
397
442
|
}
|
|
398
443
|
|
|
399
|
-
// Search project subdirectories: projects/*/jobs/
|
|
444
|
+
// Search project subdirectories: projects/*/jobs/ (flat first, then legacy)
|
|
400
445
|
const projectsDir = path.join(getPlanningRoot(cwd), 'projects');
|
|
401
446
|
if (fs.existsSync(projectsDir)) {
|
|
402
447
|
const projects = fs.readdirSync(projectsDir).filter(d =>
|
|
403
448
|
fs.statSync(path.join(projectsDir, d)).isDirectory()
|
|
404
449
|
);
|
|
405
450
|
for (const project of projects) {
|
|
451
|
+
// Flat first
|
|
452
|
+
const projFlatPath = path.join(projectsDir, project, 'jobs', fileName);
|
|
453
|
+
if (fs.existsSync(projFlatPath)) {
|
|
454
|
+
const content = fs.readFileSync(projFlatPath, 'utf-8');
|
|
455
|
+
const status = _readJobStatus(content);
|
|
456
|
+
return { found: true, path: projFlatPath, directory: null, status: status || 'pending' };
|
|
457
|
+
}
|
|
458
|
+
// Legacy subdirectory
|
|
406
459
|
for (const dir of ['in-progress', 'pending', 'completed']) {
|
|
407
460
|
const filePath = path.join(projectsDir, project, 'jobs', dir, fileName);
|
|
408
461
|
if (fs.existsSync(filePath)) {
|
|
409
|
-
|
|
462
|
+
process.stderr.write(`[DGS] Warning: job '${fileName}' found in legacy ${dir}/ directory. Run migration to flatten.\n`);
|
|
463
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
464
|
+
const fmStatus = _readJobStatus(content);
|
|
465
|
+
return { found: true, path: filePath, directory: dir, status: fmStatus || dir };
|
|
410
466
|
}
|
|
411
467
|
}
|
|
412
468
|
}
|
|
@@ -628,6 +684,53 @@ function insertGapFixSection(filePath, afterStepIndex, cycleNumber, newPhases, v
|
|
|
628
684
|
* @param {string} phasesJson - JSON string of phases array [{number, name}]
|
|
629
685
|
* @param {boolean} raw - Raw output mode
|
|
630
686
|
*/
|
|
687
|
+
/**
|
|
688
|
+
* Set a job's status in both YAML frontmatter and bold-key header (internal helper — throws on error).
|
|
689
|
+
*
|
|
690
|
+
* Dual-write strategy: YAML frontmatter is added/updated as the source of truth,
|
|
691
|
+
* and the existing **Status:** markdown header is kept in sync for human readability.
|
|
692
|
+
*
|
|
693
|
+
* @param {string} cwd - Working directory
|
|
694
|
+
* @param {string} version - Milestone version (e.g., "v20.0")
|
|
695
|
+
* @param {string} status - Target status (must be in JOB_STATUSES)
|
|
696
|
+
* @returns {{ version: string, previous_status: string, status: string, path: string }}
|
|
697
|
+
* @throws {Error} If status is invalid or job not found
|
|
698
|
+
*/
|
|
699
|
+
function setJobStatus(cwd, version, status) {
|
|
700
|
+
if (!JOB_STATUSES.includes(status)) {
|
|
701
|
+
throw new Error(`Invalid status: ${status}. Allowed: ${JOB_STATUSES.join(', ')}`);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const found = findJobFile(cwd, version);
|
|
705
|
+
if (!found.found) {
|
|
706
|
+
throw new Error(`Job not found: ${version}`);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
let content = fs.readFileSync(found.path, 'utf-8');
|
|
710
|
+
const previousHeader = parseHeader(content);
|
|
711
|
+
const previousStatus = previousHeader.status;
|
|
712
|
+
|
|
713
|
+
// 1. Update bold-key markdown header (existing mechanism)
|
|
714
|
+
updateJobHeader(found.path, 'Status', status);
|
|
715
|
+
|
|
716
|
+
// 2. Update or add YAML frontmatter
|
|
717
|
+
content = fs.readFileSync(found.path, 'utf-8');
|
|
718
|
+
const fm = extractFrontmatter(content);
|
|
719
|
+
fm.status = status;
|
|
720
|
+
|
|
721
|
+
if (content.match(/^---\n/)) {
|
|
722
|
+
// Has frontmatter — splice it
|
|
723
|
+
content = spliceFrontmatter(content, fm);
|
|
724
|
+
} else {
|
|
725
|
+
// No frontmatter — add it at the very top
|
|
726
|
+
const yamlStr = reconstructFrontmatter({ status });
|
|
727
|
+
content = `---\n${yamlStr}\n---\n\n${content}`;
|
|
728
|
+
}
|
|
729
|
+
fs.writeFileSync(found.path, content, 'utf-8');
|
|
730
|
+
|
|
731
|
+
return { version, previous_status: previousStatus, status, path: found.path };
|
|
732
|
+
}
|
|
733
|
+
|
|
631
734
|
function cmdJobsInsertGapFixSection(cwd, file, afterIndexStr, cycleStr, version, phasesJson, raw) {
|
|
632
735
|
if (!file || afterIndexStr === undefined || cycleStr === undefined || !version || !phasesJson) {
|
|
633
736
|
error('Usage: jobs insert-gap-fix-section <file> <after-index> <cycle> <version> <phases-json>');
|
|
@@ -956,9 +1059,11 @@ function generateMilestoneSteps(phases, options) {
|
|
|
956
1059
|
steps.push({ command: 'map-codebase', args: `${num} --auto` });
|
|
957
1060
|
steps.push({ command: 'plan-phase', args: `${num} --non-interactive` });
|
|
958
1061
|
steps.push({ command: 'execute-phase', args: `${num} --non-interactive` });
|
|
1062
|
+
steps.push({ command: 'validate-phase', args: `${num} --scaffold` });
|
|
959
1063
|
steps.push({ command: 'audit-phase', args: `${num}` });
|
|
960
1064
|
} else if (NEEDS_EXECUTION.has(phase.disk_status)) {
|
|
961
1065
|
steps.push({ command: 'execute-phase', args: `${num} --non-interactive` });
|
|
1066
|
+
steps.push({ command: 'validate-phase', args: `${num} --scaffold` });
|
|
962
1067
|
steps.push({ command: 'audit-phase', args: `${num}` });
|
|
963
1068
|
}
|
|
964
1069
|
}
|
|
@@ -966,7 +1071,6 @@ function generateMilestoneSteps(phases, options) {
|
|
|
966
1071
|
// Append audit + complete steps if check is enabled
|
|
967
1072
|
if (check) {
|
|
968
1073
|
steps.push({ command: 'audit-milestone', args: version });
|
|
969
|
-
steps.push({ command: 'complete-milestone', args: version });
|
|
970
1074
|
}
|
|
971
1075
|
|
|
972
1076
|
return steps;
|
|
@@ -984,7 +1088,10 @@ function generateMilestoneSteps(phases, options) {
|
|
|
984
1088
|
function buildJobFileContent(version, check, steps, createdBy) {
|
|
985
1089
|
const created = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
986
1090
|
|
|
987
|
-
|
|
1091
|
+
// YAML frontmatter (source of truth for status)
|
|
1092
|
+
let content = `---\nstatus: pending\n---\n\n`;
|
|
1093
|
+
|
|
1094
|
+
content += `# Milestone Job: ${version}\n\n`;
|
|
988
1095
|
content += `**Version:** ${version}\n`;
|
|
989
1096
|
content += `**Created:** ${created}\n`;
|
|
990
1097
|
if (createdBy) {
|
|
@@ -1219,11 +1326,11 @@ function cmdJobsCreateMilestone(cwd, version, check, raw) {
|
|
|
1219
1326
|
// Build file content
|
|
1220
1327
|
const content = buildJobFileContent(resolvedVersion, check, steps, createdBy);
|
|
1221
1328
|
|
|
1222
|
-
// Write to
|
|
1223
|
-
const
|
|
1224
|
-
fs.mkdirSync(
|
|
1329
|
+
// Write to flat jobs/ directory (status tracked in frontmatter)
|
|
1330
|
+
const jobsDir = path.join(getPlanningRoot(cwd), 'jobs');
|
|
1331
|
+
fs.mkdirSync(jobsDir, { recursive: true });
|
|
1225
1332
|
const fileName = `milestone-${resolvedVersion}.md`;
|
|
1226
|
-
const filePath = path.join(
|
|
1333
|
+
const filePath = path.join(jobsDir, fileName);
|
|
1227
1334
|
fs.writeFileSync(filePath, content, 'utf-8');
|
|
1228
1335
|
|
|
1229
1336
|
// Count phases that contribute at least one step
|
|
@@ -1234,7 +1341,7 @@ function cmdJobsCreateMilestone(cwd, version, check, raw) {
|
|
|
1234
1341
|
const result = {
|
|
1235
1342
|
created: true,
|
|
1236
1343
|
version: resolvedVersion,
|
|
1237
|
-
file: path.join(path.relative(cwd, getPlanningRoot(cwd)) || '.', 'jobs',
|
|
1344
|
+
file: path.join(path.relative(cwd, getPlanningRoot(cwd)) || '.', 'jobs', fileName),
|
|
1238
1345
|
step_count: steps.length,
|
|
1239
1346
|
check,
|
|
1240
1347
|
phase_count: phasesWithSteps.length,
|
|
@@ -1357,7 +1464,7 @@ function listJobs(cwd) {
|
|
|
1357
1464
|
}
|
|
1358
1465
|
|
|
1359
1466
|
/**
|
|
1360
|
-
* Cancel an in-progress job: reset [>] steps to [ ], set Status to pending
|
|
1467
|
+
* Cancel an in-progress job: reset [>] steps to [ ], set Status to pending.
|
|
1361
1468
|
*
|
|
1362
1469
|
* @param {string} cwd - Working directory
|
|
1363
1470
|
* @param {string} version - Milestone version (e.g., "v6.0")
|
|
@@ -1368,7 +1475,7 @@ function cancelJob(cwd, version) {
|
|
|
1368
1475
|
if (!found.found) {
|
|
1369
1476
|
return { cancelled: false, reason: 'not_found' };
|
|
1370
1477
|
}
|
|
1371
|
-
if (found.
|
|
1478
|
+
if (found.status !== 'in-progress') {
|
|
1372
1479
|
return { cancelled: false, reason: 'not_in_progress' };
|
|
1373
1480
|
}
|
|
1374
1481
|
|
|
@@ -1397,17 +1504,14 @@ function cancelJob(cwd, version) {
|
|
|
1397
1504
|
}
|
|
1398
1505
|
}
|
|
1399
1506
|
|
|
1400
|
-
//
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
// Move to pending/
|
|
1404
|
-
const pendingDir = path.join(getPlanningRoot(cwd), 'jobs', 'pending');
|
|
1405
|
-
const moveResult = moveJobFile(filePath, pendingDir);
|
|
1507
|
+
// Set job status to pending via frontmatter edit (no file move)
|
|
1508
|
+
// setJobStatus handles both markdown header and frontmatter update
|
|
1509
|
+
setJobStatus(cwd, version, 'pending');
|
|
1406
1510
|
|
|
1407
1511
|
return {
|
|
1408
1512
|
cancelled: true,
|
|
1409
1513
|
version: version.startsWith('v') ? version : 'v' + version,
|
|
1410
|
-
path:
|
|
1514
|
+
path: filePath,
|
|
1411
1515
|
steps_reset: stepsReset,
|
|
1412
1516
|
};
|
|
1413
1517
|
}
|
|
@@ -1713,8 +1817,8 @@ function recordStartShas(cwd, jobFilePath) {
|
|
|
1713
1817
|
if (name === 'Name' || name.startsWith('-')) continue;
|
|
1714
1818
|
if (!repoPath || repoPath.startsWith('-')) continue;
|
|
1715
1819
|
|
|
1716
|
-
// Resolve absolute path: paths in REPOS.md are relative to planning root
|
|
1717
|
-
const absRepoPath = path.resolve(
|
|
1820
|
+
// Resolve absolute path: paths in REPOS.md are relative to the planning root
|
|
1821
|
+
const absRepoPath = path.resolve(planningRoot, repoPath);
|
|
1718
1822
|
if (!fs.existsSync(absRepoPath)) continue;
|
|
1719
1823
|
|
|
1720
1824
|
try {
|
|
@@ -1983,6 +2087,8 @@ module.exports = {
|
|
|
1983
2087
|
insertJobSteps,
|
|
1984
2088
|
buildGapFixSteps,
|
|
1985
2089
|
buildPhaseGapFixSteps,
|
|
2090
|
+
JOB_STATUSES,
|
|
2091
|
+
setJobStatus,
|
|
1986
2092
|
insertGapFixSection,
|
|
1987
2093
|
insertPhaseGapFixSection,
|
|
1988
2094
|
updatePhaseFixCycleHeader,
|