nimai-core 0.2.2 → 0.3.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/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 +19 -0
- package/dist/lint.js.map +1 -1
- package/dist/prompts.d.ts +3 -2
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +39 -10
- package/dist/prompts.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/verdict.d.ts +39 -0
- package/dist/verdict.d.ts.map +1 -0
- package/dist/verdict.js +85 -0
- package/dist/verdict.js.map +1 -0
- package/package.json +1 -1
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;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,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;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -21,4 +21,5 @@ __exportStar(require("./context"), exports);
|
|
|
21
21
|
__exportStar(require("./prompts"), exports);
|
|
22
22
|
__exportStar(require("./clarification"), exports);
|
|
23
23
|
__exportStar(require("./discovery"), exports);
|
|
24
|
+
__exportStar(require("./verdict"), exports);
|
|
24
25
|
//# 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;AAC1B,kDAAgC;AAChC,8CAA4B"}
|
|
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;AAChC,8CAA4B;AAC5B,4CAA0B"}
|
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;AAkEnD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAQtD;AAsBD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CA6DxD"}
|
package/dist/lint.js
CHANGED
|
@@ -40,6 +40,10 @@ const fs = __importStar(require("fs"));
|
|
|
40
40
|
const BLANK_FIELD_RE = /_{3,}/;
|
|
41
41
|
// Matches [NEEDS HUMAN INPUT...] flags
|
|
42
42
|
const NHFI_RE = /\[NEEDS HUMAN INPUT/i;
|
|
43
|
+
// Matches pre-checked list items: "- [x] ..." or "* [x] ..."
|
|
44
|
+
const PRE_CHECKED_AC_RE = /^[-*]\s+\[x\]/im;
|
|
45
|
+
// Matches the nimai-spec marker (with or without date)
|
|
46
|
+
const NIMAI_MARKER_RE = /<!--\s*nimai-spec[\s:]/;
|
|
43
47
|
// Required top-level sections (by heading text, case-insensitive)
|
|
44
48
|
const REQUIRED_SECTIONS = [
|
|
45
49
|
'pre-flight',
|
|
@@ -129,12 +133,27 @@ function lintContent(content) {
|
|
|
129
133
|
issues.push(issue(lineNum, 'needs_human_input', `Unresolved [NEEDS HUMAN INPUT] flag on line ${lineNum}`));
|
|
130
134
|
}
|
|
131
135
|
}
|
|
136
|
+
// Pre-checked acceptance criteria — hard fail: ACs must be unchecked in a draft spec
|
|
137
|
+
if (PRE_CHECKED_AC_RE.test(content)) {
|
|
138
|
+
const matchLines = lines.reduce((acc, l, i) => {
|
|
139
|
+
if (/^[-*]\s+\[x\]/i.test(l))
|
|
140
|
+
acc.push(i + 1);
|
|
141
|
+
return acc;
|
|
142
|
+
}, []);
|
|
143
|
+
for (const lineNum of matchLines) {
|
|
144
|
+
issues.push(issue(lineNum, 'pre_checked_ac', `Pre-checked list item on line ${lineNum} — acceptance criteria must be unchecked ([ ]) in a draft spec`));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
132
147
|
const lower = content.toLowerCase();
|
|
133
148
|
for (const section of REQUIRED_SECTIONS) {
|
|
134
149
|
if (!lower.includes(section)) {
|
|
135
150
|
issues.push(issue(0, 'missing_section', `Required section missing: "${section}"`));
|
|
136
151
|
}
|
|
137
152
|
}
|
|
153
|
+
// Missing nimai-spec marker — advisory: spec was not created or registered by nimai
|
|
154
|
+
if (!NIMAI_MARKER_RE.test(content)) {
|
|
155
|
+
issues.push(advisoryIssue(0, 'missing_marker', 'No <!-- nimai-spec --> marker found — add it so nimai can discover this spec automatically (nimai new stamps it)'));
|
|
156
|
+
}
|
|
138
157
|
const riskTier = detectRiskTier(content);
|
|
139
158
|
const coding = isCodingSpec(content);
|
|
140
159
|
for (const rule of ADVISORY_RULES) {
|
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
|
@@ -16,9 +16,10 @@ export declare function buildPrompt1(request: string, contextSummary: string): s
|
|
|
16
16
|
* The reviewing LLM MUST end its response with a machine-parseable JSON verdict block:
|
|
17
17
|
* ## Verdict
|
|
18
18
|
* ```json
|
|
19
|
-
* {"passed": true, "issues": []}
|
|
19
|
+
* {"passed": true, "schema_version": "2", "issues": []}
|
|
20
20
|
* ```
|
|
21
|
-
*
|
|
21
|
+
* Schema version 2: issues are objects with dimension, severity, and detail fields.
|
|
22
|
+
* The host agent parses this block (last fenced JSON block) to drive the spec-review loop.
|
|
22
23
|
*/
|
|
23
24
|
export declare function buildPrompt15(specContent: string): string;
|
|
24
25
|
/**
|
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
|
|
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;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAmEzD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgBxD"}
|
package/dist/prompts.js
CHANGED
|
@@ -47,9 +47,10 @@ Loose request: ${request}`;
|
|
|
47
47
|
* The reviewing LLM MUST end its response with a machine-parseable JSON verdict block:
|
|
48
48
|
* ## Verdict
|
|
49
49
|
* ```json
|
|
50
|
-
* {"passed": true, "issues": []}
|
|
50
|
+
* {"passed": true, "schema_version": "2", "issues": []}
|
|
51
51
|
* ```
|
|
52
|
-
*
|
|
52
|
+
* Schema version 2: issues are objects with dimension, severity, and detail fields.
|
|
53
|
+
* The host agent parses this block (last fenced JSON block) to drive the spec-review loop.
|
|
53
54
|
*/
|
|
54
55
|
function buildPrompt15(specContent) {
|
|
55
56
|
return `You are a Specification Quality Reviewer operating under the FORGE framework.
|
|
@@ -59,30 +60,58 @@ Do NOT assess any code, code diffs, or implementation output.
|
|
|
59
60
|
|
|
60
61
|
## What to check
|
|
61
62
|
|
|
62
|
-
Evaluate each dimension
|
|
63
|
+
Evaluate each dimension. For each one, cite the specific line, section, or text that supports your verdict.
|
|
64
|
+
A verdict without citation is treated as NO_GO — do not assert PASS without evidence.
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
**Dimensions:**
|
|
67
|
+
|
|
68
|
+
1. **Binary acceptance criteria** — are all sub-task ACs measurable and unambiguous? Are any ACs pre-checked (- [x]) in the draft, which is always invalid?
|
|
69
|
+
2. **Scope coherence** — are in-scope and out-of-scope boundaries clearly stated and non-contradictory? Check for conflicts between conceptual terminology (e.g., state names, entity names used in descriptions) and persisted/modelled representations (e.g., enums, schemas, data shapes). Any mismatch is a HARD_FAIL.
|
|
66
70
|
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?
|
|
71
|
+
4. **Decomposition realism** — can each sub-task be completed within the stated 2-hour limit by a skilled agent? Check that sub-task dependencies are stated explicitly (if task B requires task A's output, that must be documented).
|
|
68
72
|
5. **Start-without-clarification viability** — can an agent begin immediately with the context provided, without asking the human for more information?
|
|
73
|
+
6. **Internal consistency** — are terms, names, and concepts used consistently throughout the spec? Flag any case where the same entity is described differently in different sections (e.g., "webhook event" in scope, "push notification" in ACs — are these the same thing?).
|
|
74
|
+
|
|
75
|
+
## Severity classification
|
|
76
|
+
|
|
77
|
+
For each issue, assign a severity:
|
|
78
|
+
- **HARD_FAIL** — must be fixed before any agent attempts implementation; blocks build
|
|
79
|
+
- **SOFT_FAIL** — significant gap, should be fixed but builder may proceed with explicit override
|
|
80
|
+
- **NOTE** — advisory observation; does not block
|
|
81
|
+
|
|
82
|
+
A spec passes (passed: true) only if it has zero HARD_FAIL issues.
|
|
69
83
|
|
|
70
84
|
## Output format
|
|
71
85
|
|
|
72
|
-
For each
|
|
86
|
+
For each dimension, write:
|
|
87
|
+
**[PASS|FAIL] Dimension name** — one-sentence rationale. *Evidence: cite the specific section/line/text.*
|
|
73
88
|
|
|
74
|
-
Then write a consolidated
|
|
89
|
+
Then write a consolidated remediation list for all FAIL dimensions.
|
|
75
90
|
|
|
76
91
|
Note: implementation correctness is explicitly out of scope for this review.
|
|
77
92
|
|
|
78
93
|
## Important
|
|
79
94
|
|
|
80
95
|
Always end your response with the following verdict block as the **final section**, regardless of pass/fail outcome.
|
|
81
|
-
The host agent parses
|
|
96
|
+
The host agent parses the **last fenced JSON block** in your response — if it is absent or malformed, the host treats the result as a hard failure and escalates to the human.
|
|
97
|
+
|
|
98
|
+
The verdict block format (schema version 2):
|
|
82
99
|
|
|
83
100
|
## Verdict
|
|
84
101
|
\`\`\`json
|
|
85
|
-
{
|
|
102
|
+
{
|
|
103
|
+
"passed": false,
|
|
104
|
+
"schema_version": "2",
|
|
105
|
+
"issues": [
|
|
106
|
+
{"dimension": "scope_coherence", "severity": "HARD_FAIL", "detail": "Conceptual state 'active' not mapped to persisted enum value"},
|
|
107
|
+
{"dimension": "decomposition_realism", "severity": "NOTE", "detail": "Sub-task 3 may exceed 2h limit if schema migration is complex"}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
If the spec passes all dimensions with no HARD_FAIL issues, use:
|
|
113
|
+
\`\`\`json
|
|
114
|
+
{"passed": true, "schema_version": "2", "issues": []}
|
|
86
115
|
\`\`\`
|
|
87
116
|
|
|
88
117
|
---
|
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;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;AAMH,oCA0BC;AAeD,sCAmEC;AAMD,oCAgBC;AAtID;;;GAGG;AACH,SAAgB,YAAY,CAAC,OAAe,EAAE,cAAsB;IAClE,OAAO;;;;;;;;;;;;;;;;;;;;;EAqBP,cAAc,IAAI,6BAA6B;;;iBAGhC,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,aAAa,CAAC,WAAmB;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEP,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' | 'missing_dependency_direction';
|
|
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' | 'pre_checked_ac' | 'missing_marker';
|
|
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,GACxB,8BAA8B,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,GAC9B,gBAAgB,GAChB,gBAAgB,CAAC;AAErB,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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verdict-block parser for FORGE Prompt 1.5 responses.
|
|
3
|
+
*
|
|
4
|
+
* The reviewing LLM must end its response with a fenced JSON block:
|
|
5
|
+
* ```json
|
|
6
|
+
* {"passed": true, "issues": []}
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* This module parses that block and normalises the result.
|
|
10
|
+
* Malformed or absent blocks return { passed: false } to ensure the loop
|
|
11
|
+
* escalates rather than silently treating ambiguous output as a pass.
|
|
12
|
+
*
|
|
13
|
+
* Schema versions:
|
|
14
|
+
* v1: issues is string[]
|
|
15
|
+
* v2: issues is VerdictIssue[] with dimension/severity/detail fields
|
|
16
|
+
* Both are accepted; v1 strings are wrapped as VerdictIssue with detail only.
|
|
17
|
+
*/
|
|
18
|
+
export interface VerdictIssue {
|
|
19
|
+
/** Which review dimension this issue relates to (v2+) */
|
|
20
|
+
dimension?: string;
|
|
21
|
+
/** Severity classification (v2+) */
|
|
22
|
+
severity?: 'HARD_FAIL' | 'SOFT_FAIL' | 'NOTE';
|
|
23
|
+
/** Human-readable description of the issue */
|
|
24
|
+
detail: string;
|
|
25
|
+
}
|
|
26
|
+
export interface Verdict {
|
|
27
|
+
passed: boolean;
|
|
28
|
+
issues: VerdictIssue[];
|
|
29
|
+
/** Present when schema_version "2" block was parsed */
|
|
30
|
+
schema_version?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Sentinel returned when the block is absent or malformed */
|
|
33
|
+
export declare const MALFORMED_VERDICT: Verdict;
|
|
34
|
+
/**
|
|
35
|
+
* Parse the last fenced JSON block from an LLM response.
|
|
36
|
+
* Returns a normalised Verdict, or MALFORMED_VERDICT on any parse error.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseVerdict(llmResponse: string): Verdict;
|
|
39
|
+
//# sourceMappingURL=verdict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict.d.ts","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IAC9C,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,EAAE,OAA4G,CAAC;AAE7I;;;GAGG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAqCzD"}
|
package/dist/verdict.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Verdict-block parser for FORGE Prompt 1.5 responses.
|
|
4
|
+
*
|
|
5
|
+
* The reviewing LLM must end its response with a fenced JSON block:
|
|
6
|
+
* ```json
|
|
7
|
+
* {"passed": true, "issues": []}
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* This module parses that block and normalises the result.
|
|
11
|
+
* Malformed or absent blocks return { passed: false } to ensure the loop
|
|
12
|
+
* escalates rather than silently treating ambiguous output as a pass.
|
|
13
|
+
*
|
|
14
|
+
* Schema versions:
|
|
15
|
+
* v1: issues is string[]
|
|
16
|
+
* v2: issues is VerdictIssue[] with dimension/severity/detail fields
|
|
17
|
+
* Both are accepted; v1 strings are wrapped as VerdictIssue with detail only.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.MALFORMED_VERDICT = void 0;
|
|
21
|
+
exports.parseVerdict = parseVerdict;
|
|
22
|
+
/** Sentinel returned when the block is absent or malformed */
|
|
23
|
+
exports.MALFORMED_VERDICT = { passed: false, issues: [{ detail: 'Verdict block absent or malformed — treating as failure' }] };
|
|
24
|
+
/**
|
|
25
|
+
* Parse the last fenced JSON block from an LLM response.
|
|
26
|
+
* Returns a normalised Verdict, or MALFORMED_VERDICT on any parse error.
|
|
27
|
+
*/
|
|
28
|
+
function parseVerdict(llmResponse) {
|
|
29
|
+
const lastBlock = extractLastJsonBlock(llmResponse);
|
|
30
|
+
if (!lastBlock)
|
|
31
|
+
return exports.MALFORMED_VERDICT;
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = JSON.parse(lastBlock);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return exports.MALFORMED_VERDICT;
|
|
38
|
+
}
|
|
39
|
+
if (!isPlainObject(raw))
|
|
40
|
+
return exports.MALFORMED_VERDICT;
|
|
41
|
+
if (typeof raw.passed !== 'boolean')
|
|
42
|
+
return exports.MALFORMED_VERDICT;
|
|
43
|
+
if (!Array.isArray(raw.issues))
|
|
44
|
+
return exports.MALFORMED_VERDICT;
|
|
45
|
+
const issues = [];
|
|
46
|
+
for (const item of raw.issues) {
|
|
47
|
+
if (typeof item === 'string') {
|
|
48
|
+
// v1 format: plain string
|
|
49
|
+
issues.push({ detail: item });
|
|
50
|
+
}
|
|
51
|
+
else if (isPlainObject(item) && typeof item.detail === 'string') {
|
|
52
|
+
// v2 format: object with at least detail field
|
|
53
|
+
const vi = { detail: item.detail };
|
|
54
|
+
if (typeof item.dimension === 'string')
|
|
55
|
+
vi.dimension = item.dimension;
|
|
56
|
+
if (item.severity === 'HARD_FAIL' || item.severity === 'SOFT_FAIL' || item.severity === 'NOTE') {
|
|
57
|
+
vi.severity = item.severity;
|
|
58
|
+
}
|
|
59
|
+
issues.push(vi);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Unexpected item shape — treat whole verdict as malformed
|
|
63
|
+
return exports.MALFORMED_VERDICT;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const verdict = { passed: raw.passed, issues };
|
|
67
|
+
if (typeof raw.schema_version === 'string')
|
|
68
|
+
verdict.schema_version = raw.schema_version;
|
|
69
|
+
return verdict;
|
|
70
|
+
}
|
|
71
|
+
/** Extract the text of the last ```json ... ``` fenced block in the response */
|
|
72
|
+
function extractLastJsonBlock(text) {
|
|
73
|
+
// Match all ```json ... ``` fenced blocks (non-greedy)
|
|
74
|
+
const re = /```json\s*([\s\S]*?)```/g;
|
|
75
|
+
let last = null;
|
|
76
|
+
let match;
|
|
77
|
+
while ((match = re.exec(text)) !== null) {
|
|
78
|
+
last = match[1].trim();
|
|
79
|
+
}
|
|
80
|
+
return last;
|
|
81
|
+
}
|
|
82
|
+
function isPlainObject(v) {
|
|
83
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=verdict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict.js","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;;AAyBH,oCAqCC;AA5CD,8DAA8D;AACjD,QAAA,iBAAiB,GAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,yDAAyD,EAAE,CAAC,EAAE,CAAC;AAE7I;;;GAGG;AACH,SAAgB,YAAY,CAAC,WAAmB;IAC9C,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS;QAAE,OAAO,yBAAiB,CAAC;IAEzC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,yBAAiB,CAAC;IAC3B,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,yBAAiB,CAAC;IAClD,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,yBAAiB,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,yBAAiB,CAAC;IAEzD,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,0BAA0B;YAC1B,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAChC,CAAC;aAAM,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClE,+CAA+C;YAC/C,MAAM,EAAE,GAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YACjD,IAAI,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;gBAAE,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YACtE,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gBAC/F,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC9B,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,2DAA2D;YAC3D,OAAO,yBAAiB,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAY,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IACxD,IAAI,OAAO,GAAG,CAAC,cAAc,KAAK,QAAQ;QAAE,OAAO,CAAC,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC;IACxF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gFAAgF;AAChF,SAAS,oBAAoB,CAAC,IAAY;IACxC,uDAAuD;IACvD,MAAM,EAAE,GAAG,0BAA0B,CAAC;IACtC,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC"}
|