nimai-core 0.1.1 → 0.2.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/clarification.d.ts +22 -0
- package/dist/clarification.d.ts.map +1 -0
- package/dist/clarification.js +106 -0
- package/dist/clarification.js.map +1 -0
- package/dist/context.js +24 -4
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +49 -6
- package/dist/lint.js.map +1 -1
- package/dist/prompts.d.ts +13 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +53 -0
- package/dist/prompts.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule-based clarification heuristics for nimai_spec.
|
|
3
|
+
*
|
|
4
|
+
* These are pure functions — no IO, no LLM calls.
|
|
5
|
+
* Trigger `clarifications_needed` when any heuristic fires.
|
|
6
|
+
*/
|
|
7
|
+
export interface ClarificationResult {
|
|
8
|
+
needed: boolean;
|
|
9
|
+
reasons: string[];
|
|
10
|
+
questions: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Evaluate whether a spec request needs clarification before drafting.
|
|
14
|
+
*
|
|
15
|
+
* Heuristics (any one firing triggers clarification):
|
|
16
|
+
* 1. Request is under 10 words
|
|
17
|
+
* 2. Zero repo files matched by context extractor
|
|
18
|
+
* 3. No domain nouns or action verbs detected
|
|
19
|
+
* 4. Conflicting stack hints (two competing tech choices in same category)
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectClarifications(request: string, contextFileCount: number): ClarificationResult;
|
|
22
|
+
//# sourceMappingURL=clarification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarification.d.ts","sourceRoot":"","sources":["../src/clarification.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuEH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GACvB,mBAAmB,CA+BrB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Rule-based clarification heuristics for nimai_spec.
|
|
4
|
+
*
|
|
5
|
+
* These are pure functions — no IO, no LLM calls.
|
|
6
|
+
* Trigger `clarifications_needed` when any heuristic fires.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.detectClarifications = detectClarifications;
|
|
10
|
+
// ─── Domain noun / action vocab ───────────────────────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Minimum set of technical domain nouns and action verbs that indicate the
|
|
13
|
+
* request describes a real engineering task. If the request contains none of
|
|
14
|
+
* these, it is likely too vague to spec reliably.
|
|
15
|
+
*/
|
|
16
|
+
const DOMAIN_TOKENS = new Set([
|
|
17
|
+
// Action verbs
|
|
18
|
+
'add', 'build', 'create', 'implement', 'fix', 'refactor', 'update', 'migrate',
|
|
19
|
+
'design', 'integrate', 'deploy', 'remove', 'generate', 'optimize', 'extend',
|
|
20
|
+
'replace', 'extract', 'expose', 'wire', 'scaffold', 'test', 'benchmark',
|
|
21
|
+
// Technical nouns
|
|
22
|
+
'api', 'service', 'component', 'model', 'module', 'database', 'endpoint',
|
|
23
|
+
'interface', 'schema', 'type', 'function', 'class', 'route', 'handler',
|
|
24
|
+
'middleware', 'auth', 'token', 'config', 'cli', 'ui', 'hook', 'store',
|
|
25
|
+
'query', 'mutation', 'event', 'queue', 'cache', 'index', 'migration',
|
|
26
|
+
'server', 'client', 'backend', 'frontend', 'test', 'spec', 'pipeline',
|
|
27
|
+
'workflow', 'adapter', 'plugin', 'sdk', 'contract', 'validator', 'parser',
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if the request contains at least one recognizable domain token.
|
|
31
|
+
*/
|
|
32
|
+
function hasDomainNoun(request) {
|
|
33
|
+
const words = request.toLowerCase().match(/\b[a-z]+\b/g) ?? [];
|
|
34
|
+
return words.some(w => DOMAIN_TOKENS.has(w));
|
|
35
|
+
}
|
|
36
|
+
// ─── Conflicting stack detection ──────────────────────────────────────────────
|
|
37
|
+
/** Groups of mutually-competing technology choices. Two items from the same group = conflict. */
|
|
38
|
+
const STACK_GROUPS = [
|
|
39
|
+
// Programming languages — any two in the same request signals ambiguous stack
|
|
40
|
+
[
|
|
41
|
+
'python', 'ruby', 'java', 'golang', 'rust', 'kotlin', 'swift', 'scala',
|
|
42
|
+
'php', 'elixir', 'csharp', 'typescript', 'javascript',
|
|
43
|
+
],
|
|
44
|
+
// JS UI frameworks
|
|
45
|
+
['react', 'vue', 'angular', 'svelte'],
|
|
46
|
+
// CSS frameworks
|
|
47
|
+
['tailwind', 'bootstrap'],
|
|
48
|
+
// Relational databases
|
|
49
|
+
['postgresql', 'postgres', 'mysql', 'sqlite'],
|
|
50
|
+
// NoSQL databases
|
|
51
|
+
['mongodb', 'dynamodb', 'firestore', 'cassandra'],
|
|
52
|
+
// JS test frameworks
|
|
53
|
+
['jest', 'vitest', 'jasmine'],
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Returns true if the request mentions ≥2 items from the same competing stack group,
|
|
57
|
+
* indicating an ambiguous or conflicting technology choice.
|
|
58
|
+
*/
|
|
59
|
+
function hasConflictingStack(request) {
|
|
60
|
+
const lower = request.toLowerCase();
|
|
61
|
+
for (const group of STACK_GROUPS) {
|
|
62
|
+
const hits = group.filter(tech => {
|
|
63
|
+
// Match as whole word or compound (e.g. "typescript", "vue.js")
|
|
64
|
+
const pattern = new RegExp(`\\b${tech.replace(/[-.]/g, '[-.\\s]?')}\\b`, 'i');
|
|
65
|
+
return pattern.test(lower);
|
|
66
|
+
});
|
|
67
|
+
if (hits.length >= 2)
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Evaluate whether a spec request needs clarification before drafting.
|
|
74
|
+
*
|
|
75
|
+
* Heuristics (any one firing triggers clarification):
|
|
76
|
+
* 1. Request is under 10 words
|
|
77
|
+
* 2. Zero repo files matched by context extractor
|
|
78
|
+
* 3. No domain nouns or action verbs detected
|
|
79
|
+
* 4. Conflicting stack hints (two competing tech choices in same category)
|
|
80
|
+
*/
|
|
81
|
+
function detectClarifications(request, contextFileCount) {
|
|
82
|
+
const reasons = [];
|
|
83
|
+
const wordCount = request.trim().split(/\s+/).length;
|
|
84
|
+
if (wordCount < 10) {
|
|
85
|
+
reasons.push(`request is too short (${wordCount} words — add more context)`);
|
|
86
|
+
}
|
|
87
|
+
if (contextFileCount === 0) {
|
|
88
|
+
reasons.push('no relevant repo files matched — is the repo path correct, or is this a new project?');
|
|
89
|
+
}
|
|
90
|
+
if (!hasDomainNoun(request)) {
|
|
91
|
+
reasons.push('no recognizable domain nouns or action verbs found — describe what should be built or changed');
|
|
92
|
+
}
|
|
93
|
+
if (hasConflictingStack(request)) {
|
|
94
|
+
reasons.push('conflicting technology stack hints detected — clarify which stack applies or separate into distinct tasks');
|
|
95
|
+
}
|
|
96
|
+
const needed = reasons.length > 0;
|
|
97
|
+
const questions = needed
|
|
98
|
+
? [
|
|
99
|
+
'What is the primary goal or outcome you want to achieve?',
|
|
100
|
+
'Which specific files, components, or systems should be modified?',
|
|
101
|
+
'Are there constraints, dependencies, or requirements we should be aware of?',
|
|
102
|
+
]
|
|
103
|
+
: [];
|
|
104
|
+
return { needed, reasons, questions };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=clarification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarification.js","sourceRoot":"","sources":["../src/clarification.ts"],"names":[],"mappings":"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"}
|
package/dist/context.js
CHANGED
|
@@ -74,9 +74,9 @@ function walkDir(rootPath, currentPath, results, keywords) {
|
|
|
74
74
|
catch {
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
|
-
const
|
|
77
|
+
const relPath = path.relative(rootPath, fullPath);
|
|
78
|
+
const relevance = scoreRelevance(entry.name, content, keywords, relPath);
|
|
78
79
|
if (relevance > 0) {
|
|
79
|
-
const relPath = path.relative(rootPath, fullPath);
|
|
80
80
|
results.push({
|
|
81
81
|
file: relPath,
|
|
82
82
|
snippet: content.slice(0, MAX_SNIPPET_CHARS),
|
|
@@ -86,11 +86,31 @@ function walkDir(rootPath, currentPath, results, keywords) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
// Source dirs score higher than docs/examples/schemas
|
|
90
|
+
const SOURCE_DIR_PATTERNS = ['src/', 'lib/', 'app/', 'server/', 'api/'];
|
|
91
|
+
const DOCS_DIR_PATTERNS = ['docs/', 'examples/', 'schemas/'];
|
|
92
|
+
function scoreRelevance(filename, content, keywords, relPath) {
|
|
90
93
|
if (keywords.length === 0)
|
|
91
94
|
return 1;
|
|
92
95
|
const lower = (filename + ' ' + content).toLowerCase();
|
|
93
|
-
|
|
96
|
+
const keywordScore = keywords.filter(k => lower.includes(k)).length;
|
|
97
|
+
if (keywordScore === 0)
|
|
98
|
+
return 0;
|
|
99
|
+
// Filename boost: if the filename itself matches a keyword, it's likely the most relevant file
|
|
100
|
+
const filenameLower = filename.toLowerCase().replace(/\.[^.]+$/, '');
|
|
101
|
+
const filenameBoost = keywords.some(k => filenameLower.includes(k)) ? 2 : 0;
|
|
102
|
+
// Path boost: source files score higher than docs/examples
|
|
103
|
+
let pathBoost = 0;
|
|
104
|
+
if (relPath) {
|
|
105
|
+
const rel = relPath.toLowerCase();
|
|
106
|
+
if (SOURCE_DIR_PATTERNS.some(p => rel.startsWith(p)))
|
|
107
|
+
pathBoost = 1;
|
|
108
|
+
if (DOCS_DIR_PATTERNS.some(p => rel.startsWith(p)))
|
|
109
|
+
pathBoost = -1;
|
|
110
|
+
}
|
|
111
|
+
// Nimai spec boost: files containing the <!-- nimai-spec --> marker are prioritised
|
|
112
|
+
const nimaiBoost = content.includes('<!-- nimai-spec -->') ? 2 : 0;
|
|
113
|
+
return keywordScore + filenameBoost + pathBoost + nimaiBoost;
|
|
94
114
|
}
|
|
95
115
|
function tokenize(request) {
|
|
96
116
|
return request
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,wCASC;AAlBD,uCAAyB;AACzB,2CAA6B;AAG7B,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AACpF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAC5I,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,SAAgB,cAAc,CAAC,QAAgB,EAAE,OAAe;IAC9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,UAAU,GAAkB,EAAE,CAAC;IAErC,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAElD,OAAO,UAAU;SACd,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;SACzC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,OAAO,CACd,QAAgB,EAChB,WAAmB,EACnB,OAAsB,EACtB,QAAkB;IAElB,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YACnD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAE3C,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YAED,MAAM,
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -19,4 +19,5 @@ __exportStar(require("./template"), exports);
|
|
|
19
19
|
__exportStar(require("./lint"), exports);
|
|
20
20
|
__exportStar(require("./context"), exports);
|
|
21
21
|
__exportStar(require("./prompts"), exports);
|
|
22
|
+
__exportStar(require("./clarification"), exports);
|
|
22
23
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,yCAAuB;AACvB,4CAA0B;AAC1B,4CAA0B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,yCAAuB;AACvB,4CAA0B;AAC1B,4CAA0B;AAC1B,kDAAgC"}
|
package/dist/lint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAiB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAiB,MAAM,SAAS,CAAC;AA8DnD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAQtD;AAsBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CA2CxD"}
|
package/dist/lint.js
CHANGED
|
@@ -50,12 +50,16 @@ const REQUIRED_SECTIONS = [
|
|
|
50
50
|
'governance & validation',
|
|
51
51
|
];
|
|
52
52
|
// Advisory: architecture quality signals (anti-spaghetti rules)
|
|
53
|
-
// Each rule looks for at least one keyword/heading indicating the concept is addressed
|
|
53
|
+
// Each rule looks for at least one keyword/heading indicating the concept is addressed.
|
|
54
|
+
// Rules marked hardFailTiers become hard failures (not advisory) when the spec's risk tier
|
|
55
|
+
// matches AND (if codingOnly=true) the spec is a coding/tooling/server spec.
|
|
54
56
|
const ADVISORY_RULES = [
|
|
55
57
|
{
|
|
56
58
|
type: 'missing_module_boundary',
|
|
57
|
-
keywords: ['module boundary', 'package boundary', 'layer boundary', 'separation of concerns', 'packages/core', 'packages/mcp', 'packages/cli'],
|
|
58
|
-
message: 'No module boundary definition found —
|
|
59
|
+
keywords: ['module boundary', 'package boundary', 'layer boundary', 'separation of concerns', 'packages/core', 'packages/mcp', 'packages/cli', 'app/models', 'app/state', 'app/db'],
|
|
60
|
+
message: 'No module boundary definition found — document package/layer boundaries and which layers may not import each other',
|
|
61
|
+
hardFailTiers: ['medium', 'high'],
|
|
62
|
+
codingOnly: true,
|
|
59
63
|
},
|
|
60
64
|
{
|
|
61
65
|
type: 'missing_interface_contract',
|
|
@@ -65,12 +69,22 @@ const ADVISORY_RULES = [
|
|
|
65
69
|
{
|
|
66
70
|
type: 'missing_non_goals',
|
|
67
71
|
keywords: ['non-goal', 'non-goals', 'must-not', 'scope — out', 'out of scope', 'deferred', 'excluded'],
|
|
68
|
-
message: 'No non-goals or out-of-scope section found —
|
|
72
|
+
message: 'No non-goals or out-of-scope section found — document what this spec explicitly excludes',
|
|
73
|
+
hardFailTiers: ['medium', 'high'],
|
|
69
74
|
},
|
|
70
75
|
{
|
|
71
76
|
type: 'missing_change_surface',
|
|
72
77
|
keywords: ['change surface', 'breaking change', 'migration', 'backward compat', 'semver', 'versioning', 'deprecat'],
|
|
73
|
-
message: 'No change surface documentation found —
|
|
78
|
+
message: 'No change surface documentation found — document compatibility expectations and what this spec must not break',
|
|
79
|
+
hardFailTiers: ['medium', 'high'],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
type: 'missing_dependency_direction',
|
|
83
|
+
keywords: ['dependency direction', 'may not import', 'must not import', 'import from', 'no cross-layer', 'dependency rule', 'import rule'],
|
|
84
|
+
message: 'No dependency direction rules found — document which modules/layers may import which (prevents circular and cross-layer dependencies)',
|
|
85
|
+
hardFailTiers: ['medium', 'high'],
|
|
86
|
+
codingOnly: true,
|
|
87
|
+
skipAdvisoryForTiers: ['low', 'unknown'],
|
|
74
88
|
},
|
|
75
89
|
];
|
|
76
90
|
function lintSpec(filePath) {
|
|
@@ -83,6 +97,25 @@ function lintSpec(filePath) {
|
|
|
83
97
|
}
|
|
84
98
|
return lintContent(content);
|
|
85
99
|
}
|
|
100
|
+
/** Detect risk tier from checked checkbox in spec content */
|
|
101
|
+
function detectRiskTier(content) {
|
|
102
|
+
if (/\[x\]\s*high/i.test(content))
|
|
103
|
+
return 'high';
|
|
104
|
+
if (/\[x\]\s*medium/i.test(content))
|
|
105
|
+
return 'medium';
|
|
106
|
+
if (/\[x\]\s*low/i.test(content))
|
|
107
|
+
return 'low';
|
|
108
|
+
return 'unknown';
|
|
109
|
+
}
|
|
110
|
+
/** Detect if this is a coding/tooling/server spec (vs docs/research/strategy) */
|
|
111
|
+
function isCodingSpec(content) {
|
|
112
|
+
const lower = content.toLowerCase();
|
|
113
|
+
return (lower.includes('if coding') ||
|
|
114
|
+
lower.includes('language / framework') ||
|
|
115
|
+
lower.includes('language/framework') ||
|
|
116
|
+
lower.includes('test coverage expectation') ||
|
|
117
|
+
lower.includes('performance targets'));
|
|
118
|
+
}
|
|
86
119
|
function lintContent(content) {
|
|
87
120
|
const issues = [];
|
|
88
121
|
const lines = content.split('\n');
|
|
@@ -102,10 +135,20 @@ function lintContent(content) {
|
|
|
102
135
|
issues.push(issue(0, 'missing_section', `Required section missing: "${section}"`));
|
|
103
136
|
}
|
|
104
137
|
}
|
|
138
|
+
const riskTier = detectRiskTier(content);
|
|
139
|
+
const coding = isCodingSpec(content);
|
|
105
140
|
for (const rule of ADVISORY_RULES) {
|
|
106
141
|
const found = rule.keywords.some(kw => lower.includes(kw.toLowerCase()));
|
|
107
142
|
if (!found) {
|
|
108
|
-
|
|
143
|
+
const shouldHardFail = rule.hardFailTiers !== undefined &&
|
|
144
|
+
rule.hardFailTiers.includes(riskTier) &&
|
|
145
|
+
(!rule.codingOnly || coding);
|
|
146
|
+
if (shouldHardFail) {
|
|
147
|
+
issues.push(issue(0, rule.type, `${rule.message} [required for ${riskTier}-risk${rule.codingOnly ? ' coding' : ''} specs]`));
|
|
148
|
+
}
|
|
149
|
+
else if (!rule.skipAdvisoryForTiers?.includes(riskTier)) {
|
|
150
|
+
issues.push(advisoryIssue(0, rule.type, rule.message));
|
|
151
|
+
}
|
|
109
152
|
}
|
|
110
153
|
}
|
|
111
154
|
return issues;
|
package/dist/lint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
|
package/dist/prompts.d.ts
CHANGED
|
@@ -8,6 +8,19 @@
|
|
|
8
8
|
* Returns the populated prompt ready to hand to a host model.
|
|
9
9
|
*/
|
|
10
10
|
export declare function buildPrompt1(request: string, contextSummary: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* FORGE Prompt 1.5 — Spec-Quality Reviewer.
|
|
13
|
+
* Returns a prompt for a reviewing LLM to evaluate whether a draft spec is
|
|
14
|
+
* executable by an agent without requiring clarifying questions.
|
|
15
|
+
*
|
|
16
|
+
* The reviewing LLM MUST end its response with a machine-parseable JSON verdict block:
|
|
17
|
+
* ## Verdict
|
|
18
|
+
* ```json
|
|
19
|
+
* {"passed": true, "issues": []}
|
|
20
|
+
* ```
|
|
21
|
+
* The host agent parses this block to drive the spec-review loop.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildPrompt15(specContent: string): string;
|
|
11
24
|
/**
|
|
12
25
|
* FORGE Prompt 2 — Reviewer / Validator Prompt Generator (from FORGE-quickref.md).
|
|
13
26
|
* Returns the populated reviewer prompt derived from an approved spec.
|
package/dist/prompts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CA0B5E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBxD"}
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CA0B5E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAuCzD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBxD"}
|
package/dist/prompts.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.buildPrompt1 = buildPrompt1;
|
|
9
|
+
exports.buildPrompt15 = buildPrompt15;
|
|
9
10
|
exports.buildPrompt2 = buildPrompt2;
|
|
10
11
|
/**
|
|
11
12
|
* FORGE Prompt 1 — Self-Spec Agent (from FORGE-quickref.md).
|
|
@@ -38,6 +39,58 @@ ${contextSummary || '(no repo context extracted)'}
|
|
|
38
39
|
|
|
39
40
|
Loose request: ${request}`;
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* FORGE Prompt 1.5 — Spec-Quality Reviewer.
|
|
44
|
+
* Returns a prompt for a reviewing LLM to evaluate whether a draft spec is
|
|
45
|
+
* executable by an agent without requiring clarifying questions.
|
|
46
|
+
*
|
|
47
|
+
* The reviewing LLM MUST end its response with a machine-parseable JSON verdict block:
|
|
48
|
+
* ## Verdict
|
|
49
|
+
* ```json
|
|
50
|
+
* {"passed": true, "issues": []}
|
|
51
|
+
* ```
|
|
52
|
+
* The host agent parses this block to drive the spec-review loop.
|
|
53
|
+
*/
|
|
54
|
+
function buildPrompt15(specContent) {
|
|
55
|
+
return `You are a Specification Quality Reviewer operating under the FORGE framework.
|
|
56
|
+
|
|
57
|
+
Your job is to evaluate the draft spec below for **spec quality only** — not implementation correctness.
|
|
58
|
+
Do NOT assess any code, code diffs, or implementation output.
|
|
59
|
+
|
|
60
|
+
## What to check
|
|
61
|
+
|
|
62
|
+
Evaluate each dimension with a binary PASS or FAIL:
|
|
63
|
+
|
|
64
|
+
1. **Binary acceptance criteria** — are all sub-task ACs measurable and unambiguous?
|
|
65
|
+
2. **Scope coherence** — are in-scope and out-of-scope boundaries clearly stated and non-contradictory?
|
|
66
|
+
3. **Constraint sufficiency** — do Must / Must-Not / Prefer / Escalate constraints cover the key risks?
|
|
67
|
+
4. **Decomposition realism** — can each sub-task be completed within the stated 2-hour limit by a skilled agent?
|
|
68
|
+
5. **Start-without-clarification viability** — can an agent begin immediately with the context provided, without asking the human for more information?
|
|
69
|
+
|
|
70
|
+
## Output format
|
|
71
|
+
|
|
72
|
+
For each check, write: **[PASS]** or **[FAIL]** followed by a one-sentence rationale.
|
|
73
|
+
|
|
74
|
+
Then write a consolidated summary listing all failing dimensions and their remediation guidance.
|
|
75
|
+
|
|
76
|
+
Note: implementation correctness is explicitly out of scope for this review.
|
|
77
|
+
|
|
78
|
+
## Important
|
|
79
|
+
|
|
80
|
+
Always end your response with the following verdict block as the **final section**, regardless of pass/fail outcome.
|
|
81
|
+
The host agent parses this block to drive the loop — if it is absent or malformed, the host will treat the result as ambiguous and escalate to the human.
|
|
82
|
+
|
|
83
|
+
## Verdict
|
|
84
|
+
\`\`\`json
|
|
85
|
+
{"passed": true, "issues": []}
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Draft spec to review
|
|
91
|
+
|
|
92
|
+
${specContent}`;
|
|
93
|
+
}
|
|
41
94
|
/**
|
|
42
95
|
* FORGE Prompt 2 — Reviewer / Validator Prompt Generator (from FORGE-quickref.md).
|
|
43
96
|
* Returns the populated reviewer prompt derived from an approved spec.
|
package/dist/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAMH,oCA0BC;AAMD,oCAgBC;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAMH,oCA0BC;AAcD,sCAuCC;AAMD,oCAgBC;AAzGD;;;GAGG;AACH,SAAgB,YAAY,CAAC,OAAe,EAAE,cAAsB;IAClE,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBP,cAAc,IAAI,6BAA6B;;;iBAGhC,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,aAAa,CAAC,WAAmB;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCP,WAAW,EAAE,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,WAAmB;IAC9C,OAAO;;;;;;;;;;;;;;EAcP,WAAW,EAAE,CAAC;AAChB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type LintIssueType = 'blank_field' | 'needs_human_input' | 'missing_section' | 'missing_module_boundary' | 'missing_interface_contract' | 'missing_non_goals' | 'missing_change_surface';
|
|
1
|
+
export type LintIssueType = 'blank_field' | 'needs_human_input' | 'missing_section' | 'missing_module_boundary' | 'missing_interface_contract' | 'missing_non_goals' | 'missing_change_surface' | 'missing_dependency_direction';
|
|
2
2
|
export interface LintIssue {
|
|
3
3
|
line: number;
|
|
4
4
|
type: LintIssueType;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,mBAAmB,GACnB,iBAAiB,GACjB,yBAAyB,GACzB,4BAA4B,GAC5B,mBAAmB,GACnB,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,mBAAmB,GACnB,iBAAiB,GACjB,yBAAyB,GACzB,4BAA4B,GAC5B,mBAAmB,GACnB,wBAAwB,GACxB,8BAA8B,CAAC;AAEnC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB"}
|