pm-orchestrator-runner 1.0.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/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/cli/cli-interface.d.ts +150 -0
- package/dist/cli/cli-interface.d.ts.map +1 -0
- package/dist/cli/cli-interface.js +606 -0
- package/dist/cli/cli-interface.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +243 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/llm-sentinel.d.ts +15 -0
- package/dist/cli/llm-sentinel.d.ts.map +1 -0
- package/dist/cli/llm-sentinel.js +184 -0
- package/dist/cli/llm-sentinel.js.map +1 -0
- package/dist/config/configuration-manager.d.ts +149 -0
- package/dist/config/configuration-manager.d.ts.map +1 -0
- package/dist/config/configuration-manager.js +241 -0
- package/dist/config/configuration-manager.js.map +1 -0
- package/dist/continuation/continuation-control-manager.d.ts +154 -0
- package/dist/continuation/continuation-control-manager.d.ts.map +1 -0
- package/dist/continuation/continuation-control-manager.js +303 -0
- package/dist/continuation/continuation-control-manager.js.map +1 -0
- package/dist/core/runner-core.d.ts +474 -0
- package/dist/core/runner-core.d.ts.map +1 -0
- package/dist/core/runner-core.js +1311 -0
- package/dist/core/runner-core.js.map +1 -0
- package/dist/errors/error-codes.d.ts +105 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +198 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/errors/runner-error.d.ts +14 -0
- package/dist/errors/runner-error.d.ts.map +1 -0
- package/dist/errors/runner-error.js +33 -0
- package/dist/errors/runner-error.js.map +1 -0
- package/dist/evidence/evidence-manager.d.ts +112 -0
- package/dist/evidence/evidence-manager.d.ts.map +1 -0
- package/dist/evidence/evidence-manager.js +337 -0
- package/dist/evidence/evidence-manager.js.map +1 -0
- package/dist/executor/claude-code-executor.d.ts +136 -0
- package/dist/executor/claude-code-executor.d.ts.map +1 -0
- package/dist/executor/claude-code-executor.js +643 -0
- package/dist/executor/claude-code-executor.js.map +1 -0
- package/dist/executor/deterministic-executor.d.ts +40 -0
- package/dist/executor/deterministic-executor.d.ts.map +1 -0
- package/dist/executor/deterministic-executor.js +269 -0
- package/dist/executor/deterministic-executor.js.map +1 -0
- package/dist/lifecycle/lifecycle-controller.d.ts +270 -0
- package/dist/lifecycle/lifecycle-controller.d.ts.map +1 -0
- package/dist/lifecycle/lifecycle-controller.js +596 -0
- package/dist/lifecycle/lifecycle-controller.js.map +1 -0
- package/dist/limits/resource-limit-manager.d.ts +200 -0
- package/dist/limits/resource-limit-manager.d.ts.map +1 -0
- package/dist/limits/resource-limit-manager.js +376 -0
- package/dist/limits/resource-limit-manager.js.map +1 -0
- package/dist/locks/lock-manager.d.ts +116 -0
- package/dist/locks/lock-manager.d.ts.map +1 -0
- package/dist/locks/lock-manager.js +306 -0
- package/dist/locks/lock-manager.js.map +1 -0
- package/dist/logging/index.d.ts +8 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +22 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/sensitive-data-masker.d.ts +90 -0
- package/dist/logging/sensitive-data-masker.d.ts.map +1 -0
- package/dist/logging/sensitive-data-masker.js +228 -0
- package/dist/logging/sensitive-data-masker.js.map +1 -0
- package/dist/logging/task-log-manager.d.ts +215 -0
- package/dist/logging/task-log-manager.d.ts.map +1 -0
- package/dist/logging/task-log-manager.js +743 -0
- package/dist/logging/task-log-manager.js.map +1 -0
- package/dist/mediation/fail-closed-runner.d.ts +131 -0
- package/dist/mediation/fail-closed-runner.d.ts.map +1 -0
- package/dist/mediation/fail-closed-runner.js +245 -0
- package/dist/mediation/fail-closed-runner.js.map +1 -0
- package/dist/mediation/llm-client-with-evidence.d.ts +123 -0
- package/dist/mediation/llm-client-with-evidence.d.ts.map +1 -0
- package/dist/mediation/llm-client-with-evidence.js +245 -0
- package/dist/mediation/llm-client-with-evidence.js.map +1 -0
- package/dist/mediation/llm-client.d.ts +102 -0
- package/dist/mediation/llm-client.d.ts.map +1 -0
- package/dist/mediation/llm-client.js +206 -0
- package/dist/mediation/llm-client.js.map +1 -0
- package/dist/mediation/llm-evidence-manager.d.ts +108 -0
- package/dist/mediation/llm-evidence-manager.d.ts.map +1 -0
- package/dist/mediation/llm-evidence-manager.js +230 -0
- package/dist/mediation/llm-evidence-manager.js.map +1 -0
- package/dist/mediation/llm-mediation-layer.d.ts +175 -0
- package/dist/mediation/llm-mediation-layer.d.ts.map +1 -0
- package/dist/mediation/llm-mediation-layer.js +315 -0
- package/dist/mediation/llm-mediation-layer.js.map +1 -0
- package/dist/mediation/llm-sentinel.d.ts +107 -0
- package/dist/mediation/llm-sentinel.d.ts.map +1 -0
- package/dist/mediation/llm-sentinel.js +187 -0
- package/dist/mediation/llm-sentinel.js.map +1 -0
- package/dist/mediation/real-llm-mediation-layer.d.ts +104 -0
- package/dist/mediation/real-llm-mediation-layer.d.ts.map +1 -0
- package/dist/mediation/real-llm-mediation-layer.js +322 -0
- package/dist/mediation/real-llm-mediation-layer.js.map +1 -0
- package/dist/mediation/verdict-reporter.d.ts +61 -0
- package/dist/mediation/verdict-reporter.d.ts.map +1 -0
- package/dist/mediation/verdict-reporter.js +178 -0
- package/dist/mediation/verdict-reporter.js.map +1 -0
- package/dist/models/enums.d.ts +133 -0
- package/dist/models/enums.d.ts.map +1 -0
- package/dist/models/enums.js +201 -0
- package/dist/models/enums.js.map +1 -0
- package/dist/models/evidence.d.ts +60 -0
- package/dist/models/evidence.d.ts.map +1 -0
- package/dist/models/evidence.js +135 -0
- package/dist/models/evidence.js.map +1 -0
- package/dist/models/execution-result.d.ts +89 -0
- package/dist/models/execution-result.d.ts.map +1 -0
- package/dist/models/execution-result.js +197 -0
- package/dist/models/execution-result.js.map +1 -0
- package/dist/models/file-lock.d.ts +62 -0
- package/dist/models/file-lock.d.ts.map +1 -0
- package/dist/models/file-lock.js +133 -0
- package/dist/models/file-lock.js.map +1 -0
- package/dist/models/index.d.ts +12 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +91 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/repl/index.d.ts +7 -0
- package/dist/models/repl/index.d.ts.map +1 -0
- package/dist/models/repl/index.js +32 -0
- package/dist/models/repl/index.js.map +1 -0
- package/dist/models/repl/model-registry.d.ts +73 -0
- package/dist/models/repl/model-registry.d.ts.map +1 -0
- package/dist/models/repl/model-registry.js +116 -0
- package/dist/models/repl/model-registry.js.map +1 -0
- package/dist/models/repl/repl-state.d.ts +86 -0
- package/dist/models/repl/repl-state.d.ts.map +1 -0
- package/dist/models/repl/repl-state.js +152 -0
- package/dist/models/repl/repl-state.js.map +1 -0
- package/dist/models/repl/task-log.d.ts +247 -0
- package/dist/models/repl/task-log.d.ts.map +1 -0
- package/dist/models/repl/task-log.js +178 -0
- package/dist/models/repl/task-log.js.map +1 -0
- package/dist/models/session.d.ts +71 -0
- package/dist/models/session.d.ts.map +1 -0
- package/dist/models/session.js +140 -0
- package/dist/models/session.js.map +1 -0
- package/dist/models/supporting.d.ts +97 -0
- package/dist/models/supporting.d.ts.map +1 -0
- package/dist/models/supporting.js +208 -0
- package/dist/models/supporting.js.map +1 -0
- package/dist/models/task.d.ts +77 -0
- package/dist/models/task.d.ts.map +1 -0
- package/dist/models/task.js +170 -0
- package/dist/models/task.js.map +1 -0
- package/dist/output/output-control-manager.d.ts +217 -0
- package/dist/output/output-control-manager.d.ts.map +1 -0
- package/dist/output/output-control-manager.js +378 -0
- package/dist/output/output-control-manager.js.map +1 -0
- package/dist/pool/agent-pool.d.ts +284 -0
- package/dist/pool/agent-pool.d.ts.map +1 -0
- package/dist/pool/agent-pool.js +451 -0
- package/dist/pool/agent-pool.js.map +1 -0
- package/dist/repl/commands/index.d.ts +12 -0
- package/dist/repl/commands/index.d.ts.map +1 -0
- package/dist/repl/commands/index.js +26 -0
- package/dist/repl/commands/index.js.map +1 -0
- package/dist/repl/commands/init.d.ts +31 -0
- package/dist/repl/commands/init.d.ts.map +1 -0
- package/dist/repl/commands/init.js +234 -0
- package/dist/repl/commands/init.js.map +1 -0
- package/dist/repl/commands/keys.d.ts +63 -0
- package/dist/repl/commands/keys.d.ts.map +1 -0
- package/dist/repl/commands/keys.js +114 -0
- package/dist/repl/commands/keys.js.map +1 -0
- package/dist/repl/commands/logs.d.ts +91 -0
- package/dist/repl/commands/logs.d.ts.map +1 -0
- package/dist/repl/commands/logs.js +200 -0
- package/dist/repl/commands/logs.js.map +1 -0
- package/dist/repl/commands/model.d.ts +85 -0
- package/dist/repl/commands/model.d.ts.map +1 -0
- package/dist/repl/commands/model.js +225 -0
- package/dist/repl/commands/model.js.map +1 -0
- package/dist/repl/commands/models.d.ts +50 -0
- package/dist/repl/commands/models.d.ts.map +1 -0
- package/dist/repl/commands/models.js +180 -0
- package/dist/repl/commands/models.js.map +1 -0
- package/dist/repl/commands/provider.d.ts +79 -0
- package/dist/repl/commands/provider.d.ts.map +1 -0
- package/dist/repl/commands/provider.js +291 -0
- package/dist/repl/commands/provider.js.map +1 -0
- package/dist/repl/commands/session.d.ts +50 -0
- package/dist/repl/commands/session.d.ts.map +1 -0
- package/dist/repl/commands/session.js +152 -0
- package/dist/repl/commands/session.js.map +1 -0
- package/dist/repl/commands/status.d.ts +55 -0
- package/dist/repl/commands/status.d.ts.map +1 -0
- package/dist/repl/commands/status.js +182 -0
- package/dist/repl/commands/status.js.map +1 -0
- package/dist/repl/index.d.ts +6 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +25 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl/repl-interface.d.ts +371 -0
- package/dist/repl/repl-interface.d.ts.map +1 -0
- package/dist/repl/repl-interface.js +1214 -0
- package/dist/repl/repl-interface.js.map +1 -0
- package/dist/session/session-manager.d.ts +85 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +217 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/supervisor/executor-supervisor.d.ts +90 -0
- package/dist/supervisor/executor-supervisor.d.ts.map +1 -0
- package/dist/supervisor/executor-supervisor.js +223 -0
- package/dist/supervisor/executor-supervisor.js.map +1 -0
- package/dist/supervisor/index.d.ts +5 -0
- package/dist/supervisor/index.d.ts.map +1 -0
- package/dist/supervisor/index.js +9 -0
- package/dist/supervisor/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LLM Mediation Layer
|
|
4
|
+
*
|
|
5
|
+
* Sits ABOVE Runner Core to handle ALL user interaction and decision making.
|
|
6
|
+
* Runner Core returns structured signals (facts only), this layer:
|
|
7
|
+
* - Generates natural language questions to users
|
|
8
|
+
* - Interprets user responses
|
|
9
|
+
* - Normalizes responses into explicit tasks for Runner
|
|
10
|
+
*
|
|
11
|
+
* ARCHITECTURAL RULES:
|
|
12
|
+
* - Runner MUST NOT contain conversational phrasing logic
|
|
13
|
+
* - Runner MUST NOT contain file-name-specific logic
|
|
14
|
+
* - This layer is the ONLY component that asks questions
|
|
15
|
+
* - This layer decides how to phrase clarification questions
|
|
16
|
+
* - This layer decides follow-up actions based on user answers
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.LLMMediationLayer = void 0;
|
|
20
|
+
/**
|
|
21
|
+
* LLM Mediation Layer
|
|
22
|
+
*
|
|
23
|
+
* Handles all user interaction and decision making.
|
|
24
|
+
* Receives structured signals from Runner, generates natural language,
|
|
25
|
+
* interprets user responses, and normalizes them into explicit tasks.
|
|
26
|
+
*/
|
|
27
|
+
class LLMMediationLayer {
|
|
28
|
+
/**
|
|
29
|
+
* Process Runner signal and generate appropriate output
|
|
30
|
+
*
|
|
31
|
+
* @param signal - Structured signal from Runner Core
|
|
32
|
+
* @returns Mediation output (question to user or normalized task)
|
|
33
|
+
*/
|
|
34
|
+
processRunnerSignal(signal) {
|
|
35
|
+
// If no clarification needed, pass through
|
|
36
|
+
if (!signal.clarification_needed) {
|
|
37
|
+
return {
|
|
38
|
+
needs_user_input: false,
|
|
39
|
+
status_message: this.generateStatusMessage(signal),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Generate appropriate question based on clarification reason
|
|
43
|
+
switch (signal.clarification_reason) {
|
|
44
|
+
case 'target_file_exists':
|
|
45
|
+
return this.handleFileExistsCase(signal);
|
|
46
|
+
case 'target_file_ambiguous':
|
|
47
|
+
return this.handleFileAmbiguousCase(signal);
|
|
48
|
+
case 'target_action_ambiguous':
|
|
49
|
+
return this.handleActionAmbiguousCase(signal);
|
|
50
|
+
case 'missing_required_info':
|
|
51
|
+
return this.handleMissingInfoCase(signal);
|
|
52
|
+
default:
|
|
53
|
+
// Unknown reason - ask for general clarification
|
|
54
|
+
return {
|
|
55
|
+
needs_user_input: true,
|
|
56
|
+
question: 'タスクの詳細を教えてください。',
|
|
57
|
+
suggested_responses: [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse user response and determine response type
|
|
63
|
+
*
|
|
64
|
+
* @param userInput - Raw user input string
|
|
65
|
+
* @param context - Context from previous clarification
|
|
66
|
+
* @returns Parsed user response
|
|
67
|
+
*/
|
|
68
|
+
parseUserResponse(userInput, context) {
|
|
69
|
+
const input = userInput.trim().toLowerCase();
|
|
70
|
+
// Check for cancel intent
|
|
71
|
+
if (this.isCancelIntent(input)) {
|
|
72
|
+
return { type: 'cancel', raw_input: userInput };
|
|
73
|
+
}
|
|
74
|
+
// Parse based on context
|
|
75
|
+
switch (context.clarification_reason) {
|
|
76
|
+
case 'target_file_exists':
|
|
77
|
+
return this.parseOverwriteResponse(userInput);
|
|
78
|
+
case 'target_file_ambiguous':
|
|
79
|
+
return this.parseFileSpecification(userInput);
|
|
80
|
+
case 'target_action_ambiguous':
|
|
81
|
+
return this.parseActionSpecification(userInput);
|
|
82
|
+
default:
|
|
83
|
+
return { type: 'unknown', raw_input: userInput };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Normalize user response into explicit task for Runner
|
|
88
|
+
*
|
|
89
|
+
* @param originalPrompt - Original user prompt
|
|
90
|
+
* @param signal - Runner signal that triggered clarification
|
|
91
|
+
* @param parsedResponse - Parsed user response
|
|
92
|
+
* @returns Normalized task or null if cancelled
|
|
93
|
+
*/
|
|
94
|
+
normalizeToTask(originalPrompt, signal, parsedResponse) {
|
|
95
|
+
if (parsedResponse.type === 'cancel') {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const context = {
|
|
99
|
+
original_prompt: originalPrompt,
|
|
100
|
+
clarification_reason: signal.clarification_reason,
|
|
101
|
+
user_response: parsedResponse.raw_input,
|
|
102
|
+
};
|
|
103
|
+
switch (parsedResponse.type) {
|
|
104
|
+
case 'overwrite':
|
|
105
|
+
return {
|
|
106
|
+
explicit_prompt: `${signal.target_file} を上書きして作成してください`,
|
|
107
|
+
target_file: signal.target_file,
|
|
108
|
+
action: 'overwrite',
|
|
109
|
+
original_context: context,
|
|
110
|
+
};
|
|
111
|
+
case 'new_name':
|
|
112
|
+
const newFileName = parsedResponse.new_file_name || this.generateAlternativeName(signal.target_file);
|
|
113
|
+
return {
|
|
114
|
+
explicit_prompt: `${newFileName} を新規作成してください`,
|
|
115
|
+
target_file: newFileName,
|
|
116
|
+
action: 'create_new',
|
|
117
|
+
original_context: context,
|
|
118
|
+
};
|
|
119
|
+
case 'specify_file':
|
|
120
|
+
return {
|
|
121
|
+
explicit_prompt: `${parsedResponse.new_file_name} を作成してください`,
|
|
122
|
+
target_file: parsedResponse.new_file_name,
|
|
123
|
+
action: 'create',
|
|
124
|
+
original_context: context,
|
|
125
|
+
};
|
|
126
|
+
case 'specify_action':
|
|
127
|
+
return {
|
|
128
|
+
explicit_prompt: parsedResponse.specified_action || originalPrompt,
|
|
129
|
+
action: 'modify',
|
|
130
|
+
original_context: context,
|
|
131
|
+
};
|
|
132
|
+
default:
|
|
133
|
+
// Unknown response - return original prompt with context
|
|
134
|
+
return {
|
|
135
|
+
explicit_prompt: originalPrompt,
|
|
136
|
+
action: 'create',
|
|
137
|
+
original_context: context,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// ============================================================
|
|
142
|
+
// Private helper methods
|
|
143
|
+
// ============================================================
|
|
144
|
+
/**
|
|
145
|
+
* Handle case when target file already exists
|
|
146
|
+
*/
|
|
147
|
+
handleFileExistsCase(signal) {
|
|
148
|
+
const fileName = signal.target_file || 'ファイル';
|
|
149
|
+
return {
|
|
150
|
+
needs_user_input: true,
|
|
151
|
+
question: `${fileName} は既に存在します。上書きしますか?それとも別名で新規作成しますか?(overwrite / new)`,
|
|
152
|
+
suggested_responses: ['overwrite', 'new', 'cancel'],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Handle case when target file is ambiguous
|
|
157
|
+
*/
|
|
158
|
+
handleFileAmbiguousCase(signal) {
|
|
159
|
+
return {
|
|
160
|
+
needs_user_input: true,
|
|
161
|
+
question: '対象のファイル名またはパスを指定してください。',
|
|
162
|
+
suggested_responses: [],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Handle case when action is ambiguous
|
|
167
|
+
*/
|
|
168
|
+
handleActionAmbiguousCase(signal) {
|
|
169
|
+
return {
|
|
170
|
+
needs_user_input: true,
|
|
171
|
+
question: 'どの機能/箇所を修正しますか?(例: コマンド名、エラー文、対象ファイル)',
|
|
172
|
+
suggested_responses: [],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Handle case when required info is missing
|
|
177
|
+
*/
|
|
178
|
+
handleMissingInfoCase(signal) {
|
|
179
|
+
return {
|
|
180
|
+
needs_user_input: true,
|
|
181
|
+
question: 'タスクを実行するために必要な情報を教えてください。',
|
|
182
|
+
suggested_responses: [],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Generate status message for non-clarification cases
|
|
187
|
+
*/
|
|
188
|
+
generateStatusMessage(signal) {
|
|
189
|
+
if (signal.execution_result) {
|
|
190
|
+
const result = signal.execution_result;
|
|
191
|
+
switch (result.status) {
|
|
192
|
+
case 'COMPLETE':
|
|
193
|
+
const files = result.verified_files?.filter(f => f.exists).map(f => f.path) || [];
|
|
194
|
+
return files.length > 0
|
|
195
|
+
? `完了しました。作成されたファイル: ${files.join(', ')}`
|
|
196
|
+
: '完了しました。';
|
|
197
|
+
case 'INCOMPLETE':
|
|
198
|
+
return 'タスクは部分的に完了しました。';
|
|
199
|
+
case 'NO_EVIDENCE':
|
|
200
|
+
return 'タスクの完了を確認できませんでした。';
|
|
201
|
+
case 'ERROR':
|
|
202
|
+
return 'エラーが発生しました。';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return 'タスクを処理中です。';
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Check if input indicates cancel intent
|
|
209
|
+
*/
|
|
210
|
+
isCancelIntent(input) {
|
|
211
|
+
const cancelPatterns = [
|
|
212
|
+
'cancel', 'キャンセル', '中止', 'やめる', 'やめて',
|
|
213
|
+
'abort', 'stop', '止める', '止めて', 'いいえ', 'no',
|
|
214
|
+
];
|
|
215
|
+
return cancelPatterns.some(pattern => input.includes(pattern));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Parse response for overwrite/new decision
|
|
219
|
+
*/
|
|
220
|
+
parseOverwriteResponse(input) {
|
|
221
|
+
const normalized = input.trim().toLowerCase();
|
|
222
|
+
// Check for overwrite intent
|
|
223
|
+
const overwritePatterns = [
|
|
224
|
+
'overwrite', '上書き', 'うわがき', 'replace', '置き換え',
|
|
225
|
+
'yes', 'はい', 'ok', 'おk',
|
|
226
|
+
];
|
|
227
|
+
if (overwritePatterns.some(p => normalized.includes(p))) {
|
|
228
|
+
return { type: 'overwrite', raw_input: input };
|
|
229
|
+
}
|
|
230
|
+
// Check for new name intent
|
|
231
|
+
const newNamePatterns = [
|
|
232
|
+
'new', '新規', 'しんき', '別名', 'べつめい', '別の名前',
|
|
233
|
+
'different', 'another',
|
|
234
|
+
];
|
|
235
|
+
if (newNamePatterns.some(p => normalized.includes(p))) {
|
|
236
|
+
// Try to extract new file name from input
|
|
237
|
+
const newFileName = this.extractFileName(input);
|
|
238
|
+
return {
|
|
239
|
+
type: 'new_name',
|
|
240
|
+
new_file_name: newFileName || undefined,
|
|
241
|
+
raw_input: input,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
// Check if user provided a specific file name
|
|
245
|
+
const extractedFile = this.extractFileName(input);
|
|
246
|
+
if (extractedFile) {
|
|
247
|
+
return {
|
|
248
|
+
type: 'new_name',
|
|
249
|
+
new_file_name: extractedFile,
|
|
250
|
+
raw_input: input,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return { type: 'unknown', raw_input: input };
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Parse response for file specification
|
|
257
|
+
*/
|
|
258
|
+
parseFileSpecification(input) {
|
|
259
|
+
const fileName = this.extractFileName(input);
|
|
260
|
+
if (fileName) {
|
|
261
|
+
return {
|
|
262
|
+
type: 'specify_file',
|
|
263
|
+
new_file_name: fileName,
|
|
264
|
+
raw_input: input,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return { type: 'unknown', raw_input: input };
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Parse response for action specification
|
|
271
|
+
*/
|
|
272
|
+
parseActionSpecification(input) {
|
|
273
|
+
// If input is non-trivial, treat it as action specification
|
|
274
|
+
if (input.trim().length > 2) {
|
|
275
|
+
return {
|
|
276
|
+
type: 'specify_action',
|
|
277
|
+
specified_action: input.trim(),
|
|
278
|
+
raw_input: input,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
return { type: 'unknown', raw_input: input };
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Extract file name from user input
|
|
285
|
+
*/
|
|
286
|
+
extractFileName(input) {
|
|
287
|
+
// Pattern for file paths with extensions
|
|
288
|
+
const extensions = 'ts|tsx|js|jsx|json|md|txt|yaml|yml|html|css|sh';
|
|
289
|
+
const filePattern = new RegExp(`(?:^|\\s)((?:[\\w.-]+\\/)*[\\w.-]+\\.(?:${extensions}))(?:\\s|$|を|に|の|で|と|は)`, 'i');
|
|
290
|
+
const match = input.match(filePattern);
|
|
291
|
+
if (match) {
|
|
292
|
+
return match[1];
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Generate alternative file name
|
|
298
|
+
*/
|
|
299
|
+
generateAlternativeName(originalFile) {
|
|
300
|
+
if (!originalFile) {
|
|
301
|
+
return 'new_file.txt';
|
|
302
|
+
}
|
|
303
|
+
const ext = originalFile.includes('.')
|
|
304
|
+
? originalFile.substring(originalFile.lastIndexOf('.'))
|
|
305
|
+
: '';
|
|
306
|
+
const baseName = originalFile.includes('.')
|
|
307
|
+
? originalFile.substring(0, originalFile.lastIndexOf('.'))
|
|
308
|
+
: originalFile;
|
|
309
|
+
// Add timestamp suffix
|
|
310
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19);
|
|
311
|
+
return `${baseName}_${timestamp}${ext}`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
exports.LLMMediationLayer = LLMMediationLayer;
|
|
315
|
+
//# sourceMappingURL=llm-mediation-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-mediation-layer.js","sourceRoot":"","sources":["../../src/mediation/llm-mediation-layer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Sentinel - File-based Evidence Verification
|
|
3
|
+
*
|
|
4
|
+
* Sentinel that verifies LLM execution evidence before allowing
|
|
5
|
+
* COMPLETE status to be reported.
|
|
6
|
+
*
|
|
7
|
+
* ARCHITECTURAL RULES:
|
|
8
|
+
* - COMPLETE status requires verified evidence files
|
|
9
|
+
* - Sentinel checks evidence integrity (hash verification)
|
|
10
|
+
* - Sentinel checks evidence completeness (at least one success)
|
|
11
|
+
* - Fail-closed: Any verification failure = cannot assert COMPLETE
|
|
12
|
+
*/
|
|
13
|
+
import { LLMEvidenceManager, LLMEvidence, EvidenceStats } from './llm-evidence-manager';
|
|
14
|
+
/**
|
|
15
|
+
* Sentinel verification result
|
|
16
|
+
*/
|
|
17
|
+
export interface SentinelVerificationResult {
|
|
18
|
+
/** Overall verification passed */
|
|
19
|
+
passed: boolean;
|
|
20
|
+
/** Timestamp of verification */
|
|
21
|
+
timestamp: string;
|
|
22
|
+
/** Evidence directory checked */
|
|
23
|
+
evidence_dir: string;
|
|
24
|
+
/** Number of evidence files found */
|
|
25
|
+
evidence_count: number;
|
|
26
|
+
/** Number of successful calls */
|
|
27
|
+
successful_calls: number;
|
|
28
|
+
/** Number of failed calls */
|
|
29
|
+
failed_calls: number;
|
|
30
|
+
/** Integrity check results */
|
|
31
|
+
integrity_checks: IntegrityCheckResult[];
|
|
32
|
+
/** Overall integrity passed */
|
|
33
|
+
integrity_passed: boolean;
|
|
34
|
+
/** Can assert COMPLETE status */
|
|
35
|
+
can_assert_complete: boolean;
|
|
36
|
+
/** Reason if verification failed */
|
|
37
|
+
failure_reason?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Individual evidence integrity check result
|
|
41
|
+
*/
|
|
42
|
+
export interface IntegrityCheckResult {
|
|
43
|
+
call_id: string;
|
|
44
|
+
file_exists: boolean;
|
|
45
|
+
hash_valid: boolean;
|
|
46
|
+
passed: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* LLM Sentinel for evidence verification
|
|
50
|
+
*
|
|
51
|
+
* Fail-closed behavior:
|
|
52
|
+
* - No evidence = FAIL
|
|
53
|
+
* - Evidence integrity failure = FAIL
|
|
54
|
+
* - All calls failed = FAIL
|
|
55
|
+
* - At least one successful call with valid evidence = PASS
|
|
56
|
+
*/
|
|
57
|
+
export declare class LLMSentinel {
|
|
58
|
+
private readonly evidenceManager;
|
|
59
|
+
constructor(evidenceDir: string);
|
|
60
|
+
/**
|
|
61
|
+
* Create sentinel from existing evidence manager
|
|
62
|
+
*/
|
|
63
|
+
static fromEvidenceManager(manager: LLMEvidenceManager): LLMSentinel;
|
|
64
|
+
/**
|
|
65
|
+
* Verify all evidence and determine if COMPLETE can be asserted
|
|
66
|
+
*
|
|
67
|
+
* This is the main entry point for the fail-closed check.
|
|
68
|
+
*/
|
|
69
|
+
verify(): SentinelVerificationResult;
|
|
70
|
+
/**
|
|
71
|
+
* Quick check if COMPLETE can be asserted
|
|
72
|
+
*
|
|
73
|
+
* This is a lightweight check that doesn't do full integrity verification.
|
|
74
|
+
*/
|
|
75
|
+
canAssertComplete(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Full verification with integrity checks
|
|
78
|
+
*/
|
|
79
|
+
fullVerification(): SentinelVerificationResult;
|
|
80
|
+
/**
|
|
81
|
+
* Check integrity of a single evidence file
|
|
82
|
+
*/
|
|
83
|
+
private checkIntegrity;
|
|
84
|
+
/**
|
|
85
|
+
* Get evidence statistics
|
|
86
|
+
*/
|
|
87
|
+
getStats(): EvidenceStats;
|
|
88
|
+
/**
|
|
89
|
+
* Get detailed evidence list
|
|
90
|
+
*/
|
|
91
|
+
getEvidenceDetails(): LLMEvidence[];
|
|
92
|
+
/**
|
|
93
|
+
* Generate verification report for logging
|
|
94
|
+
*/
|
|
95
|
+
generateReport(): string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create sentinel for evidence directory
|
|
99
|
+
*/
|
|
100
|
+
export declare function createSentinel(evidenceDir: string): LLMSentinel;
|
|
101
|
+
/**
|
|
102
|
+
* Verify evidence and return whether COMPLETE can be asserted
|
|
103
|
+
*
|
|
104
|
+
* Convenience function for fail-closed check.
|
|
105
|
+
*/
|
|
106
|
+
export declare function verifyLLMEvidence(evidenceDir: string): SentinelVerificationResult;
|
|
107
|
+
//# sourceMappingURL=llm-sentinel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-sentinel.d.ts","sourceRoot":"","sources":["../../src/mediation/llm-sentinel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,kCAAkC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,6BAA6B;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,gBAAgB,EAAE,oBAAoB,EAAE,CAAC;IACzC,+BAA+B;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iCAAiC;IACjC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;gBAEzC,WAAW,EAAE,MAAM;IAI/B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW;IAMpE;;;;OAIG;IACH,MAAM,IAAI,0BAA0B;IA4DpC;;;;OAIG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACH,gBAAgB,IAAI,0BAA0B;IAI9C;;OAEG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,QAAQ,IAAI,aAAa;IAIzB;;OAEG;IACH,kBAAkB,IAAI,WAAW,EAAE;IAInC;;OAEG;IACH,cAAc,IAAI,MAAM;CAkCzB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,0BAA0B,CAGjF"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LLM Sentinel - File-based Evidence Verification
|
|
4
|
+
*
|
|
5
|
+
* Sentinel that verifies LLM execution evidence before allowing
|
|
6
|
+
* COMPLETE status to be reported.
|
|
7
|
+
*
|
|
8
|
+
* ARCHITECTURAL RULES:
|
|
9
|
+
* - COMPLETE status requires verified evidence files
|
|
10
|
+
* - Sentinel checks evidence integrity (hash verification)
|
|
11
|
+
* - Sentinel checks evidence completeness (at least one success)
|
|
12
|
+
* - Fail-closed: Any verification failure = cannot assert COMPLETE
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.LLMSentinel = void 0;
|
|
16
|
+
exports.createSentinel = createSentinel;
|
|
17
|
+
exports.verifyLLMEvidence = verifyLLMEvidence;
|
|
18
|
+
const llm_evidence_manager_1 = require("./llm-evidence-manager");
|
|
19
|
+
/**
|
|
20
|
+
* LLM Sentinel for evidence verification
|
|
21
|
+
*
|
|
22
|
+
* Fail-closed behavior:
|
|
23
|
+
* - No evidence = FAIL
|
|
24
|
+
* - Evidence integrity failure = FAIL
|
|
25
|
+
* - All calls failed = FAIL
|
|
26
|
+
* - At least one successful call with valid evidence = PASS
|
|
27
|
+
*/
|
|
28
|
+
class LLMSentinel {
|
|
29
|
+
evidenceManager;
|
|
30
|
+
constructor(evidenceDir) {
|
|
31
|
+
this.evidenceManager = new llm_evidence_manager_1.LLMEvidenceManager(evidenceDir);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create sentinel from existing evidence manager
|
|
35
|
+
*/
|
|
36
|
+
static fromEvidenceManager(manager) {
|
|
37
|
+
const sentinel = Object.create(LLMSentinel.prototype);
|
|
38
|
+
sentinel.evidenceManager = manager;
|
|
39
|
+
return sentinel;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Verify all evidence and determine if COMPLETE can be asserted
|
|
43
|
+
*
|
|
44
|
+
* This is the main entry point for the fail-closed check.
|
|
45
|
+
*/
|
|
46
|
+
verify() {
|
|
47
|
+
const timestamp = new Date().toISOString();
|
|
48
|
+
const evidenceDir = this.evidenceManager.getEvidenceDir();
|
|
49
|
+
// Get all evidence
|
|
50
|
+
const allEvidence = this.evidenceManager.listEvidence();
|
|
51
|
+
// No evidence = fail-closed
|
|
52
|
+
if (allEvidence.length === 0) {
|
|
53
|
+
return {
|
|
54
|
+
passed: false,
|
|
55
|
+
timestamp,
|
|
56
|
+
evidence_dir: evidenceDir,
|
|
57
|
+
evidence_count: 0,
|
|
58
|
+
successful_calls: 0,
|
|
59
|
+
failed_calls: 0,
|
|
60
|
+
integrity_checks: [],
|
|
61
|
+
integrity_passed: true, // No files to check
|
|
62
|
+
can_assert_complete: false,
|
|
63
|
+
failure_reason: 'No LLM evidence found (fail-closed)',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Check integrity of each evidence file
|
|
67
|
+
const integrityChecks = allEvidence.map(evidence => this.checkIntegrity(evidence));
|
|
68
|
+
const integrityPassed = integrityChecks.every(check => check.passed);
|
|
69
|
+
// Get statistics
|
|
70
|
+
const stats = this.evidenceManager.getStats();
|
|
71
|
+
// Determine if COMPLETE can be asserted
|
|
72
|
+
// Requires: at least one successful call + all integrity checks passed
|
|
73
|
+
const canAssertComplete = stats.successful_calls > 0 && integrityPassed;
|
|
74
|
+
// Determine failure reason if any
|
|
75
|
+
let failureReason;
|
|
76
|
+
if (!integrityPassed) {
|
|
77
|
+
const failedCallIds = integrityChecks
|
|
78
|
+
.filter(c => !c.passed)
|
|
79
|
+
.map(c => c.call_id)
|
|
80
|
+
.join(', ');
|
|
81
|
+
failureReason = 'Evidence integrity check failed for: ' + failedCallIds;
|
|
82
|
+
}
|
|
83
|
+
else if (stats.successful_calls === 0) {
|
|
84
|
+
failureReason = 'No successful LLM calls found (all calls failed)';
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
passed: canAssertComplete,
|
|
88
|
+
timestamp,
|
|
89
|
+
evidence_dir: evidenceDir,
|
|
90
|
+
evidence_count: allEvidence.length,
|
|
91
|
+
successful_calls: stats.successful_calls,
|
|
92
|
+
failed_calls: stats.failed_calls,
|
|
93
|
+
integrity_checks: integrityChecks,
|
|
94
|
+
integrity_passed: integrityPassed,
|
|
95
|
+
can_assert_complete: canAssertComplete,
|
|
96
|
+
failure_reason: failureReason,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Quick check if COMPLETE can be asserted
|
|
101
|
+
*
|
|
102
|
+
* This is a lightweight check that doesn't do full integrity verification.
|
|
103
|
+
*/
|
|
104
|
+
canAssertComplete() {
|
|
105
|
+
return this.evidenceManager.canAssertComplete();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Full verification with integrity checks
|
|
109
|
+
*/
|
|
110
|
+
fullVerification() {
|
|
111
|
+
return this.verify();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check integrity of a single evidence file
|
|
115
|
+
*/
|
|
116
|
+
checkIntegrity(evidence) {
|
|
117
|
+
const fileExists = this.evidenceManager.hasEvidence(evidence.call_id);
|
|
118
|
+
const hashValid = fileExists && this.evidenceManager.verifyIntegrity(evidence.call_id);
|
|
119
|
+
return {
|
|
120
|
+
call_id: evidence.call_id,
|
|
121
|
+
file_exists: fileExists,
|
|
122
|
+
hash_valid: hashValid,
|
|
123
|
+
passed: fileExists && hashValid,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get evidence statistics
|
|
128
|
+
*/
|
|
129
|
+
getStats() {
|
|
130
|
+
return this.evidenceManager.getStats();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get detailed evidence list
|
|
134
|
+
*/
|
|
135
|
+
getEvidenceDetails() {
|
|
136
|
+
return this.evidenceManager.listEvidence();
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Generate verification report for logging
|
|
140
|
+
*/
|
|
141
|
+
generateReport() {
|
|
142
|
+
const result = this.verify();
|
|
143
|
+
const lines = [
|
|
144
|
+
'========================================',
|
|
145
|
+
'LLM Sentinel Verification Report',
|
|
146
|
+
'========================================',
|
|
147
|
+
'Timestamp: ' + result.timestamp,
|
|
148
|
+
'Evidence Directory: ' + result.evidence_dir,
|
|
149
|
+
'Evidence Count: ' + result.evidence_count,
|
|
150
|
+
'Successful Calls: ' + result.successful_calls,
|
|
151
|
+
'Failed Calls: ' + result.failed_calls,
|
|
152
|
+
'Integrity Passed: ' + result.integrity_passed,
|
|
153
|
+
'Can Assert COMPLETE: ' + result.can_assert_complete,
|
|
154
|
+
'Overall Result: ' + (result.passed ? 'PASS' : 'FAIL'),
|
|
155
|
+
];
|
|
156
|
+
if (result.failure_reason) {
|
|
157
|
+
lines.push('Failure Reason: ' + result.failure_reason);
|
|
158
|
+
}
|
|
159
|
+
if (result.integrity_checks.length > 0) {
|
|
160
|
+
lines.push('');
|
|
161
|
+
lines.push('Integrity Check Details:');
|
|
162
|
+
for (const check of result.integrity_checks) {
|
|
163
|
+
const status = check.passed ? 'PASS' : 'FAIL';
|
|
164
|
+
lines.push(' - ' + check.call_id + ': ' + status + ' (file=' + check.file_exists + ', hash=' + check.hash_valid + ')');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
lines.push('========================================');
|
|
168
|
+
return lines.join('\n');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.LLMSentinel = LLMSentinel;
|
|
172
|
+
/**
|
|
173
|
+
* Create sentinel for evidence directory
|
|
174
|
+
*/
|
|
175
|
+
function createSentinel(evidenceDir) {
|
|
176
|
+
return new LLMSentinel(evidenceDir);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Verify evidence and return whether COMPLETE can be asserted
|
|
180
|
+
*
|
|
181
|
+
* Convenience function for fail-closed check.
|
|
182
|
+
*/
|
|
183
|
+
function verifyLLMEvidence(evidenceDir) {
|
|
184
|
+
const sentinel = new LLMSentinel(evidenceDir);
|
|
185
|
+
return sentinel.verify();
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=llm-sentinel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-sentinel.js","sourceRoot":"","sources":["../../src/mediation/llm-sentinel.ts"],"names":[],"mappings":"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"}
|