mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-11 19:20:26 +01:00
fix: Step 11 review fixes (resume on dispatched voice models, case-insensitive family, every outside voice checked)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
286ee88337
commit
4dc0880e81
2 files changed
+63
-20
No files matched your search
+35
-19
@@ -74,36 +74,45 @@ const briefText = async (r) => {
|
||||
};
|
||||
const roleArgs = (r) => ' --role ' + q(r.role) + (r.name ? ' --name ' + q(r.name) : '');
|
||||
const REASONING = { medium: 'medium', light: 'low' };
|
||||
const family = (id) => (typeof id === 'string' && id.includes('/') ? id.slice(0, id.indexOf('/')) : '');
|
||||
const family = (id) => (typeof id === 'string' && id.includes('/') ? id.slice(0, id.indexOf('/')).toLowerCase() : '');
|
||||
const CERTIFIED_OUTSIDE = { model_id: 'openai/gpt-6.1-sol', reasoning_mode: 'medium' };
|
||||
const laneFamily = family(input.laneModel);
|
||||
const modelOf = (r) => r.model || (input.models || {})[r.role === 'specialist-batched' ? 'specialist' : r.role]
|
||||
const voiceFile = input.out.replace(/\/+$/, '') + '/voice-models.json';
|
||||
let voices = { laneModel: null, readers: {} };
|
||||
let laneFamily = family(input.laneModel);
|
||||
const modelOf = (r) => r.model || (r.reader in voices.readers ? voices.readers[r.reader] || undefined
|
||||
: (input.models || {})[r.role === 'specialist-batched' ? 'specialist' : r.role]
|
||||
|| (r.role === 'outside-voice' && laneFamily === 'anthropic' ? CERTIFIED_OUTSIDE : undefined)
|
||||
|| (REASONING[r.effort] && input.laneModel ? { model_id: input.laneModel, reasoning_mode: REASONING[r.effort] } : undefined);
|
||||
const outsideNote = (r) => {
|
||||
|| (REASONING[r.effort] && input.laneModel ? { model_id: input.laneModel, reasoning_mode: REASONING[r.effort] } : undefined));
|
||||
const outsideNote = (r, source) => {
|
||||
const ov = modelOf(r);
|
||||
const certified = laneFamily === 'anthropic' && ov.model_id === CERTIFIED_OUTSIDE.model_id && ov.reasoning_mode === CERTIFIED_OUTSIDE.reasoning_mode;
|
||||
return 'OUTSIDE_VOICE: ' + ov.model_id + ' reasoning=' + (ov.reasoning_mode || 'default') + ((input.models || {})['outside-voice'] ? ' given' : ' default for an anthropic lane')
|
||||
return 'OUTSIDE_VOICE: ' + ov.model_id + ' reasoning=' + (ov.reasoning_mode || 'default') + ' ' + source
|
||||
+ (certified ? ' (certified configuration)' : '; outside the certified configuration (' + CERTIFIED_OUTSIDE.model_id + ' at ' + CERTIFIED_OUTSIDE.reasoning_mode + ' beside an anthropic lane)');
|
||||
};
|
||||
const familyStop = (readers) => {
|
||||
const ov = readers.find((x) => x.role === 'outside-voice' && !['created', 'collected', 'failed'].includes(x.state));
|
||||
if (!ov) return null;
|
||||
const om = modelOf(ov);
|
||||
if (!om) return "the outside voice needs input.models['outside-voice'] (a model of another family); none was given";
|
||||
const native = readers.find((x) => x.role === 'adversarial-native');
|
||||
const nativeFamily = family(native && modelOf(native) ? modelOf(native).model_id : undefined);
|
||||
if (!laneFamily && !nativeFamily) return 'the outside voice ' + om.model_id + ' cannot be checked against another family: neither input.laneModel nor a native voice model was given';
|
||||
const f = family(om.model_id);
|
||||
if (!f) return 'the outside voice ' + om.model_id + ' has no provider prefix, so its family cannot be checked';
|
||||
if (f !== laneFamily && f !== nativeFamily) return null;
|
||||
return 'the outside voice ' + om.model_id + ' is the ' + f + ' family, the same as the ' + (f === nativeFamily ? 'native voice' : 'lane model') + "; Step 11 needs input.models['outside-voice'] from another family";
|
||||
for (const ov of readers.filter((x) => x.role === 'outside-voice' && !['created', 'collected', 'failed'].includes(x.state))) {
|
||||
const om = modelOf(ov);
|
||||
if (!om) return "the outside voice needs input.models['outside-voice'] (a model of another family); none was given";
|
||||
const lane = voices.laneModel || input.laneModel;
|
||||
if (!laneFamily && !nativeFamily) return 'the outside voice ' + om.model_id + ' cannot be checked against another family: ' + (lane ? 'the lane model ' + lane + ' has no provider prefix and no native voice model was given' : 'neither input.laneModel nor a native voice model was given');
|
||||
const f = family(om.model_id);
|
||||
if (!f) return 'the outside voice ' + om.model_id + ' has no provider prefix, so its family cannot be checked';
|
||||
if (f === laneFamily || f === nativeFamily) return 'the outside voice ' + om.model_id + ' is the ' + f + ' family, the same as the ' + (f === nativeFamily ? 'native voice' : 'lane model') + "; Step 11 needs input.models['outside-voice'] from another family";
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const safe = (s) => s.replace(/[^a-zA-Z0-9._-]/g, '_');
|
||||
const active = input.stage === 'voices' ? ['voices'] : ['first', 'specialists', 'red-team'];
|
||||
|
||||
try {
|
||||
let m = await load();
|
||||
if (input.stage === 'voices') {
|
||||
const v = await sh('cat ' + q(voiceFile) + ' 2>/dev/null || true');
|
||||
if (v.out.trim()) voices = JSON.parse(v.out);
|
||||
if (voices.laneModel) laneFamily = family(voices.laneModel);
|
||||
}
|
||||
if (input.stage === 'voices' && !m.readers.some((r) => r.stage === 'voices')) return finish(['VOICES: none (the pass plan lists no Step 11 voice)', 'NEXT: judge']);
|
||||
for (const s of input.logStart || []) {
|
||||
const key = (input.stage === 'voices' ? 'voices:' : 'pass:') + s;
|
||||
@@ -116,8 +125,6 @@ try {
|
||||
lines.push('REVIEW_LOG_START: ' + s + ' token=' + token);
|
||||
}
|
||||
for (;;) {
|
||||
const sameFamily = input.stage === 'voices' && familyStop(m.readers);
|
||||
if (sameFamily) return stop(sameFamily);
|
||||
const failed = m.readers.find((x) => active.includes(x.stage) && x.state === 'failed');
|
||||
if (failed) return stop(failed.reader + ' (subagent ' + failed.path + ') ' + (failed.error || 'failed') + '; its review is incomplete, so the pass cannot certify coverage; restore it with a fresh pass under a new --pass and --out');
|
||||
const list = await tools.subagent.list({});
|
||||
@@ -129,12 +136,17 @@ try {
|
||||
await mark(r.reader, found[0].status === 'draft' ? 'queued' : 'created', { path: found[0].path });
|
||||
}
|
||||
m = await load();
|
||||
const sameFamily = input.stage === 'voices' && familyStop(m.readers);
|
||||
if (sameFamily) return stop(sameFamily);
|
||||
for (const r of m.readers.filter((x) => active.includes(x.stage) && x.state === 'queued')) {
|
||||
const t = byPath.get(r.path);
|
||||
if (t && t.status !== 'draft') { await mark(r.reader, 'created', {}); continue; }
|
||||
const model = modelOf(r);
|
||||
const s = await tools.subagent.start({ indices: [Number(r.path)], machine: 'shared', ...(model ? { model } : {}) });
|
||||
if ((s.started || []).length) await mark(r.reader, 'created', {});
|
||||
if ((s.started || []).length) {
|
||||
if (r.role === 'outside-voice') lines.push(outsideNote(r, 'as dispatched, started from the queue'));
|
||||
await mark(r.reader, 'created', {});
|
||||
}
|
||||
else if (r.state_at && (await now()) - Date.parse(r.state_at) > stuckMs) return stop(r.reader + ' (subagent ' + r.path + ') still queued after ' + Math.round(stuckMs / 60000) + ' minutes; free a subagent slot, then rerun');
|
||||
}
|
||||
for (const r of m.readers.filter((x) => active.includes(x.stage) && x.state === 'created')) {
|
||||
@@ -186,7 +198,11 @@ try {
|
||||
const b = await reading();
|
||||
if (b) { await sh(bin + ' mark --manifest ' + q(mf) + ' --before ' + b.tokens + ',' + b.credits); m.before = b; }
|
||||
}
|
||||
if (r.role === 'outside-voice') lines.push(outsideNote(r));
|
||||
if (r.role === 'outside-voice') lines.push(outsideNote(r, r.model || (input.models || {})['outside-voice'] ? 'given' : 'default for an anthropic lane'));
|
||||
if (r.stage === 'voices') {
|
||||
voices = { laneModel: voices.laneModel || input.laneModel || null, readers: { ...voices.readers, [r.reader]: model || null } };
|
||||
await tools.capy.write({ path: voiceFile, content: JSON.stringify(voices) });
|
||||
}
|
||||
await mark(r.reader, 'intent', {});
|
||||
const res = await tools.subagent.create({ tasks: [{ title: r.title, prompt: text }], start: { machine: 'shared', ...(model ? { model } : {}) } });
|
||||
const idx = String(res.tasks[0].index);
|
||||
|
||||
Reference in new issue
Block a user