pmp-gywd 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/LICENSE +27 -0
- package/README.md +567 -0
- package/bin/install.js +348 -0
- package/commands/gywd/add-phase.md +207 -0
- package/commands/gywd/anticipate.md +271 -0
- package/commands/gywd/bootstrap.md +336 -0
- package/commands/gywd/challenge.md +344 -0
- package/commands/gywd/check-drift.md +144 -0
- package/commands/gywd/complete-milestone.md +106 -0
- package/commands/gywd/consider-issues.md +202 -0
- package/commands/gywd/context.md +93 -0
- package/commands/gywd/create-roadmap.md +115 -0
- package/commands/gywd/deps.md +169 -0
- package/commands/gywd/digest.md +138 -0
- package/commands/gywd/discuss-milestone.md +47 -0
- package/commands/gywd/discuss-phase.md +60 -0
- package/commands/gywd/execute-plan.md +161 -0
- package/commands/gywd/extract-decisions.md +325 -0
- package/commands/gywd/health.md +150 -0
- package/commands/gywd/help.md +556 -0
- package/commands/gywd/history.md +278 -0
- package/commands/gywd/impact.md +317 -0
- package/commands/gywd/init.md +95 -0
- package/commands/gywd/insert-phase.md +227 -0
- package/commands/gywd/list-phase-assumptions.md +50 -0
- package/commands/gywd/map-codebase.md +84 -0
- package/commands/gywd/memory.md +159 -0
- package/commands/gywd/new-milestone.md +59 -0
- package/commands/gywd/new-project.md +315 -0
- package/commands/gywd/pause-work.md +123 -0
- package/commands/gywd/plan-fix.md +205 -0
- package/commands/gywd/plan-phase.md +93 -0
- package/commands/gywd/preview-plan.md +139 -0
- package/commands/gywd/profile.md +363 -0
- package/commands/gywd/progress.md +317 -0
- package/commands/gywd/remove-phase.md +338 -0
- package/commands/gywd/research-phase.md +91 -0
- package/commands/gywd/resume-work.md +40 -0
- package/commands/gywd/rollback.md +179 -0
- package/commands/gywd/status.md +42 -0
- package/commands/gywd/sync-github.md +234 -0
- package/commands/gywd/verify-work.md +71 -0
- package/commands/gywd/why.md +251 -0
- package/docs/COMMANDS.md +722 -0
- package/docs/CONTRIBUTING.md +342 -0
- package/docs/EXAMPLES.md +535 -0
- package/docs/GETTING-STARTED.md +262 -0
- package/docs/README.md +55 -0
- package/docs/RELEASING.md +159 -0
- package/get-your-work-done/core/agent-patterns.md +331 -0
- package/get-your-work-done/core/architecture.md +334 -0
- package/get-your-work-done/core/context-model-schema.json +154 -0
- package/get-your-work-done/core/decisions-schema.json +193 -0
- package/get-your-work-done/core/learning-state-schema.json +133 -0
- package/get-your-work-done/core/profile-schema.json +257 -0
- package/get-your-work-done/references/adaptive-decomposition.md +175 -0
- package/get-your-work-done/references/checkpoints.md +287 -0
- package/get-your-work-done/references/confidence-scoring.md +169 -0
- package/get-your-work-done/references/continuation-format.md +255 -0
- package/get-your-work-done/references/git-integration.md +254 -0
- package/get-your-work-done/references/plan-format.md +428 -0
- package/get-your-work-done/references/principles.md +157 -0
- package/get-your-work-done/references/questioning.md +162 -0
- package/get-your-work-done/references/research-pitfalls.md +215 -0
- package/get-your-work-done/references/scope-estimation.md +172 -0
- package/get-your-work-done/references/tdd.md +263 -0
- package/get-your-work-done/templates/codebase/architecture.md +255 -0
- package/get-your-work-done/templates/codebase/concerns.md +310 -0
- package/get-your-work-done/templates/codebase/conventions.md +307 -0
- package/get-your-work-done/templates/codebase/integrations.md +280 -0
- package/get-your-work-done/templates/codebase/stack.md +186 -0
- package/get-your-work-done/templates/codebase/structure.md +285 -0
- package/get-your-work-done/templates/codebase/testing.md +480 -0
- package/get-your-work-done/templates/config.json +18 -0
- package/get-your-work-done/templates/context.md +161 -0
- package/get-your-work-done/templates/continue-here.md +78 -0
- package/get-your-work-done/templates/discovery.md +146 -0
- package/get-your-work-done/templates/issues.md +32 -0
- package/get-your-work-done/templates/milestone-archive.md +123 -0
- package/get-your-work-done/templates/milestone-context.md +93 -0
- package/get-your-work-done/templates/milestone.md +115 -0
- package/get-your-work-done/templates/phase-prompt.md +303 -0
- package/get-your-work-done/templates/project.md +184 -0
- package/get-your-work-done/templates/research.md +529 -0
- package/get-your-work-done/templates/roadmap.md +196 -0
- package/get-your-work-done/templates/state.md +210 -0
- package/get-your-work-done/templates/summary.md +273 -0
- package/get-your-work-done/templates/uat-issues.md +143 -0
- package/get-your-work-done/workflows/complete-milestone.md +643 -0
- package/get-your-work-done/workflows/create-milestone.md +416 -0
- package/get-your-work-done/workflows/create-roadmap.md +481 -0
- package/get-your-work-done/workflows/discovery-phase.md +293 -0
- package/get-your-work-done/workflows/discuss-milestone.md +236 -0
- package/get-your-work-done/workflows/discuss-phase.md +247 -0
- package/get-your-work-done/workflows/execute-phase.md +1625 -0
- package/get-your-work-done/workflows/list-phase-assumptions.md +178 -0
- package/get-your-work-done/workflows/map-codebase.md +434 -0
- package/get-your-work-done/workflows/plan-phase.md +488 -0
- package/get-your-work-done/workflows/research-phase.md +436 -0
- package/get-your-work-done/workflows/resume-project.md +287 -0
- package/get-your-work-done/workflows/transition.md +580 -0
- package/get-your-work-done/workflows/verify-work.md +202 -0
- package/lib/automation/dependency-analyzer.js +635 -0
- package/lib/automation/doc-generator.js +643 -0
- package/lib/automation/index.js +42 -0
- package/lib/automation/test-generator.js +628 -0
- package/lib/context/context-analyzer.js +554 -0
- package/lib/context/context-cache.js +426 -0
- package/lib/context/context-predictor.js +622 -0
- package/lib/context/index.js +44 -0
- package/lib/memory/confidence-calibrator.js +484 -0
- package/lib/memory/feedback-collector.js +551 -0
- package/lib/memory/global-memory.js +465 -0
- package/lib/memory/index.js +75 -0
- package/lib/memory/pattern-aggregator.js +487 -0
- package/lib/memory/team-sync.js +501 -0
- package/lib/profile/index.js +24 -0
- package/lib/profile/pattern-learner.js +303 -0
- package/lib/profile/profile-manager.js +445 -0
- package/lib/questioning/index.js +49 -0
- package/lib/questioning/question-engine.js +311 -0
- package/lib/questioning/question-templates.js +315 -0
- package/lib/validators/command-validator.js +188 -0
- package/lib/validators/index.js +29 -0
- package/lib/validators/schema-validator.js +183 -0
- package/package.json +61 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates GYWD command markdown files for structure and content.
|
|
5
|
+
* Zero external dependencies.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Parse YAML frontmatter from markdown content
|
|
13
|
+
* @param {string} content - Markdown content
|
|
14
|
+
* @returns {object|null} Parsed frontmatter or null if not found
|
|
15
|
+
*/
|
|
16
|
+
function parseFrontmatter(content) {
|
|
17
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
18
|
+
if (!frontmatterMatch) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const frontmatter = {};
|
|
23
|
+
const lines = frontmatterMatch[1].split('\n');
|
|
24
|
+
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
const colonIndex = line.indexOf(':');
|
|
27
|
+
if (colonIndex > 0) {
|
|
28
|
+
const key = line.slice(0, colonIndex).trim();
|
|
29
|
+
let value = line.slice(colonIndex + 1).trim();
|
|
30
|
+
|
|
31
|
+
// Handle arrays (lines starting with -)
|
|
32
|
+
if (value === '') {
|
|
33
|
+
const arrayLines = [];
|
|
34
|
+
const startIndex = lines.indexOf(line);
|
|
35
|
+
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
36
|
+
if (lines[i].trim().startsWith('-')) {
|
|
37
|
+
arrayLines.push(lines[i].trim().slice(1).trim());
|
|
38
|
+
} else if (lines[i].trim() && !lines[i].startsWith(' ')) {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (arrayLines.length > 0) {
|
|
43
|
+
value = arrayLines;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
frontmatter[key] = value;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return frontmatter;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Required sections for a valid command file
|
|
56
|
+
*/
|
|
57
|
+
const REQUIRED_SECTIONS = ['objective'];
|
|
58
|
+
const PROCESS_SECTIONS = ['process', 'reference', 'output'];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validate a command file's structure
|
|
62
|
+
* @param {string} content - File content
|
|
63
|
+
* @param {string} fileName - File name for error messages
|
|
64
|
+
* @returns {{valid: boolean, errors: string[], warnings: string[], frontmatter: object|null}}
|
|
65
|
+
*/
|
|
66
|
+
function validateCommandStructure(content, _fileName) {
|
|
67
|
+
const errors = [];
|
|
68
|
+
const warnings = [];
|
|
69
|
+
|
|
70
|
+
// Check for frontmatter
|
|
71
|
+
const frontmatter = parseFrontmatter(content);
|
|
72
|
+
if (!frontmatter) {
|
|
73
|
+
warnings.push('Missing YAML frontmatter');
|
|
74
|
+
} else {
|
|
75
|
+
// Validate frontmatter fields
|
|
76
|
+
if (!frontmatter.name) {
|
|
77
|
+
errors.push('Frontmatter missing required field: name');
|
|
78
|
+
}
|
|
79
|
+
if (!frontmatter.description) {
|
|
80
|
+
errors.push('Frontmatter missing required field: description');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check for required sections
|
|
85
|
+
for (const section of REQUIRED_SECTIONS) {
|
|
86
|
+
const regex = new RegExp(`<${section}[^>]*>`, 'i');
|
|
87
|
+
if (!regex.test(content)) {
|
|
88
|
+
errors.push(`Missing required section: <${section}>`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check for at least one process-type section
|
|
93
|
+
const hasProcessSection = PROCESS_SECTIONS.some(section => {
|
|
94
|
+
const regex = new RegExp(`<${section}[^>]*>`, 'i');
|
|
95
|
+
return regex.test(content);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (!hasProcessSection) {
|
|
99
|
+
errors.push(`Missing <process>, <reference>, or <output> section`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
valid: errors.length === 0,
|
|
104
|
+
errors,
|
|
105
|
+
warnings,
|
|
106
|
+
frontmatter,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Extract workflow references from command content
|
|
112
|
+
* @param {string} content - File content
|
|
113
|
+
* @returns {string[]} Array of referenced workflow paths
|
|
114
|
+
*/
|
|
115
|
+
function extractWorkflowReferences(content) {
|
|
116
|
+
const references = [];
|
|
117
|
+
const refMatches = content.matchAll(/@~\/.claude\/([^\s\n]+)/g);
|
|
118
|
+
|
|
119
|
+
for (const match of refMatches) {
|
|
120
|
+
// Strip trailing punctuation
|
|
121
|
+
const refPath = match[1].replace(/[`.,)]+$/, '');
|
|
122
|
+
if (refPath.includes('get-your-work-done/workflows/')) {
|
|
123
|
+
references.push(path.basename(refPath));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return references;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Validate workflow references exist
|
|
132
|
+
* @param {string[]} references - Array of workflow file names
|
|
133
|
+
* @param {string} workflowsDir - Path to workflows directory
|
|
134
|
+
* @returns {string[]} Array of missing workflow files
|
|
135
|
+
*/
|
|
136
|
+
function validateWorkflowReferences(references, workflowsDir) {
|
|
137
|
+
const missing = [];
|
|
138
|
+
|
|
139
|
+
for (const ref of references) {
|
|
140
|
+
const workflowPath = path.join(workflowsDir, ref);
|
|
141
|
+
if (!fs.existsSync(workflowPath)) {
|
|
142
|
+
missing.push(ref);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return missing;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Validate a command file
|
|
151
|
+
* @param {string} filePath - Path to the command file
|
|
152
|
+
* @param {string} workflowsDir - Path to workflows directory
|
|
153
|
+
* @returns {{valid: boolean, errors: string[], warnings: string[]}}
|
|
154
|
+
*/
|
|
155
|
+
function validateCommandFile(filePath, workflowsDir) {
|
|
156
|
+
if (!fs.existsSync(filePath)) {
|
|
157
|
+
return { valid: false, errors: [`File not found: ${filePath}`], warnings: [] };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
161
|
+
const fileName = path.basename(filePath);
|
|
162
|
+
|
|
163
|
+
// Validate structure
|
|
164
|
+
const structureResult = validateCommandStructure(content, fileName);
|
|
165
|
+
|
|
166
|
+
// Validate workflow references
|
|
167
|
+
const references = extractWorkflowReferences(content);
|
|
168
|
+
const missingWorkflows = validateWorkflowReferences(references, workflowsDir);
|
|
169
|
+
|
|
170
|
+
const errors = [...structureResult.errors];
|
|
171
|
+
for (const missing of missingWorkflows) {
|
|
172
|
+
errors.push(`Referenced workflow not found: ${missing}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
valid: errors.length === 0,
|
|
177
|
+
errors,
|
|
178
|
+
warnings: structureResult.warnings,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
module.exports = {
|
|
183
|
+
parseFrontmatter,
|
|
184
|
+
validateCommandStructure,
|
|
185
|
+
extractWorkflowReferences,
|
|
186
|
+
validateWorkflowReferences,
|
|
187
|
+
validateCommandFile,
|
|
188
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GYWD Validators
|
|
3
|
+
*
|
|
4
|
+
* Central export for all validation modules.
|
|
5
|
+
* Zero external dependencies.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const schemaValidator = require('./schema-validator');
|
|
9
|
+
const commandValidator = require('./command-validator');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
// Schema validation
|
|
13
|
+
validateJsonSyntax: schemaValidator.validateJsonSyntax,
|
|
14
|
+
validateSchemaStructure: schemaValidator.validateSchemaStructure,
|
|
15
|
+
validateDataAgainstSchema: schemaValidator.validateDataAgainstSchema,
|
|
16
|
+
loadSchema: schemaValidator.loadSchema,
|
|
17
|
+
validateFile: schemaValidator.validateFile,
|
|
18
|
+
|
|
19
|
+
// Command validation
|
|
20
|
+
parseFrontmatter: commandValidator.parseFrontmatter,
|
|
21
|
+
validateCommandStructure: commandValidator.validateCommandStructure,
|
|
22
|
+
extractWorkflowReferences: commandValidator.extractWorkflowReferences,
|
|
23
|
+
validateWorkflowReferences: commandValidator.validateWorkflowReferences,
|
|
24
|
+
validateCommandFile: commandValidator.validateCommandFile,
|
|
25
|
+
|
|
26
|
+
// Namespaced exports
|
|
27
|
+
schema: schemaValidator,
|
|
28
|
+
command: commandValidator,
|
|
29
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates JSON schemas and data files against schemas.
|
|
5
|
+
* Zero external dependencies - uses native JSON parsing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validate JSON syntax
|
|
12
|
+
* @param {string} content - JSON string to validate
|
|
13
|
+
* @returns {{valid: boolean, error?: string, data?: object}}
|
|
14
|
+
*/
|
|
15
|
+
function validateJsonSyntax(content) {
|
|
16
|
+
try {
|
|
17
|
+
const data = JSON.parse(content);
|
|
18
|
+
return { valid: true, data };
|
|
19
|
+
} catch (error) {
|
|
20
|
+
return { valid: false, error: error.message };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Validate schema structure (basic validation without external deps)
|
|
26
|
+
* @param {object} schema - The schema object to validate
|
|
27
|
+
* @returns {string[]} Array of issues found
|
|
28
|
+
*/
|
|
29
|
+
function validateSchemaStructure(schema) {
|
|
30
|
+
const issues = [];
|
|
31
|
+
|
|
32
|
+
if (!schema.$schema) {
|
|
33
|
+
issues.push('Missing $schema declaration');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!schema.title) {
|
|
37
|
+
issues.push('Missing title');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!schema.type && !schema.properties && !schema.definitions) {
|
|
41
|
+
issues.push('Schema has no type, properties, or definitions');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Check for valid type if present
|
|
45
|
+
const validTypes = ['object', 'array', 'string', 'number', 'boolean', 'null', 'integer'];
|
|
46
|
+
if (schema.type && !validTypes.includes(schema.type)) {
|
|
47
|
+
issues.push(`Invalid type: ${schema.type}`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check required is an array if present
|
|
51
|
+
if (schema.required && !Array.isArray(schema.required)) {
|
|
52
|
+
issues.push('Required must be an array');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check properties is an object if present
|
|
56
|
+
if (schema.properties && typeof schema.properties !== 'object') {
|
|
57
|
+
issues.push('Properties must be an object');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return issues;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Validate data against a schema (basic validation)
|
|
65
|
+
* @param {object} data - The data to validate
|
|
66
|
+
* @param {object} schema - The schema to validate against
|
|
67
|
+
* @returns {{valid: boolean, errors: string[]}}
|
|
68
|
+
*/
|
|
69
|
+
function validateDataAgainstSchema(data, schema) {
|
|
70
|
+
const errors = [];
|
|
71
|
+
|
|
72
|
+
// Type validation
|
|
73
|
+
if (schema.type) {
|
|
74
|
+
const actualType = Array.isArray(data) ? 'array' : typeof data;
|
|
75
|
+
if (schema.type === 'integer') {
|
|
76
|
+
if (typeof data !== 'number' || !Number.isInteger(data)) {
|
|
77
|
+
errors.push(`Expected integer, got ${typeof data}`);
|
|
78
|
+
}
|
|
79
|
+
} else if (actualType !== schema.type) {
|
|
80
|
+
errors.push(`Expected ${schema.type}, got ${actualType}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Required properties validation
|
|
85
|
+
if (schema.required && schema.type === 'object') {
|
|
86
|
+
for (const prop of schema.required) {
|
|
87
|
+
if (!(prop in data)) {
|
|
88
|
+
errors.push(`Missing required property: ${prop}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Enum validation
|
|
94
|
+
if (schema.enum && !schema.enum.includes(data)) {
|
|
95
|
+
errors.push(`Value must be one of: ${schema.enum.join(', ')}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Nested properties validation
|
|
99
|
+
if (schema.properties && typeof data === 'object' && data !== null) {
|
|
100
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
101
|
+
if (key in data) {
|
|
102
|
+
const result = validateDataAgainstSchema(data[key], propSchema);
|
|
103
|
+
for (const err of result.errors) {
|
|
104
|
+
errors.push(`${key}: ${err}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Array items validation
|
|
111
|
+
if (schema.items && Array.isArray(data)) {
|
|
112
|
+
data.forEach((item, index) => {
|
|
113
|
+
const result = validateDataAgainstSchema(item, schema.items);
|
|
114
|
+
for (const err of result.errors) {
|
|
115
|
+
errors.push(`[${index}]: ${err}`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return { valid: errors.length === 0, errors };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Load and validate a schema file
|
|
125
|
+
* @param {string} schemaPath - Path to the schema file
|
|
126
|
+
* @returns {{valid: boolean, schema?: object, errors: string[]}}
|
|
127
|
+
*/
|
|
128
|
+
function loadSchema(schemaPath) {
|
|
129
|
+
if (!fs.existsSync(schemaPath)) {
|
|
130
|
+
return { valid: false, errors: [`Schema file not found: ${schemaPath}`] };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const content = fs.readFileSync(schemaPath, 'utf8');
|
|
134
|
+
const parseResult = validateJsonSyntax(content);
|
|
135
|
+
|
|
136
|
+
if (!parseResult.valid) {
|
|
137
|
+
return { valid: false, errors: [`Invalid JSON: ${parseResult.error}`] };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const structureIssues = validateSchemaStructure(parseResult.data);
|
|
141
|
+
if (structureIssues.length > 0) {
|
|
142
|
+
return { valid: false, schema: parseResult.data, errors: structureIssues };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return { valid: true, schema: parseResult.data, errors: [] };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Validate a data file against a schema file
|
|
150
|
+
* @param {string} dataPath - Path to the data file
|
|
151
|
+
* @param {string} schemaPath - Path to the schema file
|
|
152
|
+
* @returns {{valid: boolean, errors: string[]}}
|
|
153
|
+
*/
|
|
154
|
+
function validateFile(dataPath, schemaPath) {
|
|
155
|
+
// Load schema
|
|
156
|
+
const schemaResult = loadSchema(schemaPath);
|
|
157
|
+
if (!schemaResult.valid) {
|
|
158
|
+
return { valid: false, errors: schemaResult.errors.map(e => `Schema: ${e}`) };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Load data
|
|
162
|
+
if (!fs.existsSync(dataPath)) {
|
|
163
|
+
return { valid: false, errors: [`Data file not found: ${dataPath}`] };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const content = fs.readFileSync(dataPath, 'utf8');
|
|
167
|
+
const parseResult = validateJsonSyntax(content);
|
|
168
|
+
|
|
169
|
+
if (!parseResult.valid) {
|
|
170
|
+
return { valid: false, errors: [`Invalid JSON: ${parseResult.error}`] };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Validate data against schema
|
|
174
|
+
return validateDataAgainstSchema(parseResult.data, schemaResult.schema);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = {
|
|
178
|
+
validateJsonSyntax,
|
|
179
|
+
validateSchemaStructure,
|
|
180
|
+
validateDataAgainstSchema,
|
|
181
|
+
loadSchema,
|
|
182
|
+
validateFile,
|
|
183
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pmp-gywd",
|
|
3
|
+
"version": "3.3.0",
|
|
4
|
+
"description": "PMP (GYWD - Get Your Work Done) - Decision-aware, context-engineered development system for Claude Code. Understands WHY code exists, not just WHAT it does.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"pmp-gywd": "bin/install.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"commands",
|
|
11
|
+
"docs",
|
|
12
|
+
"get-your-work-done",
|
|
13
|
+
"lib"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "jest",
|
|
17
|
+
"test:watch": "jest --watch",
|
|
18
|
+
"test:coverage": "jest --coverage",
|
|
19
|
+
"test:ci": "jest --ci --coverage --reporters=default --reporters=jest-junit",
|
|
20
|
+
"lint": "eslint bin lib scripts tests --ext .js",
|
|
21
|
+
"lint:fix": "eslint bin lib scripts tests --ext .js --fix",
|
|
22
|
+
"validate:schemas": "node scripts/validate-schemas.js",
|
|
23
|
+
"validate:commands": "node scripts/validate-commands.js",
|
|
24
|
+
"validate:all": "npm run validate:schemas && npm run validate:commands",
|
|
25
|
+
"generate:tests": "node scripts/generate-tests.js",
|
|
26
|
+
"generate:docs": "node scripts/generate-docs.js",
|
|
27
|
+
"analyze:deps": "node scripts/analyze-dependencies.js",
|
|
28
|
+
"precommit": "npm run lint && npm run validate:all && npm test",
|
|
29
|
+
"prepublishOnly": "npm run test:ci && npm run validate:all",
|
|
30
|
+
"release": "npm run lint && npm run validate:all && npm test"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"claude",
|
|
34
|
+
"claude-code",
|
|
35
|
+
"ai",
|
|
36
|
+
"meta-prompting",
|
|
37
|
+
"context-engineering",
|
|
38
|
+
"spec-driven-development",
|
|
39
|
+
"decision-intelligence",
|
|
40
|
+
"pmp",
|
|
41
|
+
"gywd"
|
|
42
|
+
],
|
|
43
|
+
"author": "cyberbloke9",
|
|
44
|
+
"license": "MIT",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/cyberbloke9/pmp-gywd.git"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/cyberbloke9/pmp-gywd/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/cyberbloke9/pmp-gywd#readme",
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=16.7.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"eslint": "^8.57.0",
|
|
58
|
+
"jest": "^29.7.0",
|
|
59
|
+
"jest-junit": "^16.0.0"
|
|
60
|
+
}
|
|
61
|
+
}
|