@cluesmith/codev 1.6.2 → 2.0.0-rc.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/bin/porch.js +7 -0
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +23 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/index.d.ts +1 -0
- package/dist/agent-farm/commands/index.d.ts.map +1 -1
- package/dist/agent-farm/commands/index.js +1 -0
- package/dist/agent-farm/commands/index.js.map +1 -1
- package/dist/agent-farm/commands/kickoff.d.ts +19 -0
- package/dist/agent-farm/commands/kickoff.d.ts.map +1 -0
- package/dist/agent-farm/commands/kickoff.js +269 -0
- package/dist/agent-farm/commands/kickoff.js.map +1 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +1 -43
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +29 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/pcheck/cache.d.ts +48 -0
- package/dist/commands/pcheck/cache.d.ts.map +1 -0
- package/dist/commands/pcheck/cache.js +170 -0
- package/dist/commands/pcheck/cache.js.map +1 -0
- package/dist/commands/pcheck/evaluator.d.ts +15 -0
- package/dist/commands/pcheck/evaluator.d.ts.map +1 -0
- package/dist/commands/pcheck/evaluator.js +246 -0
- package/dist/commands/pcheck/evaluator.js.map +1 -0
- package/dist/commands/pcheck/index.d.ts +12 -0
- package/dist/commands/pcheck/index.d.ts.map +1 -0
- package/dist/commands/pcheck/index.js +249 -0
- package/dist/commands/pcheck/index.js.map +1 -0
- package/dist/commands/pcheck/parser.d.ts +39 -0
- package/dist/commands/pcheck/parser.d.ts.map +1 -0
- package/dist/commands/pcheck/parser.js +155 -0
- package/dist/commands/pcheck/parser.js.map +1 -0
- package/dist/commands/pcheck/types.d.ts +82 -0
- package/dist/commands/pcheck/types.d.ts.map +1 -0
- package/dist/commands/pcheck/types.js +5 -0
- package/dist/commands/pcheck/types.js.map +1 -0
- package/dist/commands/porch/checks.d.ts +42 -0
- package/dist/commands/porch/checks.d.ts.map +1 -0
- package/dist/commands/porch/checks.js +195 -0
- package/dist/commands/porch/checks.js.map +1 -0
- package/dist/commands/porch/consultation.d.ts +56 -0
- package/dist/commands/porch/consultation.d.ts.map +1 -0
- package/dist/commands/porch/consultation.js +330 -0
- package/dist/commands/porch/consultation.js.map +1 -0
- package/dist/commands/porch/index.d.ts +60 -0
- package/dist/commands/porch/index.d.ts.map +1 -0
- package/dist/commands/porch/index.js +828 -0
- package/dist/commands/porch/index.js.map +1 -0
- package/dist/commands/porch/notifications.d.ts +99 -0
- package/dist/commands/porch/notifications.d.ts.map +1 -0
- package/dist/commands/porch/notifications.js +223 -0
- package/dist/commands/porch/notifications.js.map +1 -0
- package/dist/commands/porch/plan-parser.d.ts +38 -0
- package/dist/commands/porch/plan-parser.d.ts.map +1 -0
- package/dist/commands/porch/plan-parser.js +166 -0
- package/dist/commands/porch/plan-parser.js.map +1 -0
- package/dist/commands/porch/protocol-loader.d.ts +46 -0
- package/dist/commands/porch/protocol-loader.d.ts.map +1 -0
- package/dist/commands/porch/protocol-loader.js +249 -0
- package/dist/commands/porch/protocol-loader.js.map +1 -0
- package/dist/commands/porch/signal-parser.d.ts +88 -0
- package/dist/commands/porch/signal-parser.d.ts.map +1 -0
- package/dist/commands/porch/signal-parser.js +148 -0
- package/dist/commands/porch/signal-parser.js.map +1 -0
- package/dist/commands/porch/state.d.ts +133 -0
- package/dist/commands/porch/state.d.ts.map +1 -0
- package/dist/commands/porch/state.js +760 -0
- package/dist/commands/porch/state.js.map +1 -0
- package/dist/commands/porch/types.d.ts +232 -0
- package/dist/commands/porch/types.d.ts.map +1 -0
- package/dist/commands/porch/types.js +7 -0
- package/dist/commands/porch/types.js.map +1 -0
- package/package.json +2 -1
- package/skeleton/porch/prompts/defend.md +103 -0
- package/skeleton/porch/prompts/diagnose.md +70 -0
- package/skeleton/porch/prompts/evaluate.md +132 -0
- package/skeleton/porch/prompts/fix.md +59 -0
- package/skeleton/porch/prompts/implement.md +79 -0
- package/skeleton/porch/prompts/plan.md +74 -0
- package/skeleton/porch/prompts/pr.md +84 -0
- package/skeleton/porch/prompts/review.md +179 -0
- package/skeleton/porch/prompts/specify.md +53 -0
- package/skeleton/porch/prompts/test.md +63 -0
- package/skeleton/porch/prompts/understand.md +61 -0
- package/skeleton/porch/prompts/verify.md +58 -0
- package/skeleton/porch/protocols/bugfix.json +85 -0
- package/skeleton/porch/protocols/spider.json +135 -0
- package/skeleton/porch/protocols/tick.json +76 -0
- package/skeleton/protocols/bugfix/protocol.json +127 -0
- package/skeleton/protocols/protocol-schema.json +237 -0
- package/skeleton/protocols/spider/protocol.json +204 -0
- package/skeleton/protocols/tick/protocol.json +151 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates protocol definitions from JSON files.
|
|
5
|
+
*/
|
|
6
|
+
import type { Protocol, Phase } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Find protocol JSON file
|
|
9
|
+
*/
|
|
10
|
+
export declare function findProtocolFile(projectRoot: string, protocolName: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Load protocol from JSON file
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadProtocol(projectRoot: string, protocolName: string): Protocol | null;
|
|
15
|
+
/**
|
|
16
|
+
* Get all available protocols
|
|
17
|
+
*/
|
|
18
|
+
export declare function listProtocols(projectRoot: string): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Get default protocol (spider)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getDefaultProtocol(projectRoot: string): Protocol | null;
|
|
23
|
+
/**
|
|
24
|
+
* Validate a protocol has required phases
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateProtocol(protocol: Protocol): {
|
|
27
|
+
valid: boolean;
|
|
28
|
+
errors: string[];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Get phase by ID
|
|
32
|
+
*/
|
|
33
|
+
export declare function getPhase(protocol: Protocol, phaseId: string): Phase | null;
|
|
34
|
+
/**
|
|
35
|
+
* Get the next phase after a given phase
|
|
36
|
+
*/
|
|
37
|
+
export declare function getNextPhase(protocol: Protocol, currentPhaseId: string): Phase | null;
|
|
38
|
+
/**
|
|
39
|
+
* Check if a phase is a terminal phase (no next phase)
|
|
40
|
+
*/
|
|
41
|
+
export declare function isTerminalPhase(protocol: Protocol, phaseId: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Get phased phases (phases that run per plan phase)
|
|
44
|
+
*/
|
|
45
|
+
export declare function getPhasedPhases(protocol: Protocol): Phase[];
|
|
46
|
+
//# sourceMappingURL=protocol-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-loader.d.ts","sourceRoot":"","sources":["../../../src/commands/porch/protocol-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAyC,MAAM,YAAY,CAAC;AA6EzF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQzF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAevF;AAkID;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAEvE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAmCzF;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAE1E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAMrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,EAAE,CAE3D"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol Loader
|
|
3
|
+
*
|
|
4
|
+
* Loads and validates protocol definitions from JSON files.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
7
|
+
import { resolve, join } from 'node:path';
|
|
8
|
+
/**
|
|
9
|
+
* Known protocol locations (relative to project root)
|
|
10
|
+
*/
|
|
11
|
+
const PROTOCOL_PATHS = [
|
|
12
|
+
'codev/protocols',
|
|
13
|
+
'codev-skeleton/protocols',
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Find protocol JSON file
|
|
17
|
+
*/
|
|
18
|
+
export function findProtocolFile(projectRoot, protocolName) {
|
|
19
|
+
for (const basePath of PROTOCOL_PATHS) {
|
|
20
|
+
const fullPath = resolve(projectRoot, basePath, protocolName, 'protocol.json');
|
|
21
|
+
if (existsSync(fullPath)) {
|
|
22
|
+
return fullPath;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load protocol from JSON file
|
|
29
|
+
*/
|
|
30
|
+
export function loadProtocol(projectRoot, protocolName) {
|
|
31
|
+
const filePath = findProtocolFile(projectRoot, protocolName);
|
|
32
|
+
if (!filePath) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
37
|
+
const json = JSON.parse(content);
|
|
38
|
+
return convertJsonToProtocol(json);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error(`Failed to load protocol ${protocolName}: ${error}`);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert JSON representation to Protocol type
|
|
47
|
+
*/
|
|
48
|
+
function convertJsonToProtocol(json) {
|
|
49
|
+
const phases = [];
|
|
50
|
+
for (const phaseJson of json.phases) {
|
|
51
|
+
phases.push(convertPhase(phaseJson, json.defaults));
|
|
52
|
+
}
|
|
53
|
+
// Determine initial state - first phase with first substate or just phase id
|
|
54
|
+
const firstPhase = phases[0];
|
|
55
|
+
const initialState = firstPhase.substates && firstPhase.substates.length > 0
|
|
56
|
+
? `${firstPhase.id}:${firstPhase.substates[0]}`
|
|
57
|
+
: firstPhase.id;
|
|
58
|
+
return {
|
|
59
|
+
name: json.name,
|
|
60
|
+
version: json.version,
|
|
61
|
+
description: json.description,
|
|
62
|
+
phases,
|
|
63
|
+
initial: initialState,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Convert phase JSON to Phase type
|
|
68
|
+
*/
|
|
69
|
+
function convertPhase(json, defaults) {
|
|
70
|
+
const phase = {
|
|
71
|
+
id: json.id,
|
|
72
|
+
name: json.name,
|
|
73
|
+
phased: json.type === 'per_plan_phase',
|
|
74
|
+
};
|
|
75
|
+
// Add substates from steps
|
|
76
|
+
if (json.steps && json.steps.length > 0) {
|
|
77
|
+
phase.substates = json.steps;
|
|
78
|
+
}
|
|
79
|
+
// Add checks
|
|
80
|
+
if (json.checks) {
|
|
81
|
+
phase.checks = {};
|
|
82
|
+
for (const [name, checkJson] of Object.entries(json.checks)) {
|
|
83
|
+
phase.checks[name] = convertCheck(checkJson);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Add consultation
|
|
87
|
+
if (json.consultation) {
|
|
88
|
+
phase.consultation = convertConsultation(json.consultation, defaults?.consultation);
|
|
89
|
+
}
|
|
90
|
+
// Add gate - determine when gate triggers based on requires or last step
|
|
91
|
+
if (json.gate) {
|
|
92
|
+
// Gate triggers after the last required substate, or after the last step
|
|
93
|
+
const gateAfter = json.gate.requires?.length
|
|
94
|
+
? json.gate.requires[json.gate.requires.length - 1]
|
|
95
|
+
: json.steps?.length
|
|
96
|
+
? json.steps[json.steps.length - 1]
|
|
97
|
+
: null;
|
|
98
|
+
phase.gate = convertGate(json.gate, gateAfter);
|
|
99
|
+
}
|
|
100
|
+
// Build signals from transitions
|
|
101
|
+
if (json.transition) {
|
|
102
|
+
phase.signals = {};
|
|
103
|
+
if (json.transition.on_complete) {
|
|
104
|
+
phase.signals['PHASE_COMPLETE'] = json.transition.on_complete;
|
|
105
|
+
}
|
|
106
|
+
if (json.transition.on_fail) {
|
|
107
|
+
phase.signals['PHASE_FAILED'] = json.transition.on_fail;
|
|
108
|
+
}
|
|
109
|
+
if (json.transition.on_all_phases_complete) {
|
|
110
|
+
phase.signals['ALL_PHASES_COMPLETE'] = json.transition.on_all_phases_complete;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Mark as terminal if gate has no next
|
|
114
|
+
if (json.gate && json.gate.next === null) {
|
|
115
|
+
phase.terminal = true;
|
|
116
|
+
}
|
|
117
|
+
return phase;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Convert check JSON to Check type
|
|
121
|
+
*/
|
|
122
|
+
function convertCheck(json) {
|
|
123
|
+
return {
|
|
124
|
+
command: json.command,
|
|
125
|
+
on_fail: json.on_fail || 'retry',
|
|
126
|
+
max_retries: json.max_retries ?? 3,
|
|
127
|
+
retry_delay: json.retry_delay ?? 5,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Convert consultation JSON to ConsultationConfig type
|
|
132
|
+
*/
|
|
133
|
+
function convertConsultation(json, defaults) {
|
|
134
|
+
return {
|
|
135
|
+
on: json.on || 'review',
|
|
136
|
+
models: json.models || defaults?.models || ['gemini', 'codex', 'claude'],
|
|
137
|
+
type: json.type || 'impl-review',
|
|
138
|
+
parallel: json.parallel ?? defaults?.parallel ?? true,
|
|
139
|
+
max_rounds: json.max_rounds ?? 3,
|
|
140
|
+
next: json.next || '',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Convert gate JSON to GateConfig type
|
|
145
|
+
* @param json - Gate configuration from protocol JSON
|
|
146
|
+
* @param gateAfter - Substate after which the gate triggers (from requires or last step)
|
|
147
|
+
*/
|
|
148
|
+
function convertGate(json, gateAfter) {
|
|
149
|
+
return {
|
|
150
|
+
after: gateAfter || json.name, // Use computed trigger point, fallback to gate name
|
|
151
|
+
type: 'human',
|
|
152
|
+
next: json.next || '',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get all available protocols
|
|
157
|
+
*/
|
|
158
|
+
export function listProtocols(projectRoot) {
|
|
159
|
+
const protocols = [];
|
|
160
|
+
for (const basePath of PROTOCOL_PATHS) {
|
|
161
|
+
const fullPath = resolve(projectRoot, basePath);
|
|
162
|
+
if (existsSync(fullPath)) {
|
|
163
|
+
try {
|
|
164
|
+
const entries = readdirSync(fullPath, { withFileTypes: true });
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
if (entry.isDirectory()) {
|
|
167
|
+
const protocolFile = join(fullPath, entry.name, 'protocol.json');
|
|
168
|
+
if (existsSync(protocolFile)) {
|
|
169
|
+
protocols.push(entry.name);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Ignore errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [...new Set(protocols)];
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get default protocol (spider)
|
|
183
|
+
*/
|
|
184
|
+
export function getDefaultProtocol(projectRoot) {
|
|
185
|
+
return loadProtocol(projectRoot, 'spider');
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Validate a protocol has required phases
|
|
189
|
+
*/
|
|
190
|
+
export function validateProtocol(protocol) {
|
|
191
|
+
const errors = [];
|
|
192
|
+
if (!protocol.name) {
|
|
193
|
+
errors.push('Protocol name is required');
|
|
194
|
+
}
|
|
195
|
+
if (!protocol.phases || protocol.phases.length === 0) {
|
|
196
|
+
errors.push('Protocol must have at least one phase');
|
|
197
|
+
}
|
|
198
|
+
if (!protocol.initial) {
|
|
199
|
+
errors.push('Protocol must specify an initial state');
|
|
200
|
+
}
|
|
201
|
+
// Build phase ID lookup
|
|
202
|
+
const phaseIds = new Set(protocol.phases.map(p => p.id));
|
|
203
|
+
// Check phase signals reference valid phases
|
|
204
|
+
for (const phase of protocol.phases) {
|
|
205
|
+
if (phase.signals) {
|
|
206
|
+
for (const [signal, targetPhase] of Object.entries(phase.signals)) {
|
|
207
|
+
// Target might be "phaseId" or "phaseId:substate"
|
|
208
|
+
const targetPhaseId = targetPhase.split(':')[0];
|
|
209
|
+
if (!phaseIds.has(targetPhaseId)) {
|
|
210
|
+
errors.push(`Phase '${phase.id}' signal '${signal}' references unknown phase '${targetPhaseId}'`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
valid: errors.length === 0,
|
|
217
|
+
errors,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get phase by ID
|
|
222
|
+
*/
|
|
223
|
+
export function getPhase(protocol, phaseId) {
|
|
224
|
+
return protocol.phases.find(p => p.id === phaseId) || null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get the next phase after a given phase
|
|
228
|
+
*/
|
|
229
|
+
export function getNextPhase(protocol, currentPhaseId) {
|
|
230
|
+
const currentIndex = protocol.phases.findIndex(p => p.id === currentPhaseId);
|
|
231
|
+
if (currentIndex === -1 || currentIndex >= protocol.phases.length - 1) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return protocol.phases[currentIndex + 1];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Check if a phase is a terminal phase (no next phase)
|
|
238
|
+
*/
|
|
239
|
+
export function isTerminalPhase(protocol, phaseId) {
|
|
240
|
+
const phase = getPhase(protocol, phaseId);
|
|
241
|
+
return phase?.terminal ?? false;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get phased phases (phases that run per plan phase)
|
|
245
|
+
*/
|
|
246
|
+
export function getPhasedPhases(protocol) {
|
|
247
|
+
return protocol.phases.filter(p => p.phased);
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=protocol-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-loader.js","sourceRoot":"","sources":["../../../src/commands/porch/protocol-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C;;GAEG;AACH,MAAM,cAAc,GAAG;IACrB,iBAAiB;IACjB,0BAA0B;CAC3B,CAAC;AAqEF;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB,EAAE,YAAoB;IACxE,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;QAC/E,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB,EAAE,YAAoB;IACpE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAE7D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;QACjD,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2BAA2B,YAAY,KAAK,KAAK,EAAE,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,IAAkB;IAC/C,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,6EAA6E;IAC7E,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAC1E,CAAC,CAAC,GAAG,UAAU,CAAC,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;QAC/C,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;IAElB,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM;QACN,OAAO,EAAE,YAAY;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAe,EAAE,QAAmC;IACxE,MAAM,KAAK,GAAU;QACnB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,gBAAgB;KACvC,CAAC;IAEF,2BAA2B;IAC3B,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;IAC/B,CAAC;IAED,aAAa;IACb,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5D,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,KAAK,CAAC,YAAY,GAAG,mBAAmB,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IACtF,CAAC;IAED,yEAAyE;IACzE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,yEAAyE;QACzE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM;YAC1C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACnD,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM;gBAClB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;gBACnC,CAAC,CAAC,IAAI,CAAC;QACX,KAAK,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;YAChC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YAC5B,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAC1D,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC;YAC3C,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC;QAChF,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACzC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,IAAe;IACnC,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,OAAO;QAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;QAClC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;KACnC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,IAAsB,EACtB,QAAuE;IAEvE,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC;QACxE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,aAAa;QAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE,QAAQ,IAAI,IAAI;QACrD,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;QAChC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;KACtB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAc,EAAE,SAAwB;IAC3D,OAAO;QACL,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,oDAAoD;QACnF,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAChD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;wBACxB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;wBACjE,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;4BAC7B,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAC7B,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,gBAAgB;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB;IACpD,OAAO,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;IAED,wBAAwB;IACxB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzD,6CAA6C;IAC7C,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClE,kDAAkD;gBAClD,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAChD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;oBACjC,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE,aAAa,MAAM,+BAA+B,aAAa,GAAG,CAAC,CAAC;gBACpG,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAkB,EAAE,OAAe;IAC1D,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,cAAsB;IACrE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,CAAC;IAC7E,IAAI,YAAY,KAAK,CAAC,CAAC,IAAI,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAkB,EAAE,OAAe;IACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,KAAK,EAAE,QAAQ,IAAI,KAAK,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAkB;IAChD,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal Parser
|
|
3
|
+
*
|
|
4
|
+
* Extracts signals from Claude output and validates them against protocol definitions.
|
|
5
|
+
* Signals use XML-style tags: <signal>SIGNAL_NAME</signal>
|
|
6
|
+
*/
|
|
7
|
+
import type { Protocol } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Signal extraction result
|
|
10
|
+
*/
|
|
11
|
+
export interface SignalResult {
|
|
12
|
+
signal: string | null;
|
|
13
|
+
allSignals: string[];
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extract signal from Claude output
|
|
19
|
+
*
|
|
20
|
+
* Rules:
|
|
21
|
+
* - Scan for <signal>...</signal> patterns
|
|
22
|
+
* - Return the LAST signal found (multiple signals → last wins)
|
|
23
|
+
* - Return null if no signal found
|
|
24
|
+
*/
|
|
25
|
+
export declare function extractSignal(output: string): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Extract all signals from output
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractAllSignals(output: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Validate a signal against the protocol definition
|
|
32
|
+
*
|
|
33
|
+
* Returns true if the signal is valid for the current phase.
|
|
34
|
+
* Unknown signals are logged but considered valid (lenient mode).
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateSignal(signal: string, protocol: Protocol, currentState: string): {
|
|
37
|
+
valid: boolean;
|
|
38
|
+
nextState?: string;
|
|
39
|
+
warning?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Extract and validate signal from output
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseSignal(output: string, protocol: Protocol, currentState: string): SignalResult;
|
|
45
|
+
/**
|
|
46
|
+
* Get valid signals for a phase
|
|
47
|
+
*/
|
|
48
|
+
export declare function getValidSignals(protocol: Protocol, phaseId: string): string[];
|
|
49
|
+
/**
|
|
50
|
+
* Common signals used across protocols
|
|
51
|
+
*/
|
|
52
|
+
export declare const CommonSignals: {
|
|
53
|
+
readonly SPEC_DRAFTED: "SPEC_DRAFTED";
|
|
54
|
+
readonly SPEC_READY: "SPEC_READY";
|
|
55
|
+
readonly REVISION_COMPLETE: "REVISION_COMPLETE";
|
|
56
|
+
readonly PLAN_DRAFTED: "PLAN_DRAFTED";
|
|
57
|
+
readonly PLAN_READY: "PLAN_READY";
|
|
58
|
+
readonly PHASE_IMPLEMENTED: "PHASE_IMPLEMENTED";
|
|
59
|
+
readonly IMPLEMENTATION_COMPLETE: "IMPLEMENTATION_COMPLETE";
|
|
60
|
+
readonly TESTS_WRITTEN: "TESTS_WRITTEN";
|
|
61
|
+
readonly TESTS_PASSING: "TESTS_PASSING";
|
|
62
|
+
readonly EVALUATION_COMPLETE: "EVALUATION_COMPLETE";
|
|
63
|
+
readonly PHASE_COMPLETE: "PHASE_COMPLETE";
|
|
64
|
+
readonly REVIEW_COMPLETE: "REVIEW_COMPLETE";
|
|
65
|
+
readonly UNDERSTOOD: "UNDERSTOOD";
|
|
66
|
+
readonly IMPLEMENTED: "IMPLEMENTED";
|
|
67
|
+
readonly VERIFIED: "VERIFIED";
|
|
68
|
+
readonly DIAGNOSED: "DIAGNOSED";
|
|
69
|
+
readonly FIXED: "FIXED";
|
|
70
|
+
readonly TESTED: "TESTED";
|
|
71
|
+
readonly PR_CREATED: "PR_CREATED";
|
|
72
|
+
readonly COMPLETE: "COMPLETE";
|
|
73
|
+
readonly BLOCKED: "BLOCKED";
|
|
74
|
+
readonly NEEDS_CLARIFICATION: "NEEDS_CLARIFICATION";
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Format a signal for output
|
|
78
|
+
*/
|
|
79
|
+
export declare function formatSignal(signal: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Check if output contains any signal
|
|
82
|
+
*/
|
|
83
|
+
export declare function hasSignal(output: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Strip all signals from output (for clean display)
|
|
86
|
+
*/
|
|
87
|
+
export declare function stripSignals(output: string): string;
|
|
88
|
+
//# sourceMappingURL=signal-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-parser.d.ts","sourceRoot":"","sources":["../../../src/commands/porch/signal-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAS,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAwB1D;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,MAAM,GACnB,YAAY,CAoBd;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAI7E;AAED;;GAEG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;CAwChB,CAAC;AAEX;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal Parser
|
|
3
|
+
*
|
|
4
|
+
* Extracts signals from Claude output and validates them against protocol definitions.
|
|
5
|
+
* Signals use XML-style tags: <signal>SIGNAL_NAME</signal>
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Extract signal from Claude output
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - Scan for <signal>...</signal> patterns
|
|
12
|
+
* - Return the LAST signal found (multiple signals → last wins)
|
|
13
|
+
* - Return null if no signal found
|
|
14
|
+
*/
|
|
15
|
+
export function extractSignal(output) {
|
|
16
|
+
const matches = output.match(/<signal>([^<]+)<\/signal>/gi);
|
|
17
|
+
if (!matches || matches.length === 0)
|
|
18
|
+
return null;
|
|
19
|
+
// Get the last match
|
|
20
|
+
const lastMatch = matches[matches.length - 1];
|
|
21
|
+
const signalMatch = lastMatch.match(/<signal>([^<]+)<\/signal>/i);
|
|
22
|
+
return signalMatch ? signalMatch[1].trim() : null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Extract all signals from output
|
|
26
|
+
*/
|
|
27
|
+
export function extractAllSignals(output) {
|
|
28
|
+
const matches = output.match(/<signal>([^<]+)<\/signal>/gi);
|
|
29
|
+
if (!matches)
|
|
30
|
+
return [];
|
|
31
|
+
return matches.map(match => {
|
|
32
|
+
const signalMatch = match.match(/<signal>([^<]+)<\/signal>/i);
|
|
33
|
+
return signalMatch ? signalMatch[1].trim() : '';
|
|
34
|
+
}).filter(Boolean);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validate a signal against the protocol definition
|
|
38
|
+
*
|
|
39
|
+
* Returns true if the signal is valid for the current phase.
|
|
40
|
+
* Unknown signals are logged but considered valid (lenient mode).
|
|
41
|
+
*/
|
|
42
|
+
export function validateSignal(signal, protocol, currentState) {
|
|
43
|
+
const [phaseId, substate] = currentState.split(':');
|
|
44
|
+
const phase = protocol.phases.find(p => p.id === phaseId);
|
|
45
|
+
if (!phase) {
|
|
46
|
+
return {
|
|
47
|
+
valid: false,
|
|
48
|
+
warning: `Unknown phase: ${phaseId}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Check if signal is defined for this phase
|
|
52
|
+
if (phase.signals && phase.signals[signal]) {
|
|
53
|
+
return {
|
|
54
|
+
valid: true,
|
|
55
|
+
nextState: phase.signals[signal],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// Signal not defined - lenient mode: allow but warn
|
|
59
|
+
return {
|
|
60
|
+
valid: true, // Allow unknown signals to prevent blocking
|
|
61
|
+
warning: `Signal "${signal}" not defined in protocol for phase ${phaseId}`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Extract and validate signal from output
|
|
66
|
+
*/
|
|
67
|
+
export function parseSignal(output, protocol, currentState) {
|
|
68
|
+
const signal = extractSignal(output);
|
|
69
|
+
const allSignals = extractAllSignals(output);
|
|
70
|
+
if (!signal) {
|
|
71
|
+
return {
|
|
72
|
+
signal: null,
|
|
73
|
+
allSignals: [],
|
|
74
|
+
isValid: true, // No signal is valid (use default transition)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const validation = validateSignal(signal, protocol, currentState);
|
|
78
|
+
return {
|
|
79
|
+
signal,
|
|
80
|
+
allSignals,
|
|
81
|
+
isValid: validation.valid,
|
|
82
|
+
error: validation.warning,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get valid signals for a phase
|
|
87
|
+
*/
|
|
88
|
+
export function getValidSignals(protocol, phaseId) {
|
|
89
|
+
const phase = protocol.phases.find(p => p.id === phaseId);
|
|
90
|
+
if (!phase?.signals)
|
|
91
|
+
return [];
|
|
92
|
+
return Object.keys(phase.signals);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Common signals used across protocols
|
|
96
|
+
*/
|
|
97
|
+
export const CommonSignals = {
|
|
98
|
+
// Specify phase
|
|
99
|
+
SPEC_DRAFTED: 'SPEC_DRAFTED',
|
|
100
|
+
SPEC_READY: 'SPEC_READY',
|
|
101
|
+
REVISION_COMPLETE: 'REVISION_COMPLETE',
|
|
102
|
+
// Plan phase
|
|
103
|
+
PLAN_DRAFTED: 'PLAN_DRAFTED',
|
|
104
|
+
PLAN_READY: 'PLAN_READY',
|
|
105
|
+
// Implement phase
|
|
106
|
+
PHASE_IMPLEMENTED: 'PHASE_IMPLEMENTED',
|
|
107
|
+
IMPLEMENTATION_COMPLETE: 'IMPLEMENTATION_COMPLETE',
|
|
108
|
+
// Defend phase
|
|
109
|
+
TESTS_WRITTEN: 'TESTS_WRITTEN',
|
|
110
|
+
TESTS_PASSING: 'TESTS_PASSING',
|
|
111
|
+
// Evaluate phase
|
|
112
|
+
EVALUATION_COMPLETE: 'EVALUATION_COMPLETE',
|
|
113
|
+
PHASE_COMPLETE: 'PHASE_COMPLETE',
|
|
114
|
+
// Review phase
|
|
115
|
+
REVIEW_COMPLETE: 'REVIEW_COMPLETE',
|
|
116
|
+
// TICK protocol
|
|
117
|
+
UNDERSTOOD: 'UNDERSTOOD',
|
|
118
|
+
IMPLEMENTED: 'IMPLEMENTED',
|
|
119
|
+
VERIFIED: 'VERIFIED',
|
|
120
|
+
// BUGFIX protocol
|
|
121
|
+
DIAGNOSED: 'DIAGNOSED',
|
|
122
|
+
FIXED: 'FIXED',
|
|
123
|
+
TESTED: 'TESTED',
|
|
124
|
+
PR_CREATED: 'PR_CREATED',
|
|
125
|
+
// General
|
|
126
|
+
COMPLETE: 'COMPLETE',
|
|
127
|
+
BLOCKED: 'BLOCKED',
|
|
128
|
+
NEEDS_CLARIFICATION: 'NEEDS_CLARIFICATION',
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Format a signal for output
|
|
132
|
+
*/
|
|
133
|
+
export function formatSignal(signal) {
|
|
134
|
+
return `<signal>${signal}</signal>`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if output contains any signal
|
|
138
|
+
*/
|
|
139
|
+
export function hasSignal(output) {
|
|
140
|
+
return /<signal>[^<]+<\/signal>/i.test(output);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Strip all signals from output (for clean display)
|
|
144
|
+
*/
|
|
145
|
+
export function stripSignals(output) {
|
|
146
|
+
return output.replace(/<signal>[^<]+<\/signal>/gi, '').trim();
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=signal-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-parser.js","sourceRoot":"","sources":["../../../src/commands/porch/signal-parser.ts"],"names":[],"mappings":"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"}
|