@open-product-primer/cli 2.1.0 → 2.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/dist/cli.js +2 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/init.js +2 -2
- package/dist/commands/ovw.js +1 -1
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.js +131 -0
- package/dist/lib/install-agent.js +78 -977
- package/dist/lib/measure.js +1 -3
- package/dist/lib/spec-delta.d.ts +30 -0
- package/dist/lib/spec-delta.js +216 -0
- package/dist/lib/validate-checks.d.ts +13 -0
- package/dist/lib/validate-checks.js +145 -0
- package/dist/lib/workflow-renderer.d.ts +19 -0
- package/dist/lib/workflow-renderer.js +103 -0
- package/dist/lib/workflow-schema.d.ts +37 -0
- package/dist/lib/workflow-schema.js +126 -0
- package/dist/workflows/archive.inline.md +10 -0
- package/dist/workflows/archive.schema.yaml +13 -0
- package/dist/workflows/archive.template.md +109 -0
- package/dist/workflows/bet.cursor-command.md +1 -0
- package/dist/workflows/bet.inline.md +13 -0
- package/dist/workflows/bet.schema.yaml +14 -0
- package/dist/workflows/bet.template.md +114 -0
- package/dist/workflows/context.schema.yaml +13 -0
- package/dist/workflows/context.template.md +34 -0
- package/dist/workflows/criteria.cursor-command.md +1 -0
- package/dist/workflows/criteria.inline.md +11 -0
- package/dist/workflows/criteria.schema.yaml +14 -0
- package/dist/workflows/criteria.template.md +52 -0
- package/dist/workflows/note.cursor-command.md +1 -0
- package/dist/workflows/note.inline.md +11 -0
- package/dist/workflows/note.schema.yaml +14 -0
- package/dist/workflows/note.template.md +66 -0
- package/dist/workflows/pdr.cursor-command.md +1 -0
- package/dist/workflows/pdr.inline.md +10 -0
- package/dist/workflows/pdr.schema.yaml +14 -0
- package/dist/workflows/pdr.template.md +67 -0
- package/dist/workflows/promote.native.template.md +29 -0
- package/dist/workflows/promote.none.template.md +25 -0
- package/dist/workflows/promote.openspec.template.md +40 -0
- package/dist/workflows/promote.schema.yaml +14 -0
- package/dist/workflows/review.cursor-command.md +1 -0
- package/dist/workflows/review.inline.md +11 -0
- package/dist/workflows/review.schema.yaml +14 -0
- package/dist/workflows/review.template.md +69 -0
- package/dist/workflows/sequence.cursor-command.md +12 -0
- package/dist/workflows/sequence.inline.md +10 -0
- package/dist/workflows/sequence.schema.yaml +13 -0
- package/dist/workflows/sequence.template.md +88 -0
- package/dist/workflows/spec-authoring.schema.yaml +13 -0
- package/dist/workflows/spec-authoring.template.md +82 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ const commander_1 = require("commander");
|
|
|
8
8
|
const init_1 = require("./commands/init");
|
|
9
9
|
const update_1 = require("./commands/update");
|
|
10
10
|
const doctor_1 = require("./commands/doctor");
|
|
11
|
+
const validate_1 = require("./commands/validate");
|
|
11
12
|
const migrate_1 = require("./commands/migrate");
|
|
12
13
|
const measure_1 = require("./commands/measure");
|
|
13
14
|
const ovw_1 = require("./commands/ovw");
|
|
@@ -21,6 +22,7 @@ program
|
|
|
21
22
|
program.addCommand((0, init_1.initCommand)());
|
|
22
23
|
program.addCommand((0, update_1.updateCommand)());
|
|
23
24
|
program.addCommand((0, doctor_1.doctorCommand)());
|
|
25
|
+
program.addCommand((0, validate_1.validateCommand)());
|
|
24
26
|
program.addCommand((0, migrate_1.migrateCommand)());
|
|
25
27
|
program.addCommand((0, measure_1.measureCommand)());
|
|
26
28
|
program.addCommand((0, ovw_1.ovwCommand)());
|
package/dist/commands/doctor.js
CHANGED
|
@@ -231,7 +231,7 @@ function doctorCommand() {
|
|
|
231
231
|
required: false,
|
|
232
232
|
});
|
|
233
233
|
// ── Discovery checks — warn if bet is missing discovery.md ───────────────
|
|
234
|
-
const betsDir = path.join(primerDir, 'bets');
|
|
234
|
+
const betsDir = path.join(primerDir, 'bets', 'pending');
|
|
235
235
|
if (fs.existsSync(betsDir)) {
|
|
236
236
|
const betEntries = fs.readdirSync(betsDir, { withFileTypes: true });
|
|
237
237
|
for (const entry of betEntries) {
|
package/dist/commands/init.js
CHANGED
|
@@ -64,7 +64,7 @@ function initCommand() {
|
|
|
64
64
|
const specFramework = await (0, install_agent_1.promptFrameworkSelection)(projectRoot);
|
|
65
65
|
const primerDir = path.join(projectRoot, 'oprim');
|
|
66
66
|
(0, scaffold_1.ensureDir)(path.join(primerDir, 'decisions'));
|
|
67
|
-
(0, scaffold_1.ensureDir)(path.join(primerDir, 'bets'));
|
|
67
|
+
(0, scaffold_1.ensureDir)(path.join(primerDir, 'bets', 'pending'));
|
|
68
68
|
(0, scaffold_1.ensureDir)(path.join(primerDir, 'reviews'));
|
|
69
69
|
(0, scaffold_1.ensureDir)(path.join(primerDir, 'notes'));
|
|
70
70
|
(0, scaffold_1.ensureDir)(path.join(primerDir, 'templates'));
|
|
@@ -94,7 +94,7 @@ function initCommand() {
|
|
|
94
94
|
(0, scaffold_1.writeFile)(path.join(primerDir, 'index.md'), (0, templates_1.indexTemplate)(projectName));
|
|
95
95
|
}
|
|
96
96
|
(0, scaffold_1.writeFileIfAbsent)(path.join(primerDir, 'decisions', '.gitkeep'), '');
|
|
97
|
-
(0, scaffold_1.writeFileIfAbsent)(path.join(primerDir, 'bets', '.gitkeep'), '');
|
|
97
|
+
(0, scaffold_1.writeFileIfAbsent)(path.join(primerDir, 'bets', 'pending', '.gitkeep'), '');
|
|
98
98
|
(0, scaffold_1.writeFileIfAbsent)(path.join(primerDir, 'reviews', '.gitkeep'), '');
|
|
99
99
|
(0, scaffold_1.writeFileIfAbsent)(path.join(primerDir, 'notes', '.gitkeep'), '');
|
|
100
100
|
console.log('\n' + chalk_1.default.green('✓') + ' oprim/ workspace created');
|
package/dist/commands/ovw.js
CHANGED
|
@@ -228,7 +228,7 @@ function ovwCommand() {
|
|
|
228
228
|
.action(() => {
|
|
229
229
|
const projectRoot = process.cwd();
|
|
230
230
|
const sequencePath = path.join(projectRoot, 'oprim', 'sequence.yaml');
|
|
231
|
-
const betsDir = path.join(projectRoot, 'oprim', 'bets');
|
|
231
|
+
const betsDir = path.join(projectRoot, 'oprim', 'bets', 'pending');
|
|
232
232
|
if (!fs.existsSync(sequencePath)) {
|
|
233
233
|
console.error("No oprim/sequence.yaml found — run 'oprim init' first");
|
|
234
234
|
process.exit(1);
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.validateCommand = validateCommand;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const integrity_1 = require("../lib/integrity");
|
|
45
|
+
const validate_checks_1 = require("../lib/validate-checks");
|
|
46
|
+
const spec_delta_1 = require("../lib/spec-delta");
|
|
47
|
+
function runChecks(projectRoot) {
|
|
48
|
+
const checks = [];
|
|
49
|
+
(0, integrity_1.checkSequenceIntegrity)(projectRoot, checks);
|
|
50
|
+
(0, integrity_1.checkSkillVersionDrift)(projectRoot, checks);
|
|
51
|
+
(0, validate_checks_1.checkBetDefinitionOfDone)(projectRoot, checks);
|
|
52
|
+
(0, validate_checks_1.checkSpecDeltaDrift)(projectRoot, checks);
|
|
53
|
+
(0, validate_checks_1.checkCrossBetConflicts)(projectRoot, checks);
|
|
54
|
+
return checks;
|
|
55
|
+
}
|
|
56
|
+
function printReport(checks) {
|
|
57
|
+
console.log(chalk_1.default.bold('oprim validate') + '\n');
|
|
58
|
+
for (const check of checks) {
|
|
59
|
+
const icon = check.pass ? chalk_1.default.green('✓') : check.required ? chalk_1.default.red('✗') : chalk_1.default.yellow('○');
|
|
60
|
+
const label = check.pass ? chalk_1.default.white(check.name) : chalk_1.default.gray(check.name);
|
|
61
|
+
const note = check.note ? chalk_1.default.dim(` (${check.note})`) : '';
|
|
62
|
+
console.log(` ${icon} ${label}${note}`);
|
|
63
|
+
}
|
|
64
|
+
const passed = checks.filter((c) => c.pass).length;
|
|
65
|
+
console.log(`\n${passed}/${checks.length} checks passed.`);
|
|
66
|
+
}
|
|
67
|
+
function runDiff(projectRoot, betIdInput) {
|
|
68
|
+
const betsDir = path.join(projectRoot, 'oprim', 'bets', 'pending');
|
|
69
|
+
const resolvedDir = (0, spec_delta_1.resolveBetDirectory)(betsDir, betIdInput);
|
|
70
|
+
if (!resolvedDir) {
|
|
71
|
+
console.error(chalk_1.default.red(`Bet ${betIdInput} was not found in oprim/bets/pending/.`));
|
|
72
|
+
process.exitCode = 1;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const specsDir = path.join(betsDir, resolvedDir, 'specs');
|
|
76
|
+
if (!fs.existsSync(specsDir)) {
|
|
77
|
+
console.log(`${resolvedDir} has no spec deltas to preview.`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const capEntries = fs.readdirSync(specsDir, { withFileTypes: true }).filter((e) => e.isDirectory());
|
|
81
|
+
const capsWithDelta = capEntries.filter((e) => fs.existsSync(path.join(specsDir, e.name, 'spec.md')));
|
|
82
|
+
if (capsWithDelta.length === 0) {
|
|
83
|
+
console.log(`${resolvedDir} has no spec deltas to preview.`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
for (const capEntry of capsWithDelta) {
|
|
87
|
+
const deltaContent = fs.readFileSync(path.join(specsDir, capEntry.name, 'spec.md'), 'utf-8');
|
|
88
|
+
const currentTruthPath = path.join(projectRoot, 'oprim', 'specs', capEntry.name, 'spec.md');
|
|
89
|
+
const currentTruth = fs.existsSync(currentTruthPath) ? fs.readFileSync(currentTruthPath, 'utf-8') : null;
|
|
90
|
+
console.log(chalk_1.default.bold(`═══ ${capEntry.name} ═══`));
|
|
91
|
+
try {
|
|
92
|
+
const result = (0, spec_delta_1.foldDelta)(currentTruth, deltaContent);
|
|
93
|
+
console.log(result.content);
|
|
94
|
+
for (const note of result.notes) {
|
|
95
|
+
console.log(chalk_1.default.yellow(` note: ${note}`));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error(chalk_1.default.red(err.message));
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
}
|
|
102
|
+
console.log('');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function validateCommand() {
|
|
106
|
+
return new commander_1.Command('validate')
|
|
107
|
+
.description('CI-gateable validation of oprim board and spec-delta integrity')
|
|
108
|
+
.option('--json', 'print machine-readable JSON instead of the human-readable report')
|
|
109
|
+
.option('--strict', 'exit non-zero if any check fails, not only required ones')
|
|
110
|
+
.option('--diff <bet-id>', "preview a bet's spec-delta merge result without writing files")
|
|
111
|
+
.action((opts) => {
|
|
112
|
+
const projectRoot = process.cwd();
|
|
113
|
+
if (opts.diff) {
|
|
114
|
+
runDiff(projectRoot, opts.diff);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const checks = runChecks(projectRoot);
|
|
118
|
+
if (opts.json) {
|
|
119
|
+
console.log(JSON.stringify({ checks }));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
printReport(checks);
|
|
123
|
+
}
|
|
124
|
+
const requiredFailed = checks.some((c) => c.required && !c.pass);
|
|
125
|
+
const anyFailed = checks.some((c) => !c.pass);
|
|
126
|
+
const shouldFail = opts.strict ? anyFailed : requiredFailed;
|
|
127
|
+
if (shouldFail) {
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|