@planu/cli 0.99.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/dist/config/license-plans.json +202 -196
- package/dist/engine/agent-orchestrator/coordinator-prompt.d.ts +3 -0
- package/dist/engine/agent-orchestrator/coordinator-prompt.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/coordinator-prompt.js +38 -0
- package/dist/engine/agent-orchestrator/coordinator-prompt.js.map +1 -0
- package/dist/engine/agent-orchestrator/execution-guide.d.ts +3 -0
- package/dist/engine/agent-orchestrator/execution-guide.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/execution-guide.js +59 -0
- package/dist/engine/agent-orchestrator/execution-guide.js.map +1 -0
- package/dist/engine/agent-orchestrator/file-partitioner.d.ts +7 -0
- package/dist/engine/agent-orchestrator/file-partitioner.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/file-partitioner.js +19 -0
- package/dist/engine/agent-orchestrator/file-partitioner.js.map +1 -0
- package/dist/engine/agent-orchestrator/index.d.ts +12 -0
- package/dist/engine/agent-orchestrator/index.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/index.js +131 -0
- package/dist/engine/agent-orchestrator/index.js.map +1 -0
- package/dist/engine/agent-orchestrator/spec-reader.d.ts +6 -0
- package/dist/engine/agent-orchestrator/spec-reader.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/spec-reader.js +20 -0
- package/dist/engine/agent-orchestrator/spec-reader.js.map +1 -0
- package/dist/engine/agent-orchestrator/specialist-prompt.d.ts +3 -0
- package/dist/engine/agent-orchestrator/specialist-prompt.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/specialist-prompt.js +56 -0
- package/dist/engine/agent-orchestrator/specialist-prompt.js.map +1 -0
- package/dist/engine/agent-orchestrator/verifier-prompt.d.ts +3 -0
- package/dist/engine/agent-orchestrator/verifier-prompt.d.ts.map +1 -0
- package/dist/engine/agent-orchestrator/verifier-prompt.js +69 -0
- package/dist/engine/agent-orchestrator/verifier-prompt.js.map +1 -0
- package/dist/engine/filesystem-watcher/index.d.ts +31 -0
- package/dist/engine/filesystem-watcher/index.d.ts.map +1 -0
- package/dist/engine/filesystem-watcher/index.js +101 -0
- package/dist/engine/filesystem-watcher/index.js.map +1 -0
- package/dist/engine/living-specs/criteria-matcher.d.ts +12 -0
- package/dist/engine/living-specs/criteria-matcher.d.ts.map +1 -0
- package/dist/engine/living-specs/criteria-matcher.js +105 -0
- package/dist/engine/living-specs/criteria-matcher.js.map +1 -0
- package/dist/engine/living-specs/file-scanner.d.ts +11 -0
- package/dist/engine/living-specs/file-scanner.d.ts.map +1 -0
- package/dist/engine/living-specs/file-scanner.js +56 -0
- package/dist/engine/living-specs/file-scanner.js.map +1 -0
- package/dist/engine/living-specs/index.d.ts +9 -0
- package/dist/engine/living-specs/index.d.ts.map +1 -0
- package/dist/engine/living-specs/index.js +137 -0
- package/dist/engine/living-specs/index.js.map +1 -0
- package/dist/engine/skills-evaluator/eval-store.d.ts +4 -0
- package/dist/engine/skills-evaluator/eval-store.d.ts.map +1 -0
- package/dist/engine/skills-evaluator/eval-store.js +22 -0
- package/dist/engine/skills-evaluator/eval-store.js.map +1 -0
- package/dist/engine/skills-evaluator/index.d.ts +5 -0
- package/dist/engine/skills-evaluator/index.d.ts.map +1 -0
- package/dist/engine/skills-evaluator/index.js +54 -0
- package/dist/engine/skills-evaluator/index.js.map +1 -0
- package/dist/engine/skills-evaluator/scenario-runner.d.ts +7 -0
- package/dist/engine/skills-evaluator/scenario-runner.d.ts.map +1 -0
- package/dist/engine/skills-evaluator/scenario-runner.js +44 -0
- package/dist/engine/skills-evaluator/scenario-runner.js.map +1 -0
- package/dist/engine/skills-evaluator/skill-reader.d.ts +8 -0
- package/dist/engine/skills-evaluator/skill-reader.d.ts.map +1 -0
- package/dist/engine/skills-evaluator/skill-reader.js +152 -0
- package/dist/engine/skills-evaluator/skill-reader.js.map +1 -0
- package/dist/engine/trial/index.d.ts +25 -0
- package/dist/engine/trial/index.d.ts.map +1 -0
- package/dist/engine/trial/index.js +125 -0
- package/dist/engine/trial/index.js.map +1 -0
- package/dist/engine/trial-engine.d.ts +2 -0
- package/dist/engine/trial-engine.d.ts.map +1 -0
- package/dist/engine/trial-engine.js +3 -0
- package/dist/engine/trial-engine.js.map +1 -0
- package/dist/engine/update-notifier.d.ts +2 -0
- package/dist/engine/update-notifier.d.ts.map +1 -1
- package/dist/engine/update-notifier.js +12 -0
- package/dist/engine/update-notifier.js.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/trial-store.d.ts +19 -0
- package/dist/storage/trial-store.d.ts.map +1 -0
- package/dist/storage/trial-store.js +50 -0
- package/dist/storage/trial-store.js.map +1 -0
- package/dist/tools/eval-skill-v2-handler.d.ts +3 -0
- package/dist/tools/eval-skill-v2-handler.d.ts.map +1 -0
- package/dist/tools/eval-skill-v2-handler.js +53 -0
- package/dist/tools/eval-skill-v2-handler.js.map +1 -0
- package/dist/tools/filesystem-hooks-handler.d.ts +8 -0
- package/dist/tools/filesystem-hooks-handler.d.ts.map +1 -0
- package/dist/tools/filesystem-hooks-handler.js +96 -0
- package/dist/tools/filesystem-hooks-handler.js.map +1 -0
- package/dist/tools/init-project/handler.js +1 -1
- package/dist/tools/init-project/handler.js.map +1 -1
- package/dist/tools/init-project/result-builder.d.ts +1 -1
- package/dist/tools/init-project/result-builder.d.ts.map +1 -1
- package/dist/tools/init-project/result-builder.js +10 -2
- package/dist/tools/init-project/result-builder.js.map +1 -1
- package/dist/tools/license-status.d.ts.map +1 -1
- package/dist/tools/license-status.js +20 -2
- package/dist/tools/license-status.js.map +1 -1
- package/dist/tools/orchestrate-agents-handler.d.ts +4 -0
- package/dist/tools/orchestrate-agents-handler.d.ts.map +1 -0
- package/dist/tools/orchestrate-agents-handler.js +70 -0
- package/dist/tools/orchestrate-agents-handler.js.map +1 -0
- package/dist/tools/reconcile-spec-living-handler.d.ts +6 -0
- package/dist/tools/reconcile-spec-living-handler.d.ts.map +1 -0
- package/dist/tools/reconcile-spec-living-handler.js +52 -0
- package/dist/tools/reconcile-spec-living-handler.js.map +1 -0
- package/dist/tools/register-filesystem-hooks-tools.d.ts +3 -0
- package/dist/tools/register-filesystem-hooks-tools.d.ts.map +1 -0
- package/dist/tools/register-filesystem-hooks-tools.js +85 -0
- package/dist/tools/register-filesystem-hooks-tools.js.map +1 -0
- package/dist/tools/register-living-specs-tools.d.ts +3 -0
- package/dist/tools/register-living-specs-tools.d.ts.map +1 -0
- package/dist/tools/register-living-specs-tools.js +24 -0
- package/dist/tools/register-living-specs-tools.js.map +1 -0
- package/dist/tools/register-skills-eval-tools.d.ts +3 -0
- package/dist/tools/register-skills-eval-tools.d.ts.map +1 -0
- package/dist/tools/register-skills-eval-tools.js +29 -0
- package/dist/tools/register-skills-eval-tools.js.map +1 -0
- package/dist/tools/register-spec-331-tools.d.ts +3 -0
- package/dist/tools/register-spec-331-tools.d.ts.map +1 -0
- package/dist/tools/register-spec-331-tools.js +37 -0
- package/dist/tools/register-spec-331-tools.js.map +1 -0
- package/dist/tools/register-trial-tools.d.ts +3 -0
- package/dist/tools/register-trial-tools.d.ts.map +1 -0
- package/dist/tools/register-trial-tools.js +16 -0
- package/dist/tools/register-trial-tools.js.map +1 -0
- package/dist/tools/safe-handler.d.ts +3 -0
- package/dist/tools/safe-handler.d.ts.map +1 -1
- package/dist/tools/safe-handler.js +24 -2
- package/dist/tools/safe-handler.js.map +1 -1
- package/dist/tools/status-handler.d.ts.map +1 -1
- package/dist/tools/status-handler.js +9 -2
- package/dist/tools/status-handler.js.map +1 -1
- package/dist/tools/trial-handler.d.ts +5 -0
- package/dist/tools/trial-handler.d.ts.map +1 -0
- package/dist/tools/trial-handler.js +51 -0
- package/dist/tools/trial-handler.js.map +1 -0
- package/dist/tools/update-status/side-effects.d.ts.map +1 -1
- package/dist/tools/update-status/side-effects.js +11 -0
- package/dist/tools/update-status/side-effects.js.map +1 -1
- package/dist/types/agent-orchestration.d.ts +54 -0
- package/dist/types/agent-orchestration.d.ts.map +1 -0
- package/dist/types/agent-orchestration.js +3 -0
- package/dist/types/agent-orchestration.js.map +1 -0
- package/dist/types/filesystem-hooks.d.ts +30 -0
- package/dist/types/filesystem-hooks.d.ts.map +1 -0
- package/dist/types/filesystem-hooks.js +3 -0
- package/dist/types/filesystem-hooks.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/living-specs.d.ts +35 -0
- package/dist/types/living-specs.d.ts.map +1 -0
- package/dist/types/living-specs.js +3 -0
- package/dist/types/living-specs.js.map +1 -0
- package/dist/types/skills-evaluation.d.ts +38 -0
- package/dist/types/skills-evaluation.d.ts.map +1 -0
- package/dist/types/skills-evaluation.js +3 -0
- package/dist/types/skills-evaluation.js.map +1 -0
- package/dist/types/telemetry.d.ts +1 -1
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/types/trial.d.ts +41 -0
- package/dist/types/trial.d.ts.map +1 -0
- package/dist/types/trial.js +3 -0
- package/dist/types/trial.js.map +1 -0
- package/package.json +1 -1
- package/src/config/license-plans.json +202 -196
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// engine/living-specs/file-scanner.ts — File existence, line count, export extraction (SPEC-330)
|
|
2
|
+
import { readFile, access } from 'node:fs/promises';
|
|
3
|
+
const EXPORT_REGEX = /export\s+(?:async\s+)?(?:function|class|const)\s+(\w+)/g;
|
|
4
|
+
const FILE_PATH_REGEX = /\b(?:src|tests)\/[\w/.-]+\.ts\b/g;
|
|
5
|
+
/**
|
|
6
|
+
* Scan a single file: check existence, count lines, extract exports.
|
|
7
|
+
*/
|
|
8
|
+
export async function scanFile(filePath) {
|
|
9
|
+
try {
|
|
10
|
+
await access(filePath);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return { path: filePath, exists: false, lineCount: 0, exportsFound: [] };
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const content = await readFile(filePath, 'utf-8');
|
|
17
|
+
const lineCount = content.split('\n').length;
|
|
18
|
+
const exportsFound = extractExports(content);
|
|
19
|
+
return { path: filePath, exists: true, lineCount, exportsFound };
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return { path: filePath, exists: true, lineCount: 0, exportsFound: [] };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract all exported symbol names from file content.
|
|
27
|
+
*/
|
|
28
|
+
function extractExports(content) {
|
|
29
|
+
const found = [];
|
|
30
|
+
let match;
|
|
31
|
+
const regex = new RegExp(EXPORT_REGEX.source, 'g');
|
|
32
|
+
while ((match = regex.exec(content)) !== null) {
|
|
33
|
+
const name = match[1];
|
|
34
|
+
if (name !== undefined && !found.includes(name)) {
|
|
35
|
+
found.push(name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Extract all file paths referenced in technical.md content (src/ and tests/ paths).
|
|
42
|
+
* Deduplicates results.
|
|
43
|
+
*/
|
|
44
|
+
export function extractFilePaths(technicalMdContent) {
|
|
45
|
+
const found = [];
|
|
46
|
+
const regex = new RegExp(FILE_PATH_REGEX.source, 'g');
|
|
47
|
+
let match;
|
|
48
|
+
while ((match = regex.exec(technicalMdContent)) !== null) {
|
|
49
|
+
const p = match[0];
|
|
50
|
+
if (!found.includes(p)) {
|
|
51
|
+
found.push(p);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return found;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=file-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../../src/engine/living-specs/file-scanner.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,YAAY,GAAG,yDAAyD,CAAC;AAC/E,MAAM,eAAe,GAAG,kCAAkC,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAC7C,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAA6B,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,kBAA0B;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LivingSpecReconcileResult } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Auto-reconcile a spec against its actual implementation files.
|
|
4
|
+
* Reads technical.md for file paths, spec.md for criteria,
|
|
5
|
+
* scans files, matches criteria, updates progress.md.
|
|
6
|
+
* Never throws -- returns partial result on error.
|
|
7
|
+
*/
|
|
8
|
+
export declare function reconcileSpec(specId: string, projectPath: string): Promise<LivingSpecReconcileResult>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/living-specs/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAkFtE;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,yBAAyB,CAAC,CAoEpC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// engine/living-specs/index.ts -- Main auto-reconcile entry point (SPEC-330)
|
|
2
|
+
import { readFile, writeFile, access } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { glob } from 'glob';
|
|
5
|
+
import { scanFile, extractFilePaths } from './file-scanner.js';
|
|
6
|
+
import { extractCriteriaLines, matchCriteria } from './criteria-matcher.js';
|
|
7
|
+
/**
|
|
8
|
+
* Find the spec directory for a given specId within the project.
|
|
9
|
+
* Looks for planu/specs/{specId}-SLUG pattern via glob.
|
|
10
|
+
*/
|
|
11
|
+
async function findSpecDir(specId, projectPath) {
|
|
12
|
+
const suffix = specId + '-*/';
|
|
13
|
+
const pattern = join(projectPath, 'planu', 'specs', suffix);
|
|
14
|
+
const dirs = await glob(pattern, { absolute: true });
|
|
15
|
+
return dirs[0] ?? null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Read a file safely, returning empty string on error.
|
|
19
|
+
*/
|
|
20
|
+
async function readSafe(filePath) {
|
|
21
|
+
try {
|
|
22
|
+
await access(filePath);
|
|
23
|
+
return await readFile(filePath, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Build the drift flags from missing files.
|
|
31
|
+
*/
|
|
32
|
+
function buildDriftFlags(fileResults) {
|
|
33
|
+
return fileResults.filter((f) => !f.exists).map((f) => 'DRIFT: ' + f.path + ' missing');
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Append or update the Auto-Reconcile section in progress.md.
|
|
37
|
+
*/
|
|
38
|
+
async function updateProgressMd(progressPath, result) {
|
|
39
|
+
const existing = await readSafe(progressPath);
|
|
40
|
+
const coveragePct = result.criteriaTotal > 0 ? Math.round((result.criteriaMet / result.criteriaTotal) * 100) : 0;
|
|
41
|
+
const driftSection = result.driftFlags.length > 0
|
|
42
|
+
? '\n### Drift Flags\n\n' + result.driftFlags.map((f) => '- ' + f).join('\n') + '\n'
|
|
43
|
+
: '';
|
|
44
|
+
const section = '\n## Auto-Reconcile\n\n' +
|
|
45
|
+
'> Last reconciled: ' +
|
|
46
|
+
result.reconciledAt +
|
|
47
|
+
'\n\n' +
|
|
48
|
+
'- Files found: ' +
|
|
49
|
+
String(result.filesFound) +
|
|
50
|
+
'\n' +
|
|
51
|
+
'- Files missing: ' +
|
|
52
|
+
String(result.filesMissing) +
|
|
53
|
+
'\n' +
|
|
54
|
+
'- Criteria met: ' +
|
|
55
|
+
String(result.criteriaMet) +
|
|
56
|
+
'/' +
|
|
57
|
+
String(result.criteriaTotal) +
|
|
58
|
+
' (' +
|
|
59
|
+
String(coveragePct) +
|
|
60
|
+
'%)' +
|
|
61
|
+
driftSection +
|
|
62
|
+
'\n';
|
|
63
|
+
const AUTO_RECONCILE_MARKER = '## Auto-Reconcile';
|
|
64
|
+
let newContent;
|
|
65
|
+
if (existing.includes(AUTO_RECONCILE_MARKER)) {
|
|
66
|
+
newContent = existing.replace(/\n## Auto-Reconcile[\s\S]*?(?=\n## |\n$|$)/, section);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
newContent = existing + section;
|
|
70
|
+
}
|
|
71
|
+
await writeFile(progressPath, newContent, 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Auto-reconcile a spec against its actual implementation files.
|
|
75
|
+
* Reads technical.md for file paths, spec.md for criteria,
|
|
76
|
+
* scans files, matches criteria, updates progress.md.
|
|
77
|
+
* Never throws -- returns partial result on error.
|
|
78
|
+
*/
|
|
79
|
+
export async function reconcileSpec(specId, projectPath) {
|
|
80
|
+
const reconciledAt = new Date().toISOString();
|
|
81
|
+
const empty = {
|
|
82
|
+
specId,
|
|
83
|
+
reconciledAt,
|
|
84
|
+
filesFound: 0,
|
|
85
|
+
filesMissing: 0,
|
|
86
|
+
criteriaMet: 0,
|
|
87
|
+
criteriaTotal: 0,
|
|
88
|
+
driftFlags: [],
|
|
89
|
+
fileResults: [],
|
|
90
|
+
criteriaResults: [],
|
|
91
|
+
};
|
|
92
|
+
try {
|
|
93
|
+
const specDir = await findSpecDir(specId, projectPath);
|
|
94
|
+
if (specDir === null) {
|
|
95
|
+
empty.driftFlags.push('DRIFT: spec directory for ' + specId + ' not found');
|
|
96
|
+
return empty;
|
|
97
|
+
}
|
|
98
|
+
const technicalPath = join(specDir, 'technical.md');
|
|
99
|
+
const specMdPath = join(specDir, 'spec.md');
|
|
100
|
+
const progressPath = join(specDir, 'progress.md');
|
|
101
|
+
const [technicalContent, specMdContent] = await Promise.all([
|
|
102
|
+
readSafe(technicalPath),
|
|
103
|
+
readSafe(specMdPath),
|
|
104
|
+
]);
|
|
105
|
+
const relativePaths = extractFilePaths(technicalContent);
|
|
106
|
+
const absolutePaths = relativePaths.map((p) => join(projectPath, p));
|
|
107
|
+
const fileResults = await Promise.all(absolutePaths.map((p) => scanFile(p)));
|
|
108
|
+
const fileResultsWithRelative = fileResults.map((fr, i) => ({
|
|
109
|
+
...fr,
|
|
110
|
+
path: relativePaths[i] ?? fr.path,
|
|
111
|
+
}));
|
|
112
|
+
const filesFound = fileResultsWithRelative.filter((f) => f.exists).length;
|
|
113
|
+
const filesMissing = fileResultsWithRelative.filter((f) => !f.exists).length;
|
|
114
|
+
const criteriaLines = extractCriteriaLines(specMdContent);
|
|
115
|
+
const criteriaResults = matchCriteria(criteriaLines, fileResultsWithRelative);
|
|
116
|
+
const criteriaMet = criteriaResults.filter((c) => c.met).length;
|
|
117
|
+
const driftFlags = buildDriftFlags(fileResultsWithRelative);
|
|
118
|
+
const result = {
|
|
119
|
+
specId,
|
|
120
|
+
reconciledAt,
|
|
121
|
+
filesFound,
|
|
122
|
+
filesMissing,
|
|
123
|
+
criteriaMet,
|
|
124
|
+
criteriaTotal: criteriaLines.length,
|
|
125
|
+
driftFlags,
|
|
126
|
+
fileResults: fileResultsWithRelative,
|
|
127
|
+
criteriaResults,
|
|
128
|
+
};
|
|
129
|
+
await updateProgressMd(progressPath, result);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
134
|
+
return { ...empty, driftFlags: ['ERROR: ' + message] };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/living-specs/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SkillsEvalResult } from '../../types/index.js';
|
|
2
|
+
export declare function saveEvalResult(skillName: string, projectPath: string, result: SkillsEvalResult): Promise<void>;
|
|
3
|
+
export declare function loadEvalResult(skillName: string, projectPath: string): Promise<SkillsEvalResult | null>;
|
|
4
|
+
//# sourceMappingURL=eval-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval-store.d.ts","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/eval-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAQlC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// engine/skills-evaluator/eval-store.ts — Persistence for skill eval results (SPEC-332)
|
|
2
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
function evalResultPath(skillName, projectPath) {
|
|
5
|
+
return join(projectPath, '.planu', 'skills', skillName, 'eval-results.json');
|
|
6
|
+
}
|
|
7
|
+
export async function saveEvalResult(skillName, projectPath, result) {
|
|
8
|
+
const filePath = evalResultPath(skillName, projectPath);
|
|
9
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
10
|
+
await writeFile(filePath, JSON.stringify(result, null, 2), 'utf-8');
|
|
11
|
+
}
|
|
12
|
+
export async function loadEvalResult(skillName, projectPath) {
|
|
13
|
+
const filePath = evalResultPath(skillName, projectPath);
|
|
14
|
+
try {
|
|
15
|
+
const content = await readFile(filePath, 'utf-8');
|
|
16
|
+
return JSON.parse(content);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=eval-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval-store.js","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/eval-store.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAGxF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,SAAS,cAAc,CAAC,SAAiB,EAAE,WAAmB;IAC5D,OAAO,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,WAAmB,EACnB,MAAwB;IAExB,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACxD,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAqB,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SkillsEvalResult, SkillsEvalScenario } from '../../types/index.js';
|
|
2
|
+
export declare function evaluateSkill(skillName: string, projectPath: string): Promise<SkillsEvalResult>;
|
|
3
|
+
export declare function getEvalResults(skillName: string, projectPath: string): Promise<SkillsEvalResult | null>;
|
|
4
|
+
export declare function listScenarios(skillName: string, projectPath: string): Promise<SkillsEvalScenario[]>;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAejF,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAoC3B;AAED,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAElC;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAG/B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// engine/skills-evaluator/index.ts — Public API for skills evaluation framework (SPEC-332)
|
|
2
|
+
import { readSkillContent, parseEvalScenarios } from './skill-reader.js';
|
|
3
|
+
import { runScenario } from './scenario-runner.js';
|
|
4
|
+
import { saveEvalResult, loadEvalResult } from './eval-store.js';
|
|
5
|
+
function buildRecommendation(score) {
|
|
6
|
+
if (score >= 0.8) {
|
|
7
|
+
return 'Excellent — skill is well-configured';
|
|
8
|
+
}
|
|
9
|
+
if (score >= 0.5) {
|
|
10
|
+
return 'Good — minor improvements possible';
|
|
11
|
+
}
|
|
12
|
+
return 'Needs review — consider updating eval_scenarios';
|
|
13
|
+
}
|
|
14
|
+
export async function evaluateSkill(skillName, projectPath) {
|
|
15
|
+
const skillContent = await readSkillContent(skillName, projectPath);
|
|
16
|
+
const scenarios = parseEvalScenarios(skillContent);
|
|
17
|
+
if (scenarios.length === 0) {
|
|
18
|
+
const result = {
|
|
19
|
+
skillName,
|
|
20
|
+
evaluatedAt: new Date().toISOString(),
|
|
21
|
+
scenariosRun: 0,
|
|
22
|
+
scenariosPassed: 0,
|
|
23
|
+
overallScore: 0,
|
|
24
|
+
flagged: true,
|
|
25
|
+
runResults: [],
|
|
26
|
+
recommendation: 'No eval_scenarios defined in SKILL.md',
|
|
27
|
+
};
|
|
28
|
+
await saveEvalResult(skillName, projectPath, result);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
const runResults = scenarios.map((scenario) => runScenario(scenario, skillContent));
|
|
32
|
+
const scenariosPassed = runResults.filter((r) => r.passed).length;
|
|
33
|
+
const overallScore = runResults.reduce((sum, r) => sum + r.qualityScore, 0) / runResults.length;
|
|
34
|
+
const result = {
|
|
35
|
+
skillName,
|
|
36
|
+
evaluatedAt: new Date().toISOString(),
|
|
37
|
+
scenariosRun: scenarios.length,
|
|
38
|
+
scenariosPassed,
|
|
39
|
+
overallScore,
|
|
40
|
+
flagged: overallScore < 0.5,
|
|
41
|
+
runResults,
|
|
42
|
+
recommendation: buildRecommendation(overallScore),
|
|
43
|
+
};
|
|
44
|
+
await saveEvalResult(skillName, projectPath, result);
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
export async function getEvalResults(skillName, projectPath) {
|
|
48
|
+
return loadEvalResult(skillName, projectPath);
|
|
49
|
+
}
|
|
50
|
+
export async function listScenarios(skillName, projectPath) {
|
|
51
|
+
const skillContent = await readSkillContent(skillName, projectPath);
|
|
52
|
+
return parseEvalScenarios(skillContent);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/index.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAG3F,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjE,SAAS,mBAAmB,CAAC,KAAa;IACxC,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACjB,OAAO,sCAAsC,CAAC;IAChD,CAAC;IACD,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACjB,OAAO,oCAAoC,CAAC;IAC9C,CAAC;IACD,OAAO,iDAAiD,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB,EACjB,WAAmB;IAEnB,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACpE,MAAM,SAAS,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAEnD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAqB;YAC/B,SAAS;YACT,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACrC,YAAY,EAAE,CAAC;YACf,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,EAAE;YACd,cAAc,EAAE,uCAAuC;SACxD,CAAC;QACF,MAAM,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;IACpF,MAAM,eAAe,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAClE,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC;IAEhG,MAAM,MAAM,GAAqB;QAC/B,SAAS;QACT,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,YAAY,EAAE,SAAS,CAAC,MAAM;QAC9B,eAAe;QACf,YAAY;QACZ,OAAO,EAAE,YAAY,GAAG,GAAG;QAC3B,UAAU;QACV,cAAc,EAAE,mBAAmB,CAAC,YAAY,CAAC;KAClD,CAAC;IAEF,MAAM,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,WAAmB;IAEnB,OAAO,cAAc,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAiB,EACjB,WAAmB;IAEnB,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACpE,OAAO,kBAAkB,CAAC,YAAY,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SkillsEvalScenario, SkillsEvalRunResult } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Evaluate a single scenario against the provided skill content.
|
|
4
|
+
* Pure function — no async, no I/O.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runScenario(scenario: SkillsEvalScenario, skillContent: string): SkillsEvalRunResult;
|
|
7
|
+
//# sourceMappingURL=scenario-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-runner.d.ts","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/scenario-runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,kBAAkB,EAC5B,YAAY,EAAE,MAAM,GACnB,mBAAmB,CAyCrB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// engine/skills-evaluator/scenario-runner.ts — Pure scenario evaluation logic (SPEC-332)
|
|
2
|
+
/**
|
|
3
|
+
* Evaluate a single scenario against the provided skill content.
|
|
4
|
+
* Pure function — no async, no I/O.
|
|
5
|
+
*/
|
|
6
|
+
export function runScenario(scenario, skillContent) {
|
|
7
|
+
const lower = skillContent.toLowerCase();
|
|
8
|
+
const keywordsFound = [];
|
|
9
|
+
const keywordsMissing = [];
|
|
10
|
+
for (const keyword of scenario.expectedKeywords) {
|
|
11
|
+
if (lower.includes(keyword.toLowerCase())) {
|
|
12
|
+
keywordsFound.push(keyword);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
keywordsMissing.push(keyword);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let patternsMatched = 0;
|
|
19
|
+
const patternsTotal = scenario.expectedPatterns.length;
|
|
20
|
+
for (const pattern of scenario.expectedPatterns) {
|
|
21
|
+
try {
|
|
22
|
+
const regex = new RegExp(pattern, 'i');
|
|
23
|
+
if (regex.test(skillContent)) {
|
|
24
|
+
patternsMatched++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Invalid regex counts as unmatched
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const keywordRatio = keywordsFound.length / Math.max(scenario.expectedKeywords.length, 1);
|
|
32
|
+
const patternRatio = patternsMatched / Math.max(patternsTotal, 1);
|
|
33
|
+
const qualityScore = keywordRatio * 0.6 + patternRatio * 0.4;
|
|
34
|
+
return {
|
|
35
|
+
scenarioName: scenario.name,
|
|
36
|
+
qualityScore,
|
|
37
|
+
keywordsFound,
|
|
38
|
+
keywordsMissing,
|
|
39
|
+
patternsMatched,
|
|
40
|
+
patternsTotal,
|
|
41
|
+
passed: qualityScore >= 0.5,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=scenario-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-runner.js","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/scenario-runner.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAIzF;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,QAA4B,EAC5B,YAAoB;IAEpB,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAEzC,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,MAAM,eAAe,GAAa,EAAE,CAAC;IAErC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAChD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC1C,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,MAAM,aAAa,GAAG,QAAQ,CAAC,gBAAgB,CAAC,MAAM,CAAC;IAEvD,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC7B,eAAe,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oCAAoC;QACtC,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC1F,MAAM,YAAY,GAAG,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,YAAY,GAAG,GAAG,GAAG,YAAY,GAAG,GAAG,CAAC;IAE7D,OAAO;QACL,YAAY,EAAE,QAAQ,CAAC,IAAI;QAC3B,YAAY;QACZ,aAAa;QACb,eAAe;QACf,eAAe;QACf,aAAa;QACb,MAAM,EAAE,YAAY,IAAI,GAAG;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SkillsEvalScenario } from '../../types/index.js';
|
|
2
|
+
export declare function readSkillContent(skillName: string, projectPath: string): Promise<string>;
|
|
3
|
+
/**
|
|
4
|
+
* Parse eval_scenarios from skill content frontmatter.
|
|
5
|
+
* Supports block and inline YAML array format.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseEvalScenarios(skillContent: string): SkillsEvalScenario[];
|
|
8
|
+
//# sourceMappingURL=skill-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-reader.d.ts","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/skill-reader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAA6B,MAAM,sBAAsB,CAAC;AAE1F,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO9F;AAkID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAiB7E"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// engine/skills-evaluator/skill-reader.ts — Reads skill files and parses eval scenarios (SPEC-332)
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export async function readSkillContent(skillName, projectPath) {
|
|
5
|
+
const filePath = join(projectPath, '.planu', 'skills', skillName, 'SKILL.md');
|
|
6
|
+
try {
|
|
7
|
+
return await readFile(filePath, 'utf-8');
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return '';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Extract the YAML frontmatter block from skill content. */
|
|
14
|
+
function extractFrontmatter(content) {
|
|
15
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(content);
|
|
16
|
+
return match?.[1] ?? '';
|
|
17
|
+
}
|
|
18
|
+
/** Parse a scalar YAML value (quoted or unquoted). */
|
|
19
|
+
function parseScalar(raw) {
|
|
20
|
+
const trimmed = raw.trim();
|
|
21
|
+
const isDoubleQuoted = trimmed.startsWith('"') && trimmed.endsWith('"');
|
|
22
|
+
const isSingleQuoted = trimmed.startsWith("'") && trimmed.endsWith("'");
|
|
23
|
+
if (isDoubleQuoted || isSingleQuoted) {
|
|
24
|
+
return trimmed.slice(1, -1);
|
|
25
|
+
}
|
|
26
|
+
return trimmed;
|
|
27
|
+
}
|
|
28
|
+
/** Parse an inline YAML array: ["a", "b"] or ['a', 'b']. */
|
|
29
|
+
function parseInlineArray(raw) {
|
|
30
|
+
const inner = raw.trim().replace(/^\[/, '').replace(/\]$/, '').trim();
|
|
31
|
+
if (!inner) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
return inner.split(',').map((s) => parseScalar(s.trim()));
|
|
35
|
+
}
|
|
36
|
+
function toScenario(partial) {
|
|
37
|
+
return {
|
|
38
|
+
name: partial.name ?? '',
|
|
39
|
+
description: partial.description ?? '',
|
|
40
|
+
input: partial.input ?? '',
|
|
41
|
+
expectedKeywords: partial.expectedKeywords ?? [],
|
|
42
|
+
expectedPatterns: partial.expectedPatterns ?? [],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Process a named-field line, returning a patch and updated list mode. */
|
|
46
|
+
function processFieldLine(trimmed) {
|
|
47
|
+
if (trimmed.startsWith('description:')) {
|
|
48
|
+
return {
|
|
49
|
+
patch: { description: parseScalar(trimmed.slice('description:'.length).trim()) },
|
|
50
|
+
listMode: null,
|
|
51
|
+
done: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (trimmed.startsWith('input:')) {
|
|
55
|
+
return {
|
|
56
|
+
patch: { input: parseScalar(trimmed.slice('input:'.length).trim()) },
|
|
57
|
+
listMode: null,
|
|
58
|
+
done: false,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (trimmed.startsWith('expectedKeywords:')) {
|
|
62
|
+
const rest = trimmed.slice('expectedKeywords:'.length).trim();
|
|
63
|
+
if (rest.startsWith('[')) {
|
|
64
|
+
return { patch: { expectedKeywords: parseInlineArray(rest) }, listMode: null, done: false };
|
|
65
|
+
}
|
|
66
|
+
return { patch: { expectedKeywords: [] }, listMode: 'keywords', done: false };
|
|
67
|
+
}
|
|
68
|
+
if (trimmed.startsWith('expectedPatterns:')) {
|
|
69
|
+
const rest = trimmed.slice('expectedPatterns:'.length).trim();
|
|
70
|
+
if (rest.startsWith('[')) {
|
|
71
|
+
return { patch: { expectedPatterns: parseInlineArray(rest) }, listMode: null, done: false };
|
|
72
|
+
}
|
|
73
|
+
return { patch: { expectedPatterns: [] }, listMode: 'patterns', done: false };
|
|
74
|
+
}
|
|
75
|
+
// Unknown top-level key — end of eval_scenarios block
|
|
76
|
+
return { patch: {}, listMode: null, done: true };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse all eval_scenarios blocks from YAML frontmatter text.
|
|
80
|
+
* Returns an array of complete SkillsEvalScenario objects.
|
|
81
|
+
*/
|
|
82
|
+
function parseScenarioLines(lines) {
|
|
83
|
+
const results = [];
|
|
84
|
+
let current = null;
|
|
85
|
+
let listMode = null;
|
|
86
|
+
for (const rawLine of lines) {
|
|
87
|
+
const trimmed = rawLine.trimEnd().trim();
|
|
88
|
+
if (trimmed.startsWith('- name:')) {
|
|
89
|
+
if (current?.name !== undefined) {
|
|
90
|
+
results.push(toScenario(current));
|
|
91
|
+
}
|
|
92
|
+
current = {
|
|
93
|
+
name: parseScalar(trimmed.slice('- name:'.length).trim()),
|
|
94
|
+
description: '',
|
|
95
|
+
input: '',
|
|
96
|
+
expectedKeywords: [],
|
|
97
|
+
expectedPatterns: [],
|
|
98
|
+
};
|
|
99
|
+
listMode = null;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (!current) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (listMode === 'keywords' && trimmed.startsWith('- ')) {
|
|
106
|
+
current = {
|
|
107
|
+
...current,
|
|
108
|
+
expectedKeywords: [...(current.expectedKeywords ?? []), parseScalar(trimmed.slice(2))],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
else if (listMode === 'patterns' && trimmed.startsWith('- ')) {
|
|
112
|
+
current = {
|
|
113
|
+
...current,
|
|
114
|
+
expectedPatterns: [...(current.expectedPatterns ?? []), parseScalar(trimmed.slice(2))],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
else if (!trimmed.startsWith('-') && !trimmed.startsWith(' ') && trimmed !== '') {
|
|
118
|
+
const { patch, listMode: newMode, done } = processFieldLine(trimmed);
|
|
119
|
+
if (done) {
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
current = { ...current, ...patch };
|
|
123
|
+
listMode = newMode;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (current?.name !== undefined) {
|
|
127
|
+
results.push(toScenario(current));
|
|
128
|
+
}
|
|
129
|
+
return results;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Parse eval_scenarios from skill content frontmatter.
|
|
133
|
+
* Supports block and inline YAML array format.
|
|
134
|
+
*/
|
|
135
|
+
export function parseEvalScenarios(skillContent) {
|
|
136
|
+
try {
|
|
137
|
+
const frontmatter = extractFrontmatter(skillContent);
|
|
138
|
+
if (!frontmatter) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
const scenariosStart = frontmatter.indexOf('eval_scenarios:');
|
|
142
|
+
if (scenariosStart === -1) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const afterKey = frontmatter.slice(scenariosStart + 'eval_scenarios:'.length);
|
|
146
|
+
return parseScenarioLines(afterKey.split('\n'));
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=skill-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-reader.js","sourceRoot":"","sources":["../../../src/engine/skills-evaluator/skill-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TrialStatus, RequestTrialResult } from '../../types/index.js';
|
|
2
|
+
import { isTrialActive as storeIsTrialActive } from '../../storage/trial-store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Generates a deterministic, anonymous installation ID from machine attributes.
|
|
5
|
+
* Uses SHA-256(hostname + platform + arch) — no personal data.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getInstallationId(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Sends a trial activation request to the Planu trial API.
|
|
10
|
+
* On success the server inserts a row in the `trials` table and returns
|
|
11
|
+
* a UUID trialKey + expiry date.
|
|
12
|
+
*/
|
|
13
|
+
export declare function requestTrial(email: string): Promise<RequestTrialResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Returns the current trial status. Fast local read — no network call.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getTrialStatus(): Promise<TrialStatus>;
|
|
18
|
+
export { storeIsTrialActive as isTrialActive };
|
|
19
|
+
/**
|
|
20
|
+
* Validates the trial key against the server. If the server says the key is
|
|
21
|
+
* invalid or revoked, marks the trial as expired locally by clearing trialKey.
|
|
22
|
+
* Fire-and-forget — never awaited by callers.
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateTrialBackground(): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/trial/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAGL,aAAa,IAAI,kBAAkB,EAEpC,MAAM,8BAA8B,CAAC;AActC;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAMD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwC7E;AAMD;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAe3D;AAMD,OAAO,EAAE,kBAAkB,IAAI,aAAa,EAAE,CAAC;AAM/C;;;;GAIG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6B7D"}
|