@pcoliveira90/pdd 0.2.6 → 0.3.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/LICENSE +20 -20
- package/README.en.md +75 -60
- package/README.md +75 -26
- package/README.pt-BR.md +75 -12
- package/bin/pdd-ai.js +24 -23
- package/bin/pdd-pro.js +7 -7
- package/bin/pdd.js +8 -27
- package/package.json +43 -42
- package/src/ai/analyze-change.js +41 -41
- package/src/ai/engine.js +34 -34
- package/src/ai/run-fix-analysis.js +187 -174
- package/src/cli/doctor-command.js +140 -101
- package/src/cli/doctor-fix.js +51 -51
- package/src/cli/index.js +164 -130
- package/src/cli/init-command.js +270 -270
- package/src/cli/status-command.js +33 -33
- package/src/core/fix-runner.js +134 -135
- package/src/core/ide-detector.js +94 -94
- package/src/core/patch-generator.js +125 -126
- package/src/core/pr-manager.js +21 -21
- package/src/core/project-review-agent.js +301 -301
- package/src/core/remediation-advisor.js +91 -91
- package/src/core/state-manager.js +71 -71
- package/src/core/template-registry.js +446 -320
- package/src/core/template-upgrade.js +68 -68
- package/src/core/validator.js +38 -38
- package/src/core/worktree-guard.js +54 -0
|
@@ -1,101 +1,140 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { PDD_TEMPLATE_VERSION } from '../core/template-registry.js';
|
|
4
|
-
import { runDoctorFix } from './doctor-fix.js';
|
|
5
|
-
import { buildDoctorRemediationPlan, printDoctorRemediationPlan } from '../core/remediation-advisor.js';
|
|
6
|
-
|
|
7
|
-
function exists(baseDir, relativePath) {
|
|
8
|
-
return fs.existsSync(path.join(baseDir, relativePath));
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { PDD_TEMPLATE_VERSION } from '../core/template-registry.js';
|
|
4
|
+
import { runDoctorFix } from './doctor-fix.js';
|
|
5
|
+
import { buildDoctorRemediationPlan, printDoctorRemediationPlan } from '../core/remediation-advisor.js';
|
|
6
|
+
|
|
7
|
+
function exists(baseDir, relativePath) {
|
|
8
|
+
return fs.existsSync(path.join(baseDir, relativePath));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function existsAny(baseDir, relativePaths) {
|
|
12
|
+
return relativePaths.some(relativePath => exists(baseDir, relativePath));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function cursorAdapterInstalled(baseDir) {
|
|
16
|
+
return existsAny(baseDir, [
|
|
17
|
+
'.cursor/rules/pdd.mdc',
|
|
18
|
+
'.cursor/commands/pdd.md',
|
|
19
|
+
'.cursor/commands/pdd-recon.md',
|
|
20
|
+
'.cursor/commands/pdd-fix.md',
|
|
21
|
+
'.cursor/commands/pdd-feature.md',
|
|
22
|
+
'.cursor/commands/pdd-verify.md',
|
|
23
|
+
'.cursor/pdd.prompt.md'
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function claudeAdapterInstalled(baseDir) {
|
|
28
|
+
return existsAny(baseDir, [
|
|
29
|
+
'.claude/CLAUDE.md',
|
|
30
|
+
'.claude/commands/pdd.md',
|
|
31
|
+
'.claude/commands/pdd-recon.md',
|
|
32
|
+
'.claude/commands/pdd-fix.md',
|
|
33
|
+
'.claude/commands/pdd-feature.md',
|
|
34
|
+
'.claude/commands/pdd-verify.md'
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function copilotAdapterInstalled(baseDir) {
|
|
39
|
+
return existsAny(baseDir, [
|
|
40
|
+
'.github/copilot-instructions.md',
|
|
41
|
+
'.github/copilot/pdd.prompt.md',
|
|
42
|
+
'.github/prompts/pdd-recon.prompt.md',
|
|
43
|
+
'.github/prompts/pdd-fix.prompt.md',
|
|
44
|
+
'.github/prompts/pdd-feature.prompt.md',
|
|
45
|
+
'.github/prompts/pdd-verify.prompt.md'
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function readVersion(baseDir) {
|
|
50
|
+
const file = path.join(baseDir, '.pdd/version.json');
|
|
51
|
+
if (!fs.existsSync(file)) return null;
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(fs.readFileSync(file, 'utf-8')).templateVersion;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function print(label, ok, detail = '') {
|
|
61
|
+
const icon = ok ? '✅' : '⚠️';
|
|
62
|
+
console.log(`${icon} ${label}${detail ? ` — ${detail}` : ''}`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function runDoctor(baseDir = process.cwd(), argv = []) {
|
|
66
|
+
const shouldFix = argv.includes('--fix');
|
|
67
|
+
|
|
68
|
+
console.log('🩺 PDD Doctor\n');
|
|
69
|
+
|
|
70
|
+
const coreChecks = {
|
|
71
|
+
constitution: exists(baseDir, '.pdd/constitution.md'),
|
|
72
|
+
delta: exists(baseDir, '.pdd/templates/delta-spec.md'),
|
|
73
|
+
patch: exists(baseDir, '.pdd/templates/patch-plan.md'),
|
|
74
|
+
verification: exists(baseDir, '.pdd/templates/verification-report.md'),
|
|
75
|
+
memory: exists(baseDir, '.pdd/memory/system-map.md')
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const adapters = {
|
|
79
|
+
claude: claudeAdapterInstalled(baseDir),
|
|
80
|
+
cursor: cursorAdapterInstalled(baseDir),
|
|
81
|
+
copilot: copilotAdapterInstalled(baseDir)
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const installedVersion = readVersion(baseDir);
|
|
85
|
+
|
|
86
|
+
// Raw checks
|
|
87
|
+
print('Core constitution', coreChecks.constitution);
|
|
88
|
+
print('Delta spec', coreChecks.delta);
|
|
89
|
+
print('Patch plan', coreChecks.patch);
|
|
90
|
+
print('Verification report', coreChecks.verification);
|
|
91
|
+
print('System map', coreChecks.memory);
|
|
92
|
+
|
|
93
|
+
console.log('');
|
|
94
|
+
|
|
95
|
+
print('Claude adapter', adapters.claude, adapters.claude ? 'installed' : 'missing');
|
|
96
|
+
print('Cursor adapter', adapters.cursor, adapters.cursor ? 'installed' : 'missing');
|
|
97
|
+
print('Copilot adapter', adapters.copilot, adapters.copilot ? 'installed' : 'missing');
|
|
98
|
+
|
|
99
|
+
console.log('');
|
|
100
|
+
|
|
101
|
+
if (!installedVersion) {
|
|
102
|
+
console.log('⚠️ No template version detected. Run `pdd init --here --force`.');
|
|
103
|
+
} else if (installedVersion !== PDD_TEMPLATE_VERSION) {
|
|
104
|
+
console.log(`⚠️ Templates outdated (${installedVersion} → ${PDD_TEMPLATE_VERSION})`);
|
|
105
|
+
console.log('👉 Run: pdd init --here --upgrade');
|
|
106
|
+
} else {
|
|
107
|
+
console.log('🎉 Templates up to date');
|
|
108
|
+
}
|
|
109
|
+
console.log('ℹ️ Note: CLI package version and template version are tracked separately.');
|
|
110
|
+
|
|
111
|
+
if (!adapters.claude && !adapters.cursor && !adapters.copilot) {
|
|
112
|
+
console.log('ℹ️ No IDE adapters installed');
|
|
113
|
+
console.log('👉 Run: pdd init --here --ide=claude (or cursor/copilot)');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Guided remediation
|
|
117
|
+
const plan = buildDoctorRemediationPlan({
|
|
118
|
+
coreChecks,
|
|
119
|
+
adapters,
|
|
120
|
+
installedVersion,
|
|
121
|
+
currentVersion: PDD_TEMPLATE_VERSION
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
printDoctorRemediationPlan(plan);
|
|
125
|
+
|
|
126
|
+
if (shouldFix) {
|
|
127
|
+
console.log('');
|
|
128
|
+
const result = runDoctorFix(baseDir);
|
|
129
|
+
|
|
130
|
+
if (result.changed) {
|
|
131
|
+
console.log('🔧 Auto-repair applied:');
|
|
132
|
+
result.repaired.forEach(file => console.log(`- fixed: ${file}`));
|
|
133
|
+
if (result.installedVersion && result.installedVersion !== result.currentVersion) {
|
|
134
|
+
console.log(`ℹ️ Version updated: ${result.installedVersion} → ${result.currentVersion}`);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
console.log('✅ No fixes needed');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/cli/doctor-fix.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { CORE_TEMPLATES, PDD_TEMPLATE_VERSION } from '../core/template-registry.js';
|
|
4
|
-
|
|
5
|
-
function ensureDir(filePath) {
|
|
6
|
-
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function writeFile(baseDir, relativePath, content) {
|
|
10
|
-
const fullPath = path.join(baseDir, relativePath);
|
|
11
|
-
ensureDir(fullPath);
|
|
12
|
-
fs.writeFileSync(fullPath, content, 'utf-8');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function readInstalledVersion(baseDir) {
|
|
16
|
-
const versionFile = path.join(baseDir, '.pdd/version.json');
|
|
17
|
-
if (!fs.existsSync(versionFile)) return null;
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(fs.readFileSync(versionFile, 'utf-8')).templateVersion || null;
|
|
21
|
-
} catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function isCoreFile(relativePath) {
|
|
27
|
-
return relativePath.startsWith('.pdd/');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function runDoctorFix(baseDir = process.cwd()) {
|
|
31
|
-
const installedVersion = readInstalledVersion(baseDir);
|
|
32
|
-
const repaired = [];
|
|
33
|
-
|
|
34
|
-
for (const [relativePath, content] of Object.entries(CORE_TEMPLATES)) {
|
|
35
|
-
const fullPath = path.join(baseDir, relativePath);
|
|
36
|
-
const missing = !fs.existsSync(fullPath);
|
|
37
|
-
const outdatedVersionFile = relativePath === '.pdd/version.json' && installedVersion !== PDD_TEMPLATE_VERSION;
|
|
38
|
-
|
|
39
|
-
if (isCoreFile(relativePath) && (missing || outdatedVersionFile)) {
|
|
40
|
-
writeFile(baseDir, relativePath, content);
|
|
41
|
-
repaired.push(relativePath);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
repaired,
|
|
47
|
-
installedVersion,
|
|
48
|
-
currentVersion: PDD_TEMPLATE_VERSION,
|
|
49
|
-
changed: repaired.length > 0
|
|
50
|
-
};
|
|
51
|
-
}
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { CORE_TEMPLATES, PDD_TEMPLATE_VERSION } from '../core/template-registry.js';
|
|
4
|
+
|
|
5
|
+
function ensureDir(filePath) {
|
|
6
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function writeFile(baseDir, relativePath, content) {
|
|
10
|
+
const fullPath = path.join(baseDir, relativePath);
|
|
11
|
+
ensureDir(fullPath);
|
|
12
|
+
fs.writeFileSync(fullPath, content, 'utf-8');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function readInstalledVersion(baseDir) {
|
|
16
|
+
const versionFile = path.join(baseDir, '.pdd/version.json');
|
|
17
|
+
if (!fs.existsSync(versionFile)) return null;
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(fs.readFileSync(versionFile, 'utf-8')).templateVersion || null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isCoreFile(relativePath) {
|
|
27
|
+
return relativePath.startsWith('.pdd/');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function runDoctorFix(baseDir = process.cwd()) {
|
|
31
|
+
const installedVersion = readInstalledVersion(baseDir);
|
|
32
|
+
const repaired = [];
|
|
33
|
+
|
|
34
|
+
for (const [relativePath, content] of Object.entries(CORE_TEMPLATES)) {
|
|
35
|
+
const fullPath = path.join(baseDir, relativePath);
|
|
36
|
+
const missing = !fs.existsSync(fullPath);
|
|
37
|
+
const outdatedVersionFile = relativePath === '.pdd/version.json' && installedVersion !== PDD_TEMPLATE_VERSION;
|
|
38
|
+
|
|
39
|
+
if (isCoreFile(relativePath) && (missing || outdatedVersionFile)) {
|
|
40
|
+
writeFile(baseDir, relativePath, content);
|
|
41
|
+
repaired.push(relativePath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
repaired,
|
|
47
|
+
installedVersion,
|
|
48
|
+
currentVersion: PDD_TEMPLATE_VERSION,
|
|
49
|
+
changed: repaired.length > 0
|
|
50
|
+
};
|
|
51
|
+
}
|
package/src/cli/index.js
CHANGED
|
@@ -1,130 +1,164 @@
|
|
|
1
|
-
import { readFileSync } from 'fs';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import { runValidation } from '../core/validator.js';
|
|
5
|
-
import { openPullRequest } from '../core/pr-manager.js';
|
|
6
|
-
import { generatePatchArtifacts } from '../core/patch-generator.js';
|
|
7
|
-
import { runInit } from './init-command.js';
|
|
8
|
-
import { runDoctor } from './doctor-command.js';
|
|
9
|
-
import { runStatus } from './status-command.js';
|
|
10
|
-
import { runResilientFixWorkflow } from '../core/fix-runner.js';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { runValidation } from '../core/validator.js';
|
|
5
|
+
import { openPullRequest } from '../core/pr-manager.js';
|
|
6
|
+
import { generatePatchArtifacts } from '../core/patch-generator.js';
|
|
7
|
+
import { runInit } from './init-command.js';
|
|
8
|
+
import { runDoctor } from './doctor-command.js';
|
|
9
|
+
import { runStatus } from './status-command.js';
|
|
10
|
+
import { runResilientFixWorkflow } from '../core/fix-runner.js';
|
|
11
|
+
import { enforceLinkedWorktree } from '../core/worktree-guard.js';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
|
|
15
|
+
function readCliVersion() {
|
|
16
|
+
const pkgPath = join(__dirname, '../../package.json');
|
|
17
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
18
|
+
return pkg.version;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseFixArgs(argv) {
|
|
22
|
+
const issue = argv
|
|
23
|
+
.filter(arg => !arg.startsWith('--') && arg !== 'fix')
|
|
24
|
+
.join(' ')
|
|
25
|
+
.trim();
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
issue,
|
|
29
|
+
openPr: argv.includes('--open-pr'),
|
|
30
|
+
dryRun: argv.includes('--dry-run'),
|
|
31
|
+
noValidate: argv.includes('--no-validate'),
|
|
32
|
+
allowMainWorktree: argv.includes('--allow-main-worktree')
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function runCli(argv = process.argv.slice(2)) {
|
|
37
|
+
const command = argv[0];
|
|
38
|
+
const cwd = process.cwd();
|
|
39
|
+
|
|
40
|
+
if (command === '--version' || command === '-v' || command === '-V' || command === 'version') {
|
|
41
|
+
console.log(readCliVersion());
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (command === 'init') {
|
|
46
|
+
const allowMainWorktree = argv.includes('--allow-main-worktree');
|
|
47
|
+
const mutatesCurrentRepo = argv.includes('--here') || argv.includes('--upgrade');
|
|
48
|
+
if (mutatesCurrentRepo) {
|
|
49
|
+
enforceLinkedWorktree({
|
|
50
|
+
baseDir: cwd,
|
|
51
|
+
commandName: 'init',
|
|
52
|
+
allowMainWorktree
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
await runInit(argv);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (command === 'doctor') {
|
|
60
|
+
const allowMainWorktree = argv.includes('--allow-main-worktree');
|
|
61
|
+
if (argv.includes('--fix')) {
|
|
62
|
+
enforceLinkedWorktree({
|
|
63
|
+
baseDir: cwd,
|
|
64
|
+
commandName: 'doctor --fix',
|
|
65
|
+
allowMainWorktree
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
runDoctor(cwd, argv);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (command === 'status') {
|
|
73
|
+
runStatus(cwd);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (command === 'fix') {
|
|
78
|
+
const { issue, openPr, dryRun, noValidate, allowMainWorktree } = parseFixArgs(argv);
|
|
79
|
+
|
|
80
|
+
if (!issue) {
|
|
81
|
+
console.error('❌ Missing issue description.');
|
|
82
|
+
console.log('Use: pdd fix "description" [--open-pr] [--dry-run] [--no-validate] [--allow-main-worktree]');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
enforceLinkedWorktree({
|
|
87
|
+
baseDir: cwd,
|
|
88
|
+
commandName: 'fix',
|
|
89
|
+
allowMainWorktree
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log('🔧 PDD Fix Workflow');
|
|
93
|
+
console.log(`Issue: ${issue}`);
|
|
94
|
+
console.log(`Open PR prep: ${openPr ? 'yes' : 'no'}`);
|
|
95
|
+
console.log(`Dry run: ${dryRun ? 'yes' : 'no'}`);
|
|
96
|
+
console.log(`Validation: ${noValidate ? 'skipped' : 'enabled'}`);
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const result = await runResilientFixWorkflow({
|
|
100
|
+
baseDir: cwd,
|
|
101
|
+
issue,
|
|
102
|
+
dryRun,
|
|
103
|
+
noValidate,
|
|
104
|
+
openPr,
|
|
105
|
+
generatePatchArtifacts,
|
|
106
|
+
runValidation,
|
|
107
|
+
openPullRequest
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (result.status === 'dry-run') {
|
|
111
|
+
console.log('📝 Dry run only. No files created.');
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (result.changeId) {
|
|
116
|
+
console.log(`Tracking change: ${result.changeId}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (Array.isArray(result.files) && result.files.length > 0) {
|
|
120
|
+
console.log('🧩 Patch artifacts created:');
|
|
121
|
+
result.files.forEach(file => console.log(`- ${file}`));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log('✅ Fix workflow finished.');
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(`❌ ${error.message}`);
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (command === 'help' || !command) {
|
|
134
|
+
console.log(`PDD CLI ${readCliVersion()}`);
|
|
135
|
+
console.log('');
|
|
136
|
+
console.log('Core commands:');
|
|
137
|
+
console.log(' pdd init <project-name> Initialize PDD templates in a new folder');
|
|
138
|
+
console.log(' pdd init --here [--force] [--upgrade] [-y] [--no-ide-prompt] Initialize or upgrade templates in current project');
|
|
139
|
+
console.log(' [--no-project-review] [--ide=claude|cursor|copilot|...]');
|
|
140
|
+
console.log(' pdd doctor [--fix] Check installation health and optionally auto-repair');
|
|
141
|
+
console.log(' pdd status Show current change workflow state');
|
|
142
|
+
console.log(' pdd fix "description" [--open-pr] [--dry-run] [--no-validate] Run fix workflow and generate artifacts');
|
|
143
|
+
console.log(' pdd version (or: pdd --version, pdd -v) Show CLI version');
|
|
144
|
+
console.log('');
|
|
145
|
+
console.log('Worktree policy:');
|
|
146
|
+
console.log(' Mutating commands require linked git worktree by default.');
|
|
147
|
+
console.log(' Override intentionally with --allow-main-worktree.');
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log('AI command (official binary):');
|
|
150
|
+
console.log(' pdd-ai [--provider=openai|claude|openrouter] [--task=analysis|build|test|review] [--model=<id>] "issue"');
|
|
151
|
+
console.log('');
|
|
152
|
+
console.log('Examples:');
|
|
153
|
+
console.log(' pdd doctor --fix');
|
|
154
|
+
console.log(' pdd status');
|
|
155
|
+
console.log(' pdd init --here --upgrade');
|
|
156
|
+
console.log(' pdd fix "login not saving incomeStatus" --open-pr');
|
|
157
|
+
console.log(' pdd-ai --provider=openai --task=analysis "login not saving incomeStatus"');
|
|
158
|
+
console.log('');
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(`❌ Unknown command: ${command}`);
|
|
163
|
+
console.log('Use: pdd help');
|
|
164
|
+
}
|