@spekn/cli 1.0.0 → 1.0.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/README.md +58 -0
- package/dist/main.js +3707 -611
- package/dist/tui/index.mjs +2 -2
- package/package.json +29 -12
- package/dist/__tests__/export-cli.test.d.ts +0 -1
- package/dist/__tests__/export-cli.test.js +0 -70
- package/dist/__tests__/tui-args-policy.test.d.ts +0 -1
- package/dist/__tests__/tui-args-policy.test.js +0 -50
- package/dist/acp-S2MHZOAD.mjs +0 -23
- package/dist/acp-UCCI44JY.mjs +0 -25
- package/dist/auth/credentials-store.d.ts +0 -2
- package/dist/auth/credentials-store.js +0 -5
- package/dist/auth/device-flow.d.ts +0 -36
- package/dist/auth/device-flow.js +0 -189
- package/dist/auth/jwt.d.ts +0 -1
- package/dist/auth/jwt.js +0 -6
- package/dist/auth/session.d.ts +0 -67
- package/dist/auth/session.js +0 -86
- package/dist/auth-login.d.ts +0 -34
- package/dist/auth-login.js +0 -202
- package/dist/auth-logout.d.ts +0 -25
- package/dist/auth-logout.js +0 -115
- package/dist/auth-status.d.ts +0 -24
- package/dist/auth-status.js +0 -109
- package/dist/backlog-generate.d.ts +0 -11
- package/dist/backlog-generate.js +0 -308
- package/dist/backlog-health.d.ts +0 -11
- package/dist/backlog-health.js +0 -287
- package/dist/bridge-login.d.ts +0 -40
- package/dist/bridge-login.js +0 -277
- package/dist/chunk-3PAYRI4G.mjs +0 -2428
- package/dist/chunk-M4CS3A25.mjs +0 -2426
- package/dist/commands/auth/login.d.ts +0 -30
- package/dist/commands/auth/login.js +0 -164
- package/dist/commands/auth/logout.d.ts +0 -25
- package/dist/commands/auth/logout.js +0 -115
- package/dist/commands/auth/status.d.ts +0 -24
- package/dist/commands/auth/status.js +0 -109
- package/dist/commands/backlog/generate.d.ts +0 -11
- package/dist/commands/backlog/generate.js +0 -308
- package/dist/commands/backlog/health.d.ts +0 -11
- package/dist/commands/backlog/health.js +0 -287
- package/dist/commands/bridge/login.d.ts +0 -36
- package/dist/commands/bridge/login.js +0 -258
- package/dist/commands/export.d.ts +0 -35
- package/dist/commands/export.js +0 -485
- package/dist/commands/marketplace-export.d.ts +0 -21
- package/dist/commands/marketplace-export.js +0 -214
- package/dist/commands/project-clean.d.ts +0 -1
- package/dist/commands/project-clean.js +0 -126
- package/dist/commands/repo/common.d.ts +0 -105
- package/dist/commands/repo/common.js +0 -775
- package/dist/commands/repo/detach.d.ts +0 -2
- package/dist/commands/repo/detach.js +0 -120
- package/dist/commands/repo/register.d.ts +0 -21
- package/dist/commands/repo/register.js +0 -175
- package/dist/commands/repo/sync.d.ts +0 -22
- package/dist/commands/repo/sync.js +0 -873
- package/dist/commands/skills-import-local.d.ts +0 -16
- package/dist/commands/skills-import-local.js +0 -352
- package/dist/commands/spec/drift-check.d.ts +0 -3
- package/dist/commands/spec/drift-check.js +0 -186
- package/dist/commands/spec/frontmatter.d.ts +0 -11
- package/dist/commands/spec/frontmatter.js +0 -219
- package/dist/commands/spec/lint.d.ts +0 -11
- package/dist/commands/spec/lint.js +0 -499
- package/dist/commands/spec/parse.d.ts +0 -11
- package/dist/commands/spec/parse.js +0 -162
- package/dist/export.d.ts +0 -35
- package/dist/export.js +0 -485
- package/dist/main.d.ts +0 -1
- package/dist/marketplace-export.d.ts +0 -21
- package/dist/marketplace-export.js +0 -214
- package/dist/project-clean.d.ts +0 -1
- package/dist/project-clean.js +0 -126
- package/dist/project-context.d.ts +0 -99
- package/dist/project-context.js +0 -376
- package/dist/repo-common.d.ts +0 -101
- package/dist/repo-common.js +0 -671
- package/dist/repo-detach.d.ts +0 -2
- package/dist/repo-detach.js +0 -102
- package/dist/repo-ingest.d.ts +0 -29
- package/dist/repo-ingest.js +0 -305
- package/dist/repo-register.d.ts +0 -21
- package/dist/repo-register.js +0 -175
- package/dist/repo-sync.d.ts +0 -16
- package/dist/repo-sync.js +0 -152
- package/dist/resources/prompt-loader.d.ts +0 -1
- package/dist/resources/prompt-loader.js +0 -62
- package/dist/skills-import-local.d.ts +0 -16
- package/dist/skills-import-local.js +0 -352
- package/dist/spec-drift-check.d.ts +0 -3
- package/dist/spec-drift-check.js +0 -186
- package/dist/spec-frontmatter.d.ts +0 -11
- package/dist/spec-frontmatter.js +0 -219
- package/dist/spec-lint.d.ts +0 -11
- package/dist/spec-lint.js +0 -499
- package/dist/spec-parse.d.ts +0 -11
- package/dist/spec-parse.js +0 -162
- package/dist/stubs/dotenv.d.ts +0 -5
- package/dist/stubs/dotenv.js +0 -6
- package/dist/stubs/typeorm.d.ts +0 -22
- package/dist/stubs/typeorm.js +0 -28
- package/dist/tui/app.d.ts +0 -7
- package/dist/tui/app.js +0 -122
- package/dist/tui/args.d.ts +0 -8
- package/dist/tui/args.js +0 -57
- package/dist/tui/capabilities/policy.d.ts +0 -7
- package/dist/tui/capabilities/policy.js +0 -64
- package/dist/tui/components/frame.d.ts +0 -8
- package/dist/tui/components/frame.js +0 -8
- package/dist/tui/components/status-bar.d.ts +0 -8
- package/dist/tui/components/status-bar.js +0 -8
- package/dist/tui/index.d.ts +0 -2
- package/dist/tui/index.js +0 -23
- package/dist/tui/keymap/use-global-keymap.d.ts +0 -19
- package/dist/tui/keymap/use-global-keymap.js +0 -82
- package/dist/tui/navigation/nav-items.d.ts +0 -3
- package/dist/tui/navigation/nav-items.js +0 -18
- package/dist/tui/screens/bridge.d.ts +0 -8
- package/dist/tui/screens/bridge.js +0 -19
- package/dist/tui/screens/decisions.d.ts +0 -5
- package/dist/tui/screens/decisions.js +0 -28
- package/dist/tui/screens/export.d.ts +0 -5
- package/dist/tui/screens/export.js +0 -16
- package/dist/tui/screens/home.d.ts +0 -5
- package/dist/tui/screens/home.js +0 -33
- package/dist/tui/screens/locked.d.ts +0 -5
- package/dist/tui/screens/locked.js +0 -9
- package/dist/tui/screens/specs.d.ts +0 -5
- package/dist/tui/screens/specs.js +0 -31
- package/dist/tui/services/client.d.ts +0 -1
- package/dist/tui/services/client.js +0 -18
- package/dist/tui/services/context-service.d.ts +0 -19
- package/dist/tui/services/context-service.js +0 -246
- package/dist/tui/shared-enums.d.ts +0 -16
- package/dist/tui/shared-enums.js +0 -19
- package/dist/tui/state/use-app-state.d.ts +0 -35
- package/dist/tui/state/use-app-state.js +0 -177
- package/dist/tui/types.d.ts +0 -77
- package/dist/tui/types.js +0 -2
- package/dist/tui-bundle.d.ts +0 -1
- package/dist/tui-bundle.js +0 -5
- package/dist/tui-entry.mjs +0 -1407
- package/dist/utils/cli-runtime.d.ts +0 -5
- package/dist/utils/cli-runtime.js +0 -22
- package/dist/utils/help-error.d.ts +0 -7
- package/dist/utils/help-error.js +0 -14
- package/dist/utils/interaction.d.ts +0 -19
- package/dist/utils/interaction.js +0 -93
- package/dist/utils/structured-log.d.ts +0 -7
- package/dist/utils/structured-log.js +0 -112
- package/dist/utils/trpc-url.d.ts +0 -4
- package/dist/utils/trpc-url.js +0 -15
package/dist/spec-drift-check.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.main = main;
|
|
5
|
-
const shared_1 = require("@spekn/shared");
|
|
6
|
-
const cli_runtime_1 = require("./utils/cli-runtime");
|
|
7
|
-
async function columnExists(tableName, columnName) {
|
|
8
|
-
const rows = (await shared_1.AppDataSource.query(`
|
|
9
|
-
SELECT 1
|
|
10
|
-
FROM information_schema.columns
|
|
11
|
-
WHERE table_schema = current_schema()
|
|
12
|
-
AND table_name = $1
|
|
13
|
-
AND column_name = $2
|
|
14
|
-
LIMIT 1
|
|
15
|
-
`, [tableName, columnName]));
|
|
16
|
-
return rows.length > 0;
|
|
17
|
-
}
|
|
18
|
-
function parseArgs(args) {
|
|
19
|
-
const options = {};
|
|
20
|
-
for (const arg of args) {
|
|
21
|
-
if (arg.startsWith("--project-id=")) {
|
|
22
|
-
options.projectId = arg.split("=")[1];
|
|
23
|
-
}
|
|
24
|
-
else if (arg.startsWith("--spec-id=")) {
|
|
25
|
-
options.specId = arg.split("=")[1];
|
|
26
|
-
}
|
|
27
|
-
else if (arg === "--json" || arg === "-j") {
|
|
28
|
-
options.json = true;
|
|
29
|
-
}
|
|
30
|
-
else if (arg === "--verbose" || arg === "-v") {
|
|
31
|
-
options.verbose = true;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return options;
|
|
35
|
-
}
|
|
36
|
-
function printHelp() {
|
|
37
|
-
console.log(`
|
|
38
|
-
spec-drift-check - Fail when task/spec bindings drift
|
|
39
|
-
|
|
40
|
-
USAGE:
|
|
41
|
-
npm run spec-drift-check [OPTIONS]
|
|
42
|
-
|
|
43
|
-
OPTIONS:
|
|
44
|
-
--project-id=<id> Filter by project ID
|
|
45
|
-
--spec-id=<id> Filter by specification ID
|
|
46
|
-
-j, --json Output JSON
|
|
47
|
-
-v, --verbose Print individual drift rows
|
|
48
|
-
-h, --help Show this help message
|
|
49
|
-
`);
|
|
50
|
-
}
|
|
51
|
-
async function main(argv) {
|
|
52
|
-
const args = argv ?? process.argv.slice(2);
|
|
53
|
-
if ((0, cli_runtime_1.hasHelpFlag)(args)) {
|
|
54
|
-
printHelp();
|
|
55
|
-
return 0;
|
|
56
|
-
}
|
|
57
|
-
const options = parseArgs(args);
|
|
58
|
-
const hasDbConfig = Boolean(process.env.DATABASE_URL ||
|
|
59
|
-
process.env.DB_HOST ||
|
|
60
|
-
process.env.DB_NAME ||
|
|
61
|
-
process.env.POSTGRES_HOST);
|
|
62
|
-
if (!hasDbConfig) {
|
|
63
|
-
console.log("spec-drift-check: skipped (no database configuration found in environment).");
|
|
64
|
-
return 0;
|
|
65
|
-
}
|
|
66
|
-
await shared_1.AppDataSource.initialize();
|
|
67
|
-
try {
|
|
68
|
-
const hasTaskSpecVersion = await columnExists("task", "specVersion");
|
|
69
|
-
const hasTaskSpecRef = await columnExists("task", "specRef");
|
|
70
|
-
const hasSpecVersion = await columnExists("specification", "version");
|
|
71
|
-
const hasSpecRef = await columnExists("specification", "specRef");
|
|
72
|
-
const filters = [];
|
|
73
|
-
const params = [];
|
|
74
|
-
if (options.projectId) {
|
|
75
|
-
params.push(options.projectId);
|
|
76
|
-
filters.push(`t."projectId" = $${params.length}`);
|
|
77
|
-
}
|
|
78
|
-
if (options.specId) {
|
|
79
|
-
params.push(options.specId);
|
|
80
|
-
filters.push(`t."specificationId" = $${params.length}`);
|
|
81
|
-
}
|
|
82
|
-
const whereClause = filters.length > 0 ? `WHERE ${filters.join(" AND ")}` : "";
|
|
83
|
-
const taskSpecVersionExpr = hasTaskSpecVersion
|
|
84
|
-
? `t."specVersion"`
|
|
85
|
-
: `NULL::text`;
|
|
86
|
-
const taskSpecRefExpr = hasTaskSpecRef ? `t."specRef"` : `NULL::text`;
|
|
87
|
-
const currentSpecVersionExpr = hasSpecVersion
|
|
88
|
-
? `s."version"`
|
|
89
|
-
: `NULL::text`;
|
|
90
|
-
const currentSpecRefExpr = hasSpecRef ? `s."specRef"` : `NULL::text`;
|
|
91
|
-
const rows = (await shared_1.AppDataSource.query(`
|
|
92
|
-
SELECT
|
|
93
|
-
t."id" AS "taskId",
|
|
94
|
-
t."title" AS "taskTitle",
|
|
95
|
-
t."specificationId" AS "specificationId",
|
|
96
|
-
s."id" AS "specId",
|
|
97
|
-
s."title" AS "specTitle",
|
|
98
|
-
${taskSpecVersionExpr} AS "taskSpecVersion",
|
|
99
|
-
${taskSpecRefExpr} AS "taskSpecRef",
|
|
100
|
-
${currentSpecVersionExpr} AS "currentSpecVersion",
|
|
101
|
-
${currentSpecRefExpr} AS "currentSpecRef"
|
|
102
|
-
FROM "task" t
|
|
103
|
-
LEFT JOIN "specification" s ON s."id" = t."specificationId"
|
|
104
|
-
${whereClause}
|
|
105
|
-
`, params));
|
|
106
|
-
const driftItems = rows
|
|
107
|
-
.map((row) => {
|
|
108
|
-
const driftReasons = [];
|
|
109
|
-
if (!row.specId) {
|
|
110
|
-
driftReasons.push("spec_missing");
|
|
111
|
-
}
|
|
112
|
-
if (!hasTaskSpecVersion || !row.taskSpecVersion) {
|
|
113
|
-
driftReasons.push("task_spec_version_missing");
|
|
114
|
-
}
|
|
115
|
-
if (!hasTaskSpecRef || !row.taskSpecRef) {
|
|
116
|
-
driftReasons.push("task_spec_ref_missing");
|
|
117
|
-
}
|
|
118
|
-
if (!hasSpecRef) {
|
|
119
|
-
driftReasons.push("spec_ref_missing");
|
|
120
|
-
}
|
|
121
|
-
if (row.taskSpecVersion &&
|
|
122
|
-
row.currentSpecVersion &&
|
|
123
|
-
row.taskSpecVersion !== row.currentSpecVersion) {
|
|
124
|
-
driftReasons.push("spec_version_drift");
|
|
125
|
-
}
|
|
126
|
-
if (row.taskSpecRef &&
|
|
127
|
-
row.currentSpecRef &&
|
|
128
|
-
row.taskSpecRef !== row.currentSpecRef) {
|
|
129
|
-
driftReasons.push("spec_ref_drift");
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
taskId: row.taskId,
|
|
133
|
-
taskTitle: row.taskTitle,
|
|
134
|
-
specificationId: row.specificationId,
|
|
135
|
-
specTitle: row.specTitle || "<missing specification>",
|
|
136
|
-
taskSpecVersion: row.taskSpecVersion,
|
|
137
|
-
currentSpecVersion: row.currentSpecVersion,
|
|
138
|
-
taskSpecRef: row.taskSpecRef,
|
|
139
|
-
currentSpecRef: row.currentSpecRef,
|
|
140
|
-
driftReasons,
|
|
141
|
-
};
|
|
142
|
-
})
|
|
143
|
-
.filter((item) => item.driftReasons.length > 0);
|
|
144
|
-
const summary = {
|
|
145
|
-
checkedTasks: rows.length,
|
|
146
|
-
driftedTasks: driftItems.length,
|
|
147
|
-
versionDrift: driftItems.filter((d) => d.driftReasons.includes("spec_version_drift")).length,
|
|
148
|
-
refDrift: driftItems.filter((d) => d.driftReasons.includes("spec_ref_drift")).length,
|
|
149
|
-
missingBindings: driftItems.filter((d) => d.driftReasons.includes("task_spec_ref_missing") ||
|
|
150
|
-
d.driftReasons.includes("task_spec_version_missing")).length,
|
|
151
|
-
missingSpecs: driftItems.filter((d) => d.driftReasons.includes("spec_missing")).length,
|
|
152
|
-
};
|
|
153
|
-
if (options.json) {
|
|
154
|
-
console.log(JSON.stringify({ summary, items: driftItems }, null, 2));
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
console.log("Spec Drift Check");
|
|
158
|
-
console.log(`Checked tasks: ${summary.checkedTasks}`);
|
|
159
|
-
console.log(`Drifted tasks: ${summary.driftedTasks}`);
|
|
160
|
-
console.log(`Version drift: ${summary.versionDrift}`);
|
|
161
|
-
console.log(`Ref drift: ${summary.refDrift}`);
|
|
162
|
-
console.log(`Missing bindings: ${summary.missingBindings}`);
|
|
163
|
-
console.log(`Missing specs: ${summary.missingSpecs}`);
|
|
164
|
-
if (options.verbose && driftItems.length > 0) {
|
|
165
|
-
console.log("\nDrift items:");
|
|
166
|
-
for (const item of driftItems) {
|
|
167
|
-
console.log(`- ${item.taskTitle} (${item.taskId})`);
|
|
168
|
-
console.log(` Spec: ${item.specTitle} (${item.specificationId})`);
|
|
169
|
-
console.log(` Version: ${item.taskSpecVersion ?? "<missing>"} -> ${item.currentSpecVersion ?? "<missing>"}`);
|
|
170
|
-
console.log(` Ref: ${item.taskSpecRef ?? "<missing>"} -> ${item.currentSpecRef ?? "<missing>"}`);
|
|
171
|
-
console.log(` Reasons: ${item.driftReasons.join(", ")}`);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (driftItems.length > 0) {
|
|
176
|
-
return 2;
|
|
177
|
-
}
|
|
178
|
-
return 0;
|
|
179
|
-
}
|
|
180
|
-
finally {
|
|
181
|
-
await shared_1.AppDataSource.destroy();
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if (require.main === module) {
|
|
185
|
-
void (0, cli_runtime_1.runCliMain)(main, { errorPrefix: "spec-drift-check failed" });
|
|
186
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* spec-frontmatter CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Parse and validate YAML frontmatter from a specification file.
|
|
6
|
-
*
|
|
7
|
-
* Usage: spekn spec frontmatter <spec-file-path> [OPTIONS]
|
|
8
|
-
* Example: spekn spec frontmatter specs/SPECIFICATION.md
|
|
9
|
-
*/
|
|
10
|
-
declare function main(argv?: string[]): number;
|
|
11
|
-
export { main };
|
package/dist/spec-frontmatter.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* spec-frontmatter CLI Tool
|
|
5
|
-
*
|
|
6
|
-
* Parse and validate YAML frontmatter from a specification file.
|
|
7
|
-
*
|
|
8
|
-
* Usage: spekn spec frontmatter <spec-file-path> [OPTIONS]
|
|
9
|
-
* Example: spekn spec frontmatter specs/SPECIFICATION.md
|
|
10
|
-
*/
|
|
11
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
-
if (k2 === undefined) k2 = k;
|
|
13
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
-
}
|
|
17
|
-
Object.defineProperty(o, k2, desc);
|
|
18
|
-
}) : (function(o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
o[k2] = m[k];
|
|
21
|
-
}));
|
|
22
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
-
}) : function(o, v) {
|
|
25
|
-
o["default"] = v;
|
|
26
|
-
});
|
|
27
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
-
var ownKeys = function(o) {
|
|
29
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
-
var ar = [];
|
|
31
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
-
return ar;
|
|
33
|
-
};
|
|
34
|
-
return ownKeys(o);
|
|
35
|
-
};
|
|
36
|
-
return function (mod) {
|
|
37
|
-
if (mod && mod.__esModule) return mod;
|
|
38
|
-
var result = {};
|
|
39
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
-
__setModuleDefault(result, mod);
|
|
41
|
-
return result;
|
|
42
|
-
};
|
|
43
|
-
})();
|
|
44
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.main = main;
|
|
46
|
-
const fs = __importStar(require("fs"));
|
|
47
|
-
const path = __importStar(require("path"));
|
|
48
|
-
const shared_1 = require("@spekn/shared");
|
|
49
|
-
const cli_runtime_1 = require("./utils/cli-runtime");
|
|
50
|
-
function parseArgs(args) {
|
|
51
|
-
const options = {};
|
|
52
|
-
let filePath;
|
|
53
|
-
for (let i = 0; i < args.length; i++) {
|
|
54
|
-
const arg = args[i];
|
|
55
|
-
if (arg === "--verbose" || arg === "-v") {
|
|
56
|
-
options.verbose = true;
|
|
57
|
-
}
|
|
58
|
-
else if (arg === "--json" || arg === "-j") {
|
|
59
|
-
options.json = true;
|
|
60
|
-
}
|
|
61
|
-
else if (arg === "--validate-only") {
|
|
62
|
-
options.validateOnly = true;
|
|
63
|
-
}
|
|
64
|
-
else if (arg === "--auto-generate") {
|
|
65
|
-
options.autoGenerate = true;
|
|
66
|
-
}
|
|
67
|
-
else if (!arg.startsWith("-")) {
|
|
68
|
-
filePath = arg;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (!filePath) {
|
|
72
|
-
throw new Error("missing required argument: <spec-file-path>");
|
|
73
|
-
}
|
|
74
|
-
return { filePath, options };
|
|
75
|
-
}
|
|
76
|
-
function printHelp() {
|
|
77
|
-
console.log(`
|
|
78
|
-
spec-frontmatter - Parse and validate specification frontmatter
|
|
79
|
-
|
|
80
|
-
USAGE:
|
|
81
|
-
spekn spec frontmatter <spec-file-path> [OPTIONS]
|
|
82
|
-
|
|
83
|
-
ARGUMENTS:
|
|
84
|
-
<spec-file-path> Path to the specification markdown file
|
|
85
|
-
|
|
86
|
-
OPTIONS:
|
|
87
|
-
-v, --verbose Show detailed output including all fields
|
|
88
|
-
-j, --json Output in JSON format
|
|
89
|
-
--validate-only Only validate, don't display parsed result
|
|
90
|
-
--auto-generate Generate minimal frontmatter if missing
|
|
91
|
-
-h, --help Show this help message
|
|
92
|
-
|
|
93
|
-
EXAMPLES:
|
|
94
|
-
spekn spec frontmatter specs/SPECIFICATION.md
|
|
95
|
-
spekn spec frontmatter specs/SPECIFICATION.md --json
|
|
96
|
-
spekn spec frontmatter specs/SPECIFICATION.md --validate-only
|
|
97
|
-
spekn spec frontmatter specs/SPECIFICATION.md --auto-generate
|
|
98
|
-
`);
|
|
99
|
-
}
|
|
100
|
-
function main(argv) {
|
|
101
|
-
const args = argv ?? process.argv.slice(2);
|
|
102
|
-
if ((0, cli_runtime_1.hasHelpFlag)(args)) {
|
|
103
|
-
printHelp();
|
|
104
|
-
return 0;
|
|
105
|
-
}
|
|
106
|
-
let filePath;
|
|
107
|
-
let options;
|
|
108
|
-
try {
|
|
109
|
-
({ filePath, options } = parseArgs(args));
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
console.error("Error: Missing required argument <spec-file-path>");
|
|
113
|
-
printHelp();
|
|
114
|
-
return 1;
|
|
115
|
-
}
|
|
116
|
-
const resolvedPath = path.resolve(process.cwd(), filePath);
|
|
117
|
-
if (!fs.existsSync(resolvedPath)) {
|
|
118
|
-
console.error(`Error: File not found: ${resolvedPath}`);
|
|
119
|
-
return 1;
|
|
120
|
-
}
|
|
121
|
-
let content;
|
|
122
|
-
try {
|
|
123
|
-
content = fs.readFileSync(resolvedPath, "utf-8");
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
console.error(`Error reading file: ${(0, cli_runtime_1.errorMessage)(error)}`);
|
|
127
|
-
return 1;
|
|
128
|
-
}
|
|
129
|
-
const result = (0, shared_1.parseSpecificationFrontmatter)(content);
|
|
130
|
-
// Auto-generate if requested and no frontmatter found
|
|
131
|
-
if (!result.hasFrontmatter && options.autoGenerate) {
|
|
132
|
-
const generated = (0, shared_1.autoGenerateFrontmatter)(content);
|
|
133
|
-
const yamlStr = (0, shared_1.serializeFrontmatter)(generated);
|
|
134
|
-
if (options.json) {
|
|
135
|
-
console.log(JSON.stringify({ frontmatter: generated, autoGenerated: true }, null, 2));
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
console.log("\nNo frontmatter found. Auto-generated minimal frontmatter:\n");
|
|
139
|
-
console.log(yamlStr);
|
|
140
|
-
console.log();
|
|
141
|
-
}
|
|
142
|
-
return 0;
|
|
143
|
-
}
|
|
144
|
-
// Handle validation errors
|
|
145
|
-
if (result.errors?.length) {
|
|
146
|
-
if (options.json) {
|
|
147
|
-
console.log(JSON.stringify({ errors: result.errors, valid: false }, null, 2));
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
console.error(`\nFrontmatter validation failed for ${path.basename(filePath)}:\n`);
|
|
151
|
-
for (const error of result.errors) {
|
|
152
|
-
console.error(` - ${error}`);
|
|
153
|
-
}
|
|
154
|
-
console.error();
|
|
155
|
-
}
|
|
156
|
-
return 1;
|
|
157
|
-
}
|
|
158
|
-
// No frontmatter found
|
|
159
|
-
if (!result.hasFrontmatter) {
|
|
160
|
-
if (options.json) {
|
|
161
|
-
console.log(JSON.stringify({ hasFrontmatter: false, valid: false }, null, 2));
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
console.error(`\nError: No frontmatter found in ${path.basename(filePath)}`);
|
|
165
|
-
console.error(" Specifications require YAML frontmatter delimited by --- markers.");
|
|
166
|
-
console.error(" Use --auto-generate to create minimal frontmatter.\n");
|
|
167
|
-
}
|
|
168
|
-
return 1;
|
|
169
|
-
}
|
|
170
|
-
// Validate-only mode
|
|
171
|
-
if (options.validateOnly) {
|
|
172
|
-
if (options.json) {
|
|
173
|
-
console.log(JSON.stringify({ valid: true }, null, 2));
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
console.log(`\nFrontmatter valid in ${path.basename(filePath)}\n`);
|
|
177
|
-
}
|
|
178
|
-
return 0;
|
|
179
|
-
}
|
|
180
|
-
// Display parsed frontmatter
|
|
181
|
-
if (options.json) {
|
|
182
|
-
console.log(JSON.stringify(result, null, 2));
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
const fm = result.frontmatter;
|
|
186
|
-
console.log(`\nFrontmatter for ${path.basename(filePath)}:\n`);
|
|
187
|
-
console.log(` Title: ${fm.title}`);
|
|
188
|
-
console.log(` Type: ${fm.type}`);
|
|
189
|
-
console.log(` Version: ${fm.version}`);
|
|
190
|
-
if (fm.status)
|
|
191
|
-
console.log(` Status: ${fm.status}`);
|
|
192
|
-
if (fm.author)
|
|
193
|
-
console.log(` Author: ${fm.author}`);
|
|
194
|
-
if (fm.specRef)
|
|
195
|
-
console.log(` SpecRef: ${fm.specRef}`);
|
|
196
|
-
if (fm.tags?.length)
|
|
197
|
-
console.log(` Tags: ${fm.tags.join(", ")}`);
|
|
198
|
-
if (fm.hints && options.verbose) {
|
|
199
|
-
console.log("\n Content Hints:");
|
|
200
|
-
for (const [layer, hints] of Object.entries(fm.hints)) {
|
|
201
|
-
if (hints?.length) {
|
|
202
|
-
console.log(` ${layer}:`);
|
|
203
|
-
for (const hint of hints) {
|
|
204
|
-
console.log(` - ${hint}`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (fm.dependsOn?.length)
|
|
210
|
-
console.log(`\n Dependencies: ${fm.dependsOn.join(", ")}`);
|
|
211
|
-
if (fm.extends)
|
|
212
|
-
console.log(` Extends: ${fm.extends}`);
|
|
213
|
-
console.log();
|
|
214
|
-
}
|
|
215
|
-
return 0;
|
|
216
|
-
}
|
|
217
|
-
if (require.main === module) {
|
|
218
|
-
void (0, cli_runtime_1.runCliMain)(main, { errorPrefix: "spec-frontmatter failed" });
|
|
219
|
-
}
|
package/dist/spec-lint.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* spec-lint CLI Tool
|
|
4
|
-
*
|
|
5
|
-
* Validate specification markdown quality and structure.
|
|
6
|
-
*
|
|
7
|
-
* Usage: npm run spec-lint <spec-file-path>
|
|
8
|
-
* Example: npm run spec-lint specs/DECISIONS.md
|
|
9
|
-
*/
|
|
10
|
-
declare function main(argv?: string[]): number;
|
|
11
|
-
export { main };
|