@planu/cli 4.10.6 → 4.10.7
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/CHANGELOG.md +11 -1
- package/dist/engine/local-first/tool-classification.d.ts +1 -0
- package/dist/engine/local-first/tool-classification.js +294 -100
- package/dist/tools/audit.js +1 -1
- package/dist/tools/challenge-spec.js +52 -2
- package/dist/tools/check-readiness.js +15 -8
- package/dist/tools/data-governance/audit-handler.js +21 -6
- package/dist/tools/data-governance/detect-handler.js +32 -15
- package/dist/tools/define-ui-contract.js +1 -4
- package/dist/tools/design-schema.js +1 -4
- package/dist/tools/detect-drift.js +48 -28
- package/dist/tools/flag-spec-gap.js +47 -12
- package/dist/tools/generate-sub-agent.js +2 -4
- package/dist/tools/orchestrate-locking.js +15 -4
- package/dist/tools/reverse-engineer/handler.js +9 -10
- package/dist/tools/rollback-release.js +20 -2
- package/dist/tools/spec-diff-handler.js +3 -3
- package/dist/tools/suggest-mcp-server.js +2 -4
- package/dist/tools/update-status/dod-gates.js +39 -24
- package/dist/tools/update-status/evidence-gate.js +6 -4
- package/dist/tools/update-status/index.js +3 -2
- package/dist/tools/update-status/transition-guard.js +33 -11
- package/dist/tools/validate-team-results.js +23 -1
- package/dist/transports/http-transport.js +13 -0
- package/package.json +10 -10
- package/planu-native.json +29 -8
- package/planu-plugin.json +35 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## [4.10.7] - 2026-07-07
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
- fix(SPEC-1114): reduce MCP token waste
|
|
5
|
+
|
|
6
|
+
### Chores
|
|
7
|
+
- chore(deps): update patch/minor dependencies
|
|
8
|
+
- chore(planu): clear released pending specs
|
|
9
|
+
|
|
10
|
+
|
|
1
11
|
## [4.10.6] - 2026-07-07
|
|
2
12
|
|
|
3
13
|
### Bug Fixes
|
|
@@ -4199,4 +4209,4 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · Versioning:
|
|
|
4199
4209
|
- Mermaid diagram generation (architecture, sequence, state machine, ER, data flow)
|
|
4200
4210
|
- Multi-language i18n (EN/ES/PT) for generated specs
|
|
4201
4211
|
- Clean Architecture (hexagonal) — engine, tools, storage, types layers
|
|
4202
|
-
- 10,857 tests with ≥95% coverage
|
|
4212
|
+
- 10,857 tests with ≥95% coverage
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolClassification } from '../../types/tool-classification.js';
|
|
2
2
|
export declare function getToolClassification(toolName: string): ToolClassification;
|
|
3
|
+
export declare function hasExplicitToolClassification(toolName: string): boolean;
|
|
3
4
|
export declare function isLocalFirstTool(toolName: string): boolean;
|
|
4
5
|
export declare function requiresLlmByDefault(toolName: string): boolean;
|
|
5
6
|
export declare function listToolClassifications(): ToolClassification[];
|
|
@@ -1,104 +1,295 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
1
|
+
const REGISTERED_TOOL_NAMES = [
|
|
2
|
+
'agent_run_history',
|
|
3
|
+
'analyze_spec_dependencies',
|
|
4
|
+
'approval_status',
|
|
5
|
+
'approve_spec',
|
|
6
|
+
'assess_merge_risk',
|
|
7
|
+
'assign_role',
|
|
8
|
+
'audit',
|
|
9
|
+
'audit_claude_config',
|
|
10
|
+
'audit_log_export',
|
|
11
|
+
'audit_schema_type_parity',
|
|
12
|
+
'audit_specs_drift',
|
|
13
|
+
'bump_spec_version',
|
|
14
|
+
'challenge_spec',
|
|
15
|
+
'check_compliance',
|
|
16
|
+
'check_config_health',
|
|
17
|
+
'check_spec_accuracy',
|
|
18
|
+
'check_versions',
|
|
19
|
+
'clarify_requirements',
|
|
20
|
+
'code_graph_status',
|
|
21
|
+
'compliance_coverage_report',
|
|
22
|
+
'compliance_gap_analysis',
|
|
23
|
+
'compliance_gate_status',
|
|
24
|
+
'compliance_score_report',
|
|
25
|
+
'config_health',
|
|
26
|
+
'configure_approval_policy',
|
|
27
|
+
'configure_code_graph',
|
|
28
|
+
'configure_compliance',
|
|
29
|
+
'configure_compliance_gate',
|
|
30
|
+
'configure_memory',
|
|
31
|
+
'configure_roles',
|
|
32
|
+
'configure_squad',
|
|
33
|
+
'configure_workers',
|
|
34
|
+
'consult_docs',
|
|
35
|
+
'context_budget',
|
|
36
|
+
'coverage_gap_analyzer',
|
|
37
|
+
'create_spec',
|
|
38
|
+
'data_retention_policy',
|
|
39
|
+
'define_spec_lint_rule',
|
|
40
|
+
'define_ui_contract',
|
|
41
|
+
'delete_spec_lint_rule',
|
|
42
|
+
'design_schema',
|
|
43
|
+
'detect_agent',
|
|
44
|
+
'detect_drift',
|
|
45
|
+
'discover_docs_url',
|
|
46
|
+
'discover_mcps',
|
|
47
|
+
'discover_registry',
|
|
48
|
+
'ears_lint',
|
|
49
|
+
'ecosystem_status',
|
|
50
|
+
'estimate',
|
|
51
|
+
'eval_rule',
|
|
52
|
+
'eval_skill',
|
|
53
|
+
'export_audit_trail',
|
|
54
|
+
'expose_spec_as_prompt',
|
|
55
|
+
'fix_schema_type_parity',
|
|
56
|
+
'free_tool',
|
|
57
|
+
'generate_adr',
|
|
58
|
+
'generate_api_client',
|
|
59
|
+
'generate_checklist',
|
|
60
|
+
'generate_compliance_report',
|
|
61
|
+
'generate_compliance_tests',
|
|
62
|
+
'generate_docs',
|
|
63
|
+
'generate_docs_site',
|
|
64
|
+
'generate_execution_plan',
|
|
65
|
+
'generate_orchestration_script',
|
|
66
|
+
'generate_rules',
|
|
67
|
+
'generate_skill',
|
|
68
|
+
'generate_sub_agent',
|
|
69
|
+
'generate_tests',
|
|
70
|
+
'generate_validation_schema',
|
|
71
|
+
'graph_specs',
|
|
72
|
+
'guided_tour',
|
|
73
|
+
'init_constitution',
|
|
74
|
+
'init_project',
|
|
75
|
+
'integrate_pm',
|
|
76
|
+
'issue_reviewer_token',
|
|
77
|
+
'learn_pattern',
|
|
78
|
+
'list_spec_lint_rules',
|
|
79
|
+
'list_spec_prompts',
|
|
80
|
+
'list_specs',
|
|
81
|
+
'manage_context',
|
|
82
|
+
'manage_git',
|
|
83
|
+
'manage_plugins',
|
|
84
|
+
'memory_status',
|
|
85
|
+
'oauth_status',
|
|
86
|
+
'onboarding_checklist',
|
|
87
|
+
'onboarding_progress',
|
|
88
|
+
'orchestrate',
|
|
89
|
+
'paradigm_report',
|
|
90
|
+
'pin_version',
|
|
91
|
+
'pro_tool',
|
|
92
|
+
'publish_registry',
|
|
93
|
+
'quick_start',
|
|
94
|
+
'reconcile_hooks',
|
|
95
|
+
'reconcile_rules',
|
|
96
|
+
'reconcile_skills',
|
|
97
|
+
'reconcile_spec',
|
|
98
|
+
'red_team',
|
|
99
|
+
'registry_install',
|
|
100
|
+
'registry_login',
|
|
101
|
+
'registry_logout',
|
|
102
|
+
'registry_publish',
|
|
103
|
+
'registry_search',
|
|
104
|
+
'registry_whoami',
|
|
105
|
+
'request_changes',
|
|
106
|
+
'reverse_engineer',
|
|
107
|
+
'rewrite_criteria_ears',
|
|
108
|
+
'run_mutation_hints',
|
|
109
|
+
'run_spec_lint',
|
|
110
|
+
'scaffold_plugin',
|
|
111
|
+
'scan_orphan_spec_refs',
|
|
112
|
+
'search_all_projects',
|
|
113
|
+
'set_locale',
|
|
114
|
+
'set_work_mode',
|
|
115
|
+
'skill_install',
|
|
116
|
+
'skill_search',
|
|
117
|
+
'spec_obesity_healer',
|
|
118
|
+
'squad_status',
|
|
119
|
+
'ssr_back_migration',
|
|
120
|
+
'start_oauth_flow',
|
|
121
|
+
'start_onboarding',
|
|
122
|
+
'suggest_mcp_server',
|
|
123
|
+
'suggest_mcps',
|
|
124
|
+
'suggest_stack',
|
|
125
|
+
'suggest_token_optimizer',
|
|
126
|
+
'suggest_tooling',
|
|
127
|
+
'summarize_spec',
|
|
128
|
+
'sync_ai_configs',
|
|
129
|
+
'tdd_scaffold',
|
|
130
|
+
'token_optimizer_status',
|
|
131
|
+
'tool',
|
|
132
|
+
'type_safety_gate',
|
|
133
|
+
'update_registry',
|
|
134
|
+
'update_status',
|
|
135
|
+
'update_status_batch',
|
|
136
|
+
'validate',
|
|
137
|
+
'validate_api_contract',
|
|
138
|
+
'validate_criteria_quality',
|
|
139
|
+
'validate_docs_registry',
|
|
140
|
+
'verify_spec_compliance',
|
|
141
|
+
'worker_status',
|
|
142
|
+
];
|
|
143
|
+
const LEGACY_OR_RUNTIME_TOOL_NAMES = [
|
|
144
|
+
'multi_agent_review',
|
|
145
|
+
'orchestrate_runtime',
|
|
146
|
+
'package_handoff',
|
|
147
|
+
'recommend_model',
|
|
148
|
+
];
|
|
149
|
+
const LLM_REQUIRED_TOOL_NAMES = ['create_spec'];
|
|
150
|
+
const HYBRID_TOOL_NAMES = [
|
|
151
|
+
'challenge_spec',
|
|
152
|
+
'clarify_requirements',
|
|
153
|
+
'consult_docs',
|
|
154
|
+
'define_ui_contract',
|
|
155
|
+
'design_schema',
|
|
156
|
+
'estimate',
|
|
157
|
+
'eval_skill',
|
|
158
|
+
'generate_adr',
|
|
159
|
+
'generate_api_client',
|
|
160
|
+
'generate_checklist',
|
|
161
|
+
'generate_compliance_report',
|
|
162
|
+
'generate_compliance_tests',
|
|
163
|
+
'generate_docs',
|
|
164
|
+
'generate_docs_site',
|
|
165
|
+
'generate_execution_plan',
|
|
166
|
+
'generate_orchestration_script',
|
|
167
|
+
'generate_rules',
|
|
168
|
+
'generate_skill',
|
|
169
|
+
'generate_sub_agent',
|
|
170
|
+
'generate_tests',
|
|
171
|
+
'generate_validation_schema',
|
|
172
|
+
'multi_agent_review',
|
|
173
|
+
'paradigm_report',
|
|
174
|
+
'reconcile_spec',
|
|
175
|
+
'red_team',
|
|
176
|
+
'reverse_engineer',
|
|
177
|
+
'rewrite_criteria_ears',
|
|
178
|
+
'spec_obesity_healer',
|
|
179
|
+
'ssr_back_migration',
|
|
180
|
+
'suggest_mcp_server',
|
|
181
|
+
'suggest_mcps',
|
|
182
|
+
'suggest_stack',
|
|
183
|
+
'suggest_token_optimizer',
|
|
184
|
+
'suggest_tooling',
|
|
185
|
+
'tdd_scaffold',
|
|
186
|
+
];
|
|
187
|
+
const NO_LLM_LOCAL_TOOL_NAMES = [
|
|
188
|
+
'approval_status',
|
|
189
|
+
'approve_spec',
|
|
190
|
+
'check_versions',
|
|
191
|
+
'code_graph_status',
|
|
192
|
+
'config_health',
|
|
193
|
+
'configure_approval_policy',
|
|
194
|
+
'configure_code_graph',
|
|
195
|
+
'configure_compliance',
|
|
196
|
+
'configure_compliance_gate',
|
|
197
|
+
'configure_memory',
|
|
198
|
+
'configure_roles',
|
|
199
|
+
'configure_squad',
|
|
200
|
+
'configure_workers',
|
|
201
|
+
'context_budget',
|
|
202
|
+
'detect_agent',
|
|
203
|
+
'discover_docs_url',
|
|
204
|
+
'discover_mcps',
|
|
205
|
+
'discover_registry',
|
|
206
|
+
'ears_lint',
|
|
207
|
+
'free_tool',
|
|
208
|
+
'issue_reviewer_token',
|
|
209
|
+
'list_spec_lint_rules',
|
|
210
|
+
'list_spec_prompts',
|
|
211
|
+
'list_specs',
|
|
212
|
+
'manage_context',
|
|
213
|
+
'manage_git',
|
|
214
|
+
'manage_plugins',
|
|
215
|
+
'memory_status',
|
|
216
|
+
'oauth_status',
|
|
217
|
+
'orchestrate',
|
|
218
|
+
'orchestrate_runtime',
|
|
219
|
+
'package_handoff',
|
|
220
|
+
'pin_version',
|
|
221
|
+
'pro_tool',
|
|
222
|
+
'registry_install',
|
|
223
|
+
'registry_login',
|
|
224
|
+
'registry_logout',
|
|
225
|
+
'registry_publish',
|
|
226
|
+
'registry_search',
|
|
227
|
+
'registry_whoami',
|
|
228
|
+
'run_spec_lint',
|
|
229
|
+
'scan_orphan_spec_refs',
|
|
230
|
+
'search_all_projects',
|
|
231
|
+
'set_locale',
|
|
232
|
+
'set_work_mode',
|
|
233
|
+
'skill_install',
|
|
234
|
+
'skill_search',
|
|
235
|
+
'squad_status',
|
|
236
|
+
'start_oauth_flow',
|
|
237
|
+
'summarize_spec',
|
|
238
|
+
'token_optimizer_status',
|
|
239
|
+
'tool',
|
|
240
|
+
'update_registry',
|
|
241
|
+
'update_status',
|
|
242
|
+
'update_status_batch',
|
|
243
|
+
'validate',
|
|
244
|
+
'worker_status',
|
|
245
|
+
];
|
|
246
|
+
const EXPLICIT_TOOL_NAMES = new Set([
|
|
247
|
+
...REGISTERED_TOOL_NAMES,
|
|
248
|
+
...LEGACY_OR_RUNTIME_TOOL_NAMES,
|
|
101
249
|
]);
|
|
250
|
+
const LLM_REQUIRED_TOOLS = new Set(LLM_REQUIRED_TOOL_NAMES);
|
|
251
|
+
const HYBRID_TOOLS = new Set(HYBRID_TOOL_NAMES);
|
|
252
|
+
const NO_LLM_LOCAL_TOOLS = new Set(NO_LLM_LOCAL_TOOL_NAMES);
|
|
253
|
+
function executionClassFor(toolName) {
|
|
254
|
+
if (LLM_REQUIRED_TOOLS.has(toolName)) {
|
|
255
|
+
return 'llm-required';
|
|
256
|
+
}
|
|
257
|
+
if (HYBRID_TOOLS.has(toolName)) {
|
|
258
|
+
return 'hybrid';
|
|
259
|
+
}
|
|
260
|
+
return 'local';
|
|
261
|
+
}
|
|
262
|
+
function reasonFor(toolName, executionClass) {
|
|
263
|
+
if (executionClass === 'llm-required') {
|
|
264
|
+
return 'Creates the primary spec artifact and requires language synthesis from user intent.';
|
|
265
|
+
}
|
|
266
|
+
if (executionClass === 'hybrid') {
|
|
267
|
+
return 'Runs local discovery, validation, or scaffolding first; only synthesis/review steps should use LLM tokens.';
|
|
268
|
+
}
|
|
269
|
+
if (NO_LLM_LOCAL_TOOLS.has(toolName)) {
|
|
270
|
+
return 'Uses deterministic local project state and should not call an LLM by default.';
|
|
271
|
+
}
|
|
272
|
+
return 'Processes local project artifacts and returns bounded summaries before any model-facing handoff.';
|
|
273
|
+
}
|
|
274
|
+
function tokenPolicyFor(toolName, executionClass) {
|
|
275
|
+
if (executionClass === 'llm-required') {
|
|
276
|
+
return 'llm-product';
|
|
277
|
+
}
|
|
278
|
+
if (executionClass === 'local' && NO_LLM_LOCAL_TOOLS.has(toolName)) {
|
|
279
|
+
return 'no-llm';
|
|
280
|
+
}
|
|
281
|
+
return 'summarize-first';
|
|
282
|
+
}
|
|
283
|
+
function buildClassification(toolName) {
|
|
284
|
+
const executionClass = executionClassFor(toolName);
|
|
285
|
+
return {
|
|
286
|
+
toolName,
|
|
287
|
+
executionClass,
|
|
288
|
+
tokenPolicy: tokenPolicyFor(toolName, executionClass),
|
|
289
|
+
reason: reasonFor(toolName, executionClass),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
const TOOL_CLASSIFICATIONS = new Map([...EXPLICIT_TOOL_NAMES].map((toolName) => [toolName, buildClassification(toolName)]));
|
|
102
293
|
export function getToolClassification(toolName) {
|
|
103
294
|
return (TOOL_CLASSIFICATIONS.get(toolName) ?? {
|
|
104
295
|
toolName,
|
|
@@ -107,6 +298,9 @@ export function getToolClassification(toolName) {
|
|
|
107
298
|
reason: 'Unregistered tools default to local preprocessing with bounded summaries.',
|
|
108
299
|
});
|
|
109
300
|
}
|
|
301
|
+
export function hasExplicitToolClassification(toolName) {
|
|
302
|
+
return TOOL_CLASSIFICATIONS.has(toolName);
|
|
303
|
+
}
|
|
110
304
|
export function isLocalFirstTool(toolName) {
|
|
111
305
|
return getToolClassification(toolName).executionClass !== 'llm-required';
|
|
112
306
|
}
|
package/dist/tools/audit.js
CHANGED
|
@@ -139,8 +139,8 @@ export async function handleAudit(args) {
|
|
|
139
139
|
findingsCount: String(result.findings.length),
|
|
140
140
|
}),
|
|
141
141
|
},
|
|
142
|
-
{ type: 'text', text: JSON.stringify(output, null, 2) },
|
|
143
142
|
],
|
|
143
|
+
structuredContent: output,
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
function scoreToGrade(score) {
|
|
@@ -32,6 +32,7 @@ const ALL_FOCUS_AREAS = [
|
|
|
32
32
|
'security',
|
|
33
33
|
'data-consistency',
|
|
34
34
|
];
|
|
35
|
+
const ACTIONABLE_RELEVANCE_MIN = 15;
|
|
35
36
|
/**
|
|
36
37
|
* SPEC-615 AC3: detect contradictions between spec criteria and prior decisions.
|
|
37
38
|
* Mutates failureScenarios in place. Best-effort — never throws.
|
|
@@ -242,8 +243,16 @@ export async function handleChallengeSpec(args, server) {
|
|
|
242
243
|
const match = prioritized.find((p) => p.scenario === s.scenario);
|
|
243
244
|
return match !== undefined ? { ...s, relevanceScore: match.relevanceScore } : s;
|
|
244
245
|
});
|
|
246
|
+
const prioritizedScenarios = new Set(prioritized.map((scenario) => scenario.scenario));
|
|
247
|
+
const actionableFailureScenarios = failureScenariosScored.filter((scenario) => prioritizedScenarios.has(scenario.scenario) ||
|
|
248
|
+
scenario.impact === 'critical' ||
|
|
249
|
+
scenario.impact === 'high' ||
|
|
250
|
+
isDomainRelevantScenario(scenario, specContent, knowledge) ||
|
|
251
|
+
(scenario.relevanceScore ?? computeScenarioRelevanceFallback(scenario)) >=
|
|
252
|
+
ACTIONABLE_RELEVANCE_MIN);
|
|
253
|
+
const suppressedScenarioCount = failureScenariosScored.length - actionableFailureScenarios.length;
|
|
245
254
|
const analysis = {
|
|
246
|
-
failureScenarios:
|
|
255
|
+
failureScenarios: actionableFailureScenarios,
|
|
247
256
|
concurrencyAnalysis,
|
|
248
257
|
scalabilityAssessment,
|
|
249
258
|
overallRisk,
|
|
@@ -262,6 +271,8 @@ export async function handleChallengeSpec(args, server) {
|
|
|
262
271
|
},
|
|
263
272
|
summary: {
|
|
264
273
|
totalScenarios: failureScenarios.length,
|
|
274
|
+
actionableScenarios: actionableFailureScenarios.length,
|
|
275
|
+
suppressedLowRelevanceScenarios: suppressedScenarioCount,
|
|
265
276
|
shownByDefault: 3,
|
|
266
277
|
mustAddressBeforeCoding: prioritizedSummary,
|
|
267
278
|
criticalImpact: failureScenarios.filter((s) => s.impact === 'critical').length,
|
|
@@ -354,9 +365,48 @@ export async function handleChallengeSpec(args, server) {
|
|
|
354
365
|
scenarioCount: String(failureScenarios.length),
|
|
355
366
|
}),
|
|
356
367
|
},
|
|
357
|
-
{
|
|
368
|
+
{
|
|
369
|
+
type: 'text',
|
|
370
|
+
text: `Actionable scenarios: ${String(actionableFailureScenarios.length)}` +
|
|
371
|
+
` | Suppressed low-relevance: ${String(suppressedScenarioCount)}` +
|
|
372
|
+
` | Overall risk: ${overallRisk}`,
|
|
373
|
+
},
|
|
358
374
|
{ type: 'text', text: humanSummary },
|
|
359
375
|
],
|
|
376
|
+
structuredContent: analysisPayload,
|
|
360
377
|
};
|
|
361
378
|
}
|
|
379
|
+
function computeScenarioRelevanceFallback(scenario) {
|
|
380
|
+
if (scenario.impact === 'critical') {
|
|
381
|
+
return 100;
|
|
382
|
+
}
|
|
383
|
+
if (scenario.impact === 'high') {
|
|
384
|
+
return 70;
|
|
385
|
+
}
|
|
386
|
+
if (scenario.probability === 'high') {
|
|
387
|
+
return 35;
|
|
388
|
+
}
|
|
389
|
+
return 0;
|
|
390
|
+
}
|
|
391
|
+
function isDomainRelevantScenario(scenario, specContent, knowledge) {
|
|
392
|
+
const haystack = `${scenario.scenario} ${scenario.currentHandling} ${scenario.requiredHandling}`
|
|
393
|
+
.toLowerCase()
|
|
394
|
+
.trim();
|
|
395
|
+
const specText = specContent.toLowerCase();
|
|
396
|
+
const framework = knowledge.framework?.toLowerCase() ?? '';
|
|
397
|
+
const isGameProject = knowledge.projectCategory === 'game' ||
|
|
398
|
+
['unity', 'godot', 'unreal', 'bevy', 'phaser', 'pygame'].includes(framework);
|
|
399
|
+
if (isGameProject && /\b(game|physics|cheat|balance|save|hud|player)\b/.test(haystack)) {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
if (/\b(database|query|index|pagination|transaction|cache)\b/.test(haystack) &&
|
|
403
|
+
/\b(database|query|index|pagination|transaction|cache|sql|postgres|sqlite)\b/.test(specText)) {
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
if (/\b(api|auth|jwt|session|csrf|injection|tenant|bola)\b/.test(haystack) &&
|
|
407
|
+
/\b(api|auth|jwt|session|csrf|injection|tenant|bola)\b/.test(specText)) {
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
362
412
|
//# sourceMappingURL=challenge-spec.js.map
|
|
@@ -6,6 +6,9 @@ import { buildCheckReadinessSummary } from '../engine/human-summary.js';
|
|
|
6
6
|
import { validateSpecFormat } from '../core/spec-validator.js';
|
|
7
7
|
import { resolveProjectId } from './resolve-project-id.js';
|
|
8
8
|
// ── Formatting helpers ───────────────────────────────────────────────────────
|
|
9
|
+
const MAX_VISIBLE_BLOCKERS = 8;
|
|
10
|
+
const MAX_VISIBLE_WARNINGS = 8;
|
|
11
|
+
const MAX_VISIBLE_RECOMMENDATIONS = 5;
|
|
9
12
|
function formatScore(score) {
|
|
10
13
|
if (score >= 90) {
|
|
11
14
|
return `${score}/100 (Excellent)`;
|
|
@@ -50,34 +53,38 @@ function formatReport(report) {
|
|
|
50
53
|
if (report.issues.blockers.length > 0) {
|
|
51
54
|
lines.push('## Blockers');
|
|
52
55
|
lines.push('');
|
|
53
|
-
for (const blocker of report.issues.blockers) {
|
|
56
|
+
for (const blocker of report.issues.blockers.slice(0, MAX_VISIBLE_BLOCKERS)) {
|
|
54
57
|
lines.push(`- BLOCKER: ${blocker}`);
|
|
55
58
|
}
|
|
59
|
+
if (report.issues.blockers.length > MAX_VISIBLE_BLOCKERS) {
|
|
60
|
+
lines.push(`- ...and ${String(report.issues.blockers.length - MAX_VISIBLE_BLOCKERS)} more`);
|
|
61
|
+
}
|
|
56
62
|
lines.push('');
|
|
57
63
|
}
|
|
58
64
|
// Warnings
|
|
59
65
|
if (report.issues.warnings.length > 0) {
|
|
60
66
|
lines.push('## Warnings');
|
|
61
67
|
lines.push('');
|
|
62
|
-
for (const warning of report.issues.warnings) {
|
|
68
|
+
for (const warning of report.issues.warnings.slice(0, MAX_VISIBLE_WARNINGS)) {
|
|
63
69
|
lines.push(`- WARNING: ${warning}`);
|
|
64
70
|
}
|
|
71
|
+
if (report.issues.warnings.length > MAX_VISIBLE_WARNINGS) {
|
|
72
|
+
lines.push(`- ...and ${String(report.issues.warnings.length - MAX_VISIBLE_WARNINGS)} more`);
|
|
73
|
+
}
|
|
65
74
|
lines.push('');
|
|
66
75
|
}
|
|
67
76
|
// Recommendations
|
|
68
77
|
if (report.recommendations.length > 0) {
|
|
69
78
|
lines.push('## Recommendations');
|
|
70
79
|
lines.push('');
|
|
71
|
-
for (const rec of report.recommendations) {
|
|
80
|
+
for (const rec of report.recommendations.slice(0, MAX_VISIBLE_RECOMMENDATIONS)) {
|
|
72
81
|
lines.push(`- ${rec}`);
|
|
73
82
|
}
|
|
83
|
+
if (report.recommendations.length > MAX_VISIBLE_RECOMMENDATIONS) {
|
|
84
|
+
lines.push(`- ...and ${String(report.recommendations.length - MAX_VISIBLE_RECOMMENDATIONS)} more`);
|
|
85
|
+
}
|
|
74
86
|
lines.push('');
|
|
75
87
|
}
|
|
76
|
-
// SPEC-042: Config health hint
|
|
77
|
-
lines.push('## Config Health');
|
|
78
|
-
lines.push('');
|
|
79
|
-
lines.push('- Run `check_config_health` to detect silent misconfigurations (tsconfig coverage, CI script references, build artifact gaps) that block DoR.');
|
|
80
|
-
lines.push('');
|
|
81
88
|
return lines.join('\n');
|
|
82
89
|
}
|
|
83
90
|
// ── Handler ──────────────────────────────────────────────────────────────────
|
|
@@ -3,6 +3,7 @@ import { specStore, knowledgeStore } from '../../storage/index.js';
|
|
|
3
3
|
import { ti } from '../../i18n/index.js';
|
|
4
4
|
import { detectPIIInSpec, detectLegalFramework } from '../../engine/pii-detector.js';
|
|
5
5
|
import { readFile } from 'node:fs/promises';
|
|
6
|
+
import { formatKeyValue } from '../output-formatter.js';
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
// privacy-notice subcommand
|
|
8
9
|
// ---------------------------------------------------------------------------
|
|
@@ -40,14 +41,21 @@ export async function handlePrivacyNotice(projectId) {
|
|
|
40
41
|
},
|
|
41
42
|
{
|
|
42
43
|
type: 'text',
|
|
43
|
-
text:
|
|
44
|
+
text: formatKeyValue({
|
|
44
45
|
subcommand: 'privacy-notice',
|
|
45
46
|
specsWithPII: privacyItems.length,
|
|
46
47
|
totalSpecs: specs.length,
|
|
47
|
-
|
|
48
|
-
}
|
|
48
|
+
noticeChars: notice.length,
|
|
49
|
+
}),
|
|
49
50
|
},
|
|
50
51
|
],
|
|
52
|
+
structuredContent: {
|
|
53
|
+
subcommand: 'privacy-notice',
|
|
54
|
+
specsWithPII: privacyItems.length,
|
|
55
|
+
totalSpecs: specs.length,
|
|
56
|
+
noticeText: notice,
|
|
57
|
+
items: privacyItems,
|
|
58
|
+
},
|
|
51
59
|
};
|
|
52
60
|
}
|
|
53
61
|
// ---------------------------------------------------------------------------
|
|
@@ -105,16 +113,23 @@ export async function handleAudit(projectId) {
|
|
|
105
113
|
},
|
|
106
114
|
{
|
|
107
115
|
type: 'text',
|
|
108
|
-
text:
|
|
116
|
+
text: formatKeyValue({
|
|
109
117
|
subcommand: 'audit',
|
|
110
118
|
totalSpecs: specs.length,
|
|
111
119
|
specsWithPII: auditItems.filter((i) => i.hasPII).length,
|
|
112
120
|
nonCompliantSpecs: nonCompliant,
|
|
113
121
|
framework,
|
|
114
|
-
|
|
115
|
-
}, null, 2),
|
|
122
|
+
}),
|
|
116
123
|
},
|
|
117
124
|
],
|
|
125
|
+
structuredContent: {
|
|
126
|
+
subcommand: 'audit',
|
|
127
|
+
totalSpecs: specs.length,
|
|
128
|
+
specsWithPII: auditItems.filter((i) => i.hasPII).length,
|
|
129
|
+
nonCompliantSpecs: nonCompliant,
|
|
130
|
+
framework,
|
|
131
|
+
items: auditItems,
|
|
132
|
+
},
|
|
118
133
|
};
|
|
119
134
|
}
|
|
120
135
|
// ---------------------------------------------------------------------------
|