@kaydash9999/banker-plugins 0.22.0 → 0.23.2
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +68 -0
- package/PRIVACY.md +1 -0
- package/README.md +39 -13
- package/bin/banker.js +118 -22
- package/bin/lib/codex-hooks.mjs +116 -18
- package/bin/lib/codex-names.mjs +4 -0
- package/bin/lib/codex-routes.mjs +93 -1
- package/bin/lib/command-skill.cjs +37 -6
- package/codex/command-skills/front-qa/SKILL.md +1 -1
- package/codex/command-skills/setup/SKILL.md +4 -4
- package/codex/hooks.json +5 -5
- package/codex/manifest.json +18 -15
- package/codex/skills/progress/scripts/progress.mjs +44 -14
- package/codex/skills/teamwork/SKILL.md +143 -0
- package/codex/skills/teamwork/scripts/teamwork.mjs +1007 -0
- package/codex/transform-matrix.md +5 -3
- package/hooks/obsidize-hook.mjs +75 -32
- package/hooks/telemetry-count-codex.mjs +238 -57
- package/hooks/update-fetch.mjs +2 -1
- package/hooks/update-notify.mjs +82 -20
- package/package.json +3 -1
- package/skills/3d-intro-build/SKILL.md +101 -20
- package/skills/3d-intro-build/references/NOTICE.md +9 -2
- package/skills/3d-intro-build/references/assemble.mjs +113 -22
- package/skills/3d-intro-build/references/azure-adapter.mjs +110 -24
- package/skills/3d-intro-build/references/clip-post.mjs +443 -0
- package/skills/3d-intro-build/references/dive-mode.mjs +299 -0
- package/skills/3d-intro-build/references/intro-fixes.css +11 -0
- package/skills/3d-intro-build/references/prompts.md +51 -4
- package/skills/3d-intro-build/references/scrub-engine.js +1 -0
- package/skills/3d-intro-build/references/step-nav.css +29 -0
- package/skills/3d-intro-build/references/step-nav.js +284 -106
- package/skills/3d-intro-build/references/verify-intro.mjs +373 -32
- package/skills/3d-intro-build/references/verify.md +6 -0
- package/skills/3d-intro-build/references/video-pool.mjs +142 -12
- package/skills/3d-intro-setup/SKILL.md +20 -7
- package/skills/3d-intro-setup/references/azure-adapter.mjs +110 -24
- package/skills/3d-intro-setup/references/video-pool.mjs +142 -12
- package/skills/all-in-one/SKILL.md +125 -86
- package/skills/omc-patch/SKILL.md +1 -1
- package/skills/payload-mon/SKILL.md +1 -1
- package/skills/play-qa/SKILL.md +6 -4
- package/skills/progress-mon/README.md +164 -0
- package/skills/progress-mon/SKILL.md +165 -0
- package/skills/progress-mon/assets/fixture/README.md +1 -0
- package/skills/progress-mon/assets/fixture/arch.json +33 -0
- package/skills/progress-mon/assets/fixture/commits.json +7 -0
- package/skills/progress-mon/assets/fixture/config.json +30 -0
- package/skills/progress-mon/assets/fixture/events.jsonl +7 -0
- package/skills/progress-mon/assets/fixture/flow.json +44 -0
- package/skills/progress-mon/assets/fixture/items.json +14 -0
- package/skills/progress-mon/assets/fixture/req-spec.json +31 -0
- package/skills/progress-mon/assets/fixture/reqs.json +11 -0
- package/skills/progress-mon/assets/fixture/variants/arch-auto/arch.json +58 -0
- package/skills/progress-mon/assets/fixture/variants/check-auto/arch.json +15 -0
- package/skills/progress-mon/assets/fixture/variants/check-overlap/arch.json +14 -0
- package/skills/progress-mon/assets/fixture/variants/history-manual/config.json +13 -0
- package/skills/progress-mon/assets/fixture/variants/history-manual/items.json +7 -0
- package/skills/progress-mon/assets/fixture/variants/workflow-wide/flow.json +35 -0
- package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a01.jsonl +1 -0
- package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a02.jsonl +1 -0
- package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a03.jsonl +1 -0
- package/skills/progress-mon/assets/fixture/workflows/wf_ex1/agent-a04.jsonl +1 -0
- package/skills/progress-mon/assets/fixture/workflows/wf_ex1/journal.jsonl +7 -0
- package/skills/progress-mon/references/arch.md +280 -0
- package/skills/progress-mon/references/authoring.md +199 -0
- package/skills/progress-mon/references/config.md +115 -0
- package/skills/progress-mon/references/flow.md +75 -0
- package/skills/progress-mon/references/inventory.md +58 -0
- package/skills/progress-mon/references/items.md +74 -0
- package/skills/progress-mon/references/req-spec.md +74 -0
- package/skills/progress-mon/references/reqs.md +30 -0
- package/skills/progress-mon/scripts/index.js +31 -0
- package/skills/progress-mon/scripts/pm-check.mjs +549 -0
- package/skills/progress-mon/scripts/pm-config.mjs +343 -0
- package/skills/progress-mon/scripts/pm-data.mjs +394 -0
- package/skills/progress-mon/scripts/pm-html.mjs +77 -0
- package/skills/progress-mon/scripts/pm-memory.mjs +333 -0
- package/skills/progress-mon/scripts/pm-render.mjs +1644 -0
- package/skills/progress-mon/scripts/pm-server.mjs +781 -0
- package/skills/progress-mon/scripts/pm-sources.mjs +501 -0
- package/skills/progress-mon/scripts/progress-mon.mjs +167 -0
- package/skills/ralph-qa/SKILL.md +107 -17
- package/skills/ralph-qa/references/gate-evidence.mjs +457 -0
- package/skills/ralph-qa/references/payload-scan.mjs +19 -2
- package/skills/ralph-qa/references/run-folder.mjs +299 -0
- package/skills/ralph-qa/references/seat-payload.mjs +60 -13
- package/skills/ralph-qa/references/seat-run.mjs +200 -159
- package/skills/remains/SKILL.md +2 -0
- package/skills/remains/scripts/boxes.mjs +6 -2
- package/skills/setup-bypass-permissions/scripts/codex-config.mjs +19 -8
- package/skills/setup-mcp/SKILL.md +1 -1
- package/skills/setup-omc-hud/SKILL.md +2 -1
- package/skills/setup-omc-hud/assets/codex-config.mjs +19 -8
- package/skills/ultra-chain/SKILL.md +32 -14
- package/skills/ultra-chain/references/chain-ledger.mjs +111 -3
- package/skills/ultra-init/SKILL.md +30 -22
- package/skills/ultraqa/NOTICE.md +34 -0
- package/skills/ultraqa/SKILL.md +197 -0
- package/skills/ultraqa/references/gate-evidence.mjs +457 -0
- package/skills/ultraqa/references/run-folder.mjs +299 -0
- package/skills/ultraqa/references/tmux-drive.md +52 -0
- package/skills/ultraqa/references/uqa-run.mjs +339 -0
- package/skills/update-banker/SKILL.md +1 -1
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
*
|
|
29
29
|
* Pool state lives in ~/.config/banker/3d-intro/video-pool-state.json (0600). It holds
|
|
30
30
|
* FINGERPRINTS (sha256 of endpoint+key+model), never a key, so a rotated key or a changed model
|
|
31
|
-
* starts with a clean record.
|
|
31
|
+
* starts with a clean record. A Sora deployment that answered 410 (retired) is recorded under the
|
|
32
|
+
* fingerprint of its endpoint origin and deployment name, and Sora is skipped for 24 h.
|
|
33
|
+
* State is advisory: a failed write is reported, never fatal.
|
|
32
34
|
* Concurrent processes share the file last-write-wins; the per-key in-flight limit is per process.
|
|
33
35
|
*
|
|
34
36
|
* Runtime: Node >=18 builtins only. globalThis.fetch and cp.spawnSync are read at call time so
|
|
@@ -40,7 +42,7 @@ import os from 'node:os';
|
|
|
40
42
|
import crypto from 'node:crypto';
|
|
41
43
|
import cp from 'node:child_process';
|
|
42
44
|
import {
|
|
43
|
-
createVideo, pollVideo, downloadVideo, resolveFfmpeg, redact, fetchGuarded, safeForKey, keyHeldBack,
|
|
45
|
+
createVideo, pollVideo, downloadVideo, resolveFfmpeg, redact, fetchGuarded, safeForKey, keyHeldBack, probeSoraDeployment,
|
|
44
46
|
API_TIMEOUT_MS, DOWNLOAD_TIMEOUT_MS, HELD_KEY, errnoOf, timeLeft,
|
|
45
47
|
} from './azure-adapter.mjs';
|
|
46
48
|
|
|
@@ -213,13 +215,17 @@ function updateEntry(file, entry, fn, emit) {
|
|
|
213
215
|
}
|
|
214
216
|
}
|
|
215
217
|
|
|
216
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* Clear recorded state for all entries, or only for the given labels (e.g. ['WAN_2']). 'AZURE_SORA'
|
|
220
|
+
* clears the Sora retirement record (every Sora deployment's, so creds are not needed for it).
|
|
221
|
+
*/
|
|
217
222
|
export function resetPoolState({ statePath = defaultStatePath(), creds, labels } = {}) {
|
|
218
223
|
const state = loadPoolState(statePath);
|
|
219
224
|
if (!labels) state.entries = {};
|
|
220
225
|
else {
|
|
221
226
|
const fps = new Set(loadWanPool(creds).filter((e) => labels.includes(e.label)).map((e) => e.fp));
|
|
222
|
-
|
|
227
|
+
const sora = labels.includes(SORA_LABEL);
|
|
228
|
+
for (const [fp, st] of Object.entries(state.entries)) if (fps.has(fp) || (sora && st?.label === SORA_LABEL)) delete state.entries[fp];
|
|
223
229
|
}
|
|
224
230
|
return savePoolState(state, statePath);
|
|
225
231
|
}
|
|
@@ -235,14 +241,62 @@ function entryStatus(st, t) {
|
|
|
235
241
|
return { status: 'ok' };
|
|
236
242
|
}
|
|
237
243
|
|
|
238
|
-
/**
|
|
244
|
+
/**
|
|
245
|
+
* Per-entry availability for reporting: one row per WAN entry (provider 'wan'), then one Sora row
|
|
246
|
+
* (label AZURE_SORA, provider 'sora', status ok | retired | unset | malformed). Never includes a key,
|
|
247
|
+
* nor a malformed endpoint or model.
|
|
248
|
+
*/
|
|
239
249
|
export function poolSummary({ creds = {}, statePath = defaultStatePath(), now = Date.now() } = {}) {
|
|
240
250
|
const state = loadPoolState(statePath);
|
|
241
|
-
|
|
251
|
+
const wan = loadWanPool(creds).map((e) => {
|
|
242
252
|
const st = state.entries[e.fp];
|
|
243
253
|
const field = malformedField(e);
|
|
244
|
-
return { ...shownEntry(e), okCount: st?.okCount || 0, ...(field ? { status: 'malformed', reason: field } : entryStatus(st, now)) };
|
|
254
|
+
return { ...shownEntry(e), provider: 'wan', okCount: st?.okCount || 0, ...(field ? { status: 'malformed', reason: field } : entryStatus(st, now)) };
|
|
245
255
|
});
|
|
256
|
+
return [...wan, soraSummary(creds, state, now)];
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// The Sora row of poolSummary.
|
|
260
|
+
function soraSummary(creds, state, t) {
|
|
261
|
+
const conn = soraConn(creds);
|
|
262
|
+
const base = { label: SORA_LABEL, provider: 'sora', model: isModelId(conn.model) ? conn.model : '(invalid model)' };
|
|
263
|
+
if (!conn.endpoint || !conn.key) return { ...base, host: null, status: 'unset' };
|
|
264
|
+
if (!originOf(conn.endpoint)) return { ...base, host: '(invalid endpoint)', status: 'malformed', reason: 'endpoint' };
|
|
265
|
+
const rec = retiredIn(state, conn, t);
|
|
266
|
+
const status = rec ? { status: 'retired', reason: rec.reason, retiredAt: rec.retiredAt, until: rec.retiredAt + SORA_RETIRED_TTL_MS } : { status: 'ok' };
|
|
267
|
+
return { ...base, host: hostOf(originOf(conn.endpoint)), ...status };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The CLIP_MODE a run starts with (FREE, nothing is sent): dive without exits on any provider (the user
|
|
272
|
+
* found it the most natural of the three on the sora-2 comparison page). Returns { mode, exit, provider,
|
|
273
|
+
* measured, reason }: provider is the first one generateClip would really use (VIDEO_PROVIDER_ORDER), and
|
|
274
|
+
* measured is false on WAN (dive on WAN is not measured; say so when the user picks). mode is null when
|
|
275
|
+
* no leg could be made: every WAN entry refused (generateClip stops there and does not use Sora), a Sora
|
|
276
|
+
* endpoint that is not https, or nothing set up (no WAN entry, Sora unset or recorded retired).
|
|
277
|
+
*/
|
|
278
|
+
export function defaultClipMode(creds = {}, { statePath = defaultStatePath(), now = Date.now() } = {}) {
|
|
279
|
+
for (const p of parseProviderOrder(creds.VIDEO_PROVIDER_ORDER)) {
|
|
280
|
+
const r = p === 'wan' ? wanMode(creds) : soraMode(creds, loadPoolState(statePath), now);
|
|
281
|
+
if (r) return r;
|
|
282
|
+
}
|
|
283
|
+
return { mode: null, provider: null, reason: 'no video provider: no WAN entry, and Sora is unset or recorded retired' };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function wanMode(creds) {
|
|
287
|
+
const pool = loadWanPool(creds);
|
|
288
|
+
if (!pool.length) return null;
|
|
289
|
+
if (pool.every((e) => entryRefusal(e))) return { mode: null, provider: 'wan', reason: 'every WAN entry is malformed or held back: generateClip stops there and does not use Sora' };
|
|
290
|
+
return { mode: 'dive', exit: false, provider: 'wan', measured: false, reason: 'the video runs on WAN: dive without exits (dive on WAN is not measured)' };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function soraMode(creds, state, t) {
|
|
294
|
+
const conn = soraConn(creds);
|
|
295
|
+
if (!conn.endpoint || !conn.key) return null;
|
|
296
|
+
const origin = originOf(conn.endpoint);
|
|
297
|
+
if (!origin || proxyHolds(origin)) return { mode: null, provider: 'sora', reason: 'AZURE_SORA_ENDPOINT is not an https URL (or the env proxy holds the key back): the leg stops before sending' };
|
|
298
|
+
if (retiredIn(state, conn, t)) return null;
|
|
299
|
+
return { mode: 'dive', exit: false, provider: 'sora', measured: true, reason: 'the video runs on Sora: dive without exits (measured on sora-2 2025-12-08)' };
|
|
246
300
|
}
|
|
247
301
|
|
|
248
302
|
// In-process in-flight counter per fingerprint (the documented limit is per key).
|
|
@@ -728,6 +782,60 @@ function soraConn(creds) {
|
|
|
728
782
|
};
|
|
729
783
|
}
|
|
730
784
|
|
|
785
|
+
// ---------------------------------------------------------------------------
|
|
786
|
+
// Sora retirement (HTTP 410). A 410 on the submit is the model's retirement at once. A 410 on a poll
|
|
787
|
+
// or a download may also be a job that expired, so it counts only when the free deployment probe says
|
|
788
|
+
// retired. The record keeps Sora from being sent the next legs for 24 h.
|
|
789
|
+
// ---------------------------------------------------------------------------
|
|
790
|
+
|
|
791
|
+
const SORA_LABEL = 'AZURE_SORA';
|
|
792
|
+
const SORA_RETIRED_TTL_MS = 24 * 3_600_000;
|
|
793
|
+
// The Sora record's name in the state file: endpoint origin and deployment, never the key.
|
|
794
|
+
const soraFp = (conn) => `sora:${crypto.createHash('sha256').update(`${originOf(conn.endpoint)}\n${conn.model}`).digest('hex').slice(0, 16)}`;
|
|
795
|
+
|
|
796
|
+
function retiredIn(state, conn, t) {
|
|
797
|
+
const st = state.entries[soraFp(conn)];
|
|
798
|
+
return st?.status === 'retired' && t - st.retiredAt < SORA_RETIRED_TTL_MS ? st : null;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
function recordSoraRetired(ctx, conn, stage) {
|
|
802
|
+
const t = ctx.now();
|
|
803
|
+
updateEntry(ctx.statePath, { fp: soraFp(conn), label: SORA_LABEL }, (st) => ({ ...st, status: 'retired', retiredAt: t, reason: `HTTP 410 (${stage})` }), ctx.emit);
|
|
804
|
+
ctx.emit({ type: 'fail', provider: 'sora', label: SORA_LABEL, kind: 'retired', status: 410, stage });
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
const soraWhere = (conn) => `Sora deployment ${isModelId(conn.model) ? conn.model : '(invalid model)'} on ${hostOf(originOf(conn.endpoint))}`;
|
|
808
|
+
const SORA_RETIRED_NEXT = "add a WAN key (3d-intro-setup), or deploy a newer Sora model and clear the record with resetPoolState({ labels: ['AZURE_SORA'] })";
|
|
809
|
+
|
|
810
|
+
function soraRetiredStop(conn, stage, taskId) {
|
|
811
|
+
const job = taskId ? `job ${taskId} may have billed` : 'no job was made';
|
|
812
|
+
return stopError('retired', `${soraWhere(conn)} is retired (HTTP 410 on the ${stage}); ${job}; Sora is skipped for 24 h — ${SORA_RETIRED_NEXT}`, { provider: 'sora', label: SORA_LABEL, status: 410, ...(taskId ? { taskId } : {}) });
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Sora was skipped for its record, and no other provider took the leg.
|
|
816
|
+
function soraSkippedStop(conn, rec) {
|
|
817
|
+
return stopError('retired', `${soraWhere(conn)} was recorded retired (${rec.reason}) at ${new Date(rec.retiredAt).toISOString()}, and no WAN key could take the leg; nothing was sent — ${SORA_RETIRED_NEXT}`, { provider: 'sora', label: SORA_LABEL, retiredAt: rec.retiredAt });
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// One free probe per process and deployment.
|
|
821
|
+
const soraProbes = new Map();
|
|
822
|
+
function probeSoraOnce(conn, now) {
|
|
823
|
+
const fp = soraFp(conn);
|
|
824
|
+
if (!soraProbes.has(fp)) {
|
|
825
|
+
soraProbes.set(fp, probeSoraDeployment({ endpoint: conn.endpoint, key: conn.key, deployment: conn.model, now }).catch(() => ({ state: 'unknown', status: null })));
|
|
826
|
+
}
|
|
827
|
+
return soraProbes.get(fp);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// The retired stop for a 410 on a poll or a download when the probe confirms it, else null.
|
|
831
|
+
async function confirmRetired(ctx, conn, stage, jobId) {
|
|
832
|
+
const p = await probeSoraOnce(conn, ctx.now);
|
|
833
|
+
ctx.emit({ type: 'probe', provider: 'sora', label: SORA_LABEL, stage, state: p.state, status: p.status ?? null });
|
|
834
|
+
if (p.state !== 'retired') return null;
|
|
835
|
+
recordSoraRetired(ctx, conn, stage);
|
|
836
|
+
return soraRetiredStop(conn, stage, jobId);
|
|
837
|
+
}
|
|
838
|
+
|
|
731
839
|
// Poll an accepted Sora job to a downloaded clip; same stop rules as finishWanTask.
|
|
732
840
|
async function finishSoraJob(ctx, jobId, secs) {
|
|
733
841
|
const conn = soraConn(ctx.creds);
|
|
@@ -737,13 +845,14 @@ async function finishSoraJob(ctx, jobId, secs) {
|
|
|
737
845
|
if (!st || !SORA_DONE.has(st.status)) {
|
|
738
846
|
throw stopError('timeout', `Sora job ${jobId} still ${st?.status ?? 'unknown'} after polling for ${ctx.now() - t0} ms; resume with resumeClip`, { provider: 'sora', taskId: jobId, label: 'AZURE_SORA', seconds: secs });
|
|
739
847
|
}
|
|
740
|
-
const mp4 = await downloadSoraClip(conn, jobId, secs);
|
|
848
|
+
const mp4 = await downloadSoraClip(ctx, conn, jobId, secs);
|
|
741
849
|
ctx.emit({ type: 'done', provider: 'sora', label: 'AZURE_SORA', taskId: jobId });
|
|
742
850
|
return { mp4, provider: 'sora', label: 'AZURE_SORA', model: conn.model, seconds: secs, taskId: jobId, usage: null };
|
|
743
851
|
}
|
|
744
852
|
|
|
745
853
|
// pollVideo throws on a 4xx other than 408/429 (the job is gone, or the key is refused): such a job
|
|
746
|
-
// never turns terminal, so the leg ends at once as task_lost instead of polling to the deadline.
|
|
854
|
+
// never turns terminal, so the leg ends at once as task_lost instead of polling to the deadline. A 410
|
|
855
|
+
// the deployment probe calls retired ends it as retired.
|
|
747
856
|
async function pollSoraJob(ctx, conn, jobId) {
|
|
748
857
|
const interval = Math.max(0, ctx.pollIntervalMs);
|
|
749
858
|
try {
|
|
@@ -754,6 +863,8 @@ async function pollSoraJob(ctx, conn, jobId) {
|
|
|
754
863
|
});
|
|
755
864
|
} catch (e) {
|
|
756
865
|
if (!e.status) throw e;
|
|
866
|
+
const retired = e.status === 410 && await confirmRetired(ctx, conn, 'poll', jobId);
|
|
867
|
+
if (retired) throw retired;
|
|
757
868
|
throw stopError('task_lost', `Sora poll for job ${jobId} failed: HTTP ${e.status}${e.code ? ` ${e.code}` : ''}; check the job in Azure before resubmitting`, { provider: 'sora', taskId: jobId, label: 'AZURE_SORA', status: e.status, code: e.code });
|
|
758
869
|
}
|
|
759
870
|
}
|
|
@@ -764,10 +875,12 @@ function soraFailure(st, jobId) {
|
|
|
764
875
|
return stopError('failed', `Sora job ${jobId} ended ${st.status}: ${JSON.stringify(st.error || '')}`, { provider: 'sora', taskId: jobId, code });
|
|
765
876
|
}
|
|
766
877
|
|
|
767
|
-
async function downloadSoraClip(conn, jobId, secs) {
|
|
878
|
+
async function downloadSoraClip(ctx, conn, jobId, secs) {
|
|
768
879
|
try {
|
|
769
880
|
return await downloadVideo({ endpoint: conn.endpoint, key: conn.key, id: jobId, apiVersion: conn.apiVersion });
|
|
770
881
|
} catch (err) {
|
|
882
|
+
const retired = err.status === 410 && await confirmRetired(ctx, conn, 'download', jobId);
|
|
883
|
+
if (retired) throw retired;
|
|
771
884
|
throw stopError('download', `${err.message} for Sora job ${jobId}; resume with resumeClip`, { provider: 'sora', taskId: jobId, label: 'AZURE_SORA', seconds: secs });
|
|
772
885
|
}
|
|
773
886
|
}
|
|
@@ -784,7 +897,8 @@ const SORA_SUBMIT_TRIES = 5;
|
|
|
784
897
|
|
|
785
898
|
// A 429 is a refusal, so retrying it cannot double-bill; a lost connection or a bare 5xx can. Each
|
|
786
899
|
// wait is the server's Retry-After, else 30 s doubling, from 1 s to 10 min. A Retry-After longer
|
|
787
|
-
// than maxRateWaitMs is not waited out: the leg stops as `rate` at once, as WAN's waits do.
|
|
900
|
+
// than maxRateWaitMs is not waited out: the leg stops as `rate` at once, as WAN's waits do. A 410 is
|
|
901
|
+
// the deployment's retirement: recorded, and the leg stops as `retired`.
|
|
788
902
|
async function submitSora(ctx, conn, secs) {
|
|
789
903
|
for (let i = 0; ; i++) {
|
|
790
904
|
try {
|
|
@@ -793,6 +907,7 @@ async function submitSora(ctx, conn, secs) {
|
|
|
793
907
|
endpoint: conn.endpoint, key: conn.key, model: conn.model, prompt: ctx.prompt, size: ctx.size, seconds: secs, inputReferencePng: ctx.firstFramePng, apiVersion: conn.apiVersion,
|
|
794
908
|
});
|
|
795
909
|
} catch (e) {
|
|
910
|
+
if (e.status === 410) { recordSoraRetired(ctx, conn, 'submit'); throw soraRetiredStop(conn, 'submit'); }
|
|
796
911
|
if (e.status !== 429 || i >= SORA_SUBMIT_TRIES - 1) throw soraSubmitError(e);
|
|
797
912
|
const want = e.retryAfterMs ?? RATE_BASE_MS * 2 ** i;
|
|
798
913
|
if (want > ctx.maxRateWaitMs) throw soraRateStop(want, ctx.maxRateWaitMs, e.retryAfterMs != null);
|
|
@@ -815,6 +930,10 @@ function soraSubmitError(e) {
|
|
|
815
930
|
if (e.status === 429) {
|
|
816
931
|
return stopError('rate', `Sora still answered HTTP 429 after ${SORA_SUBMIT_TRIES} tries; no job was made — wait, then generate the leg again`, { provider: 'sora', status: 429 });
|
|
817
932
|
}
|
|
933
|
+
if (e.status === 404) {
|
|
934
|
+
// only the status and the code field are read: a message is no contract
|
|
935
|
+
return stopError('invalid_request', `${e.message}; the deployment name may be wrong, or the deployment was removed after its model retired — check AZURE_SORA_DEPLOYMENT (3d-intro-setup §4 checks it for free)`, { provider: 'sora', status: 404, code: e.code || null });
|
|
936
|
+
}
|
|
818
937
|
if (soraMayHaveJob(e)) {
|
|
819
938
|
const answer = e.status === 0 ? e.errno || 'network' : `HTTP ${e.status}`;
|
|
820
939
|
return stopError('submit_unknown', `Sora submit got no usable answer (${answer}); the job may exist — check Azure before resubmitting`, { provider: 'sora', status: e.status });
|
|
@@ -851,6 +970,10 @@ const DEFAULTS = { size: '720x1280', seconds: 5, pollIntervalMs: 15_000, pollTim
|
|
|
851
970
|
* kind 'unreachable' Sora host refused the connection (nothing was sent)
|
|
852
971
|
* kind 'rate' Sora kept answering 429, or asked (Retry-After, err.retryAfterMs) for a
|
|
853
972
|
* wait past maxRateWaitMs (no job was made); wait, then call again
|
|
973
|
+
* kind 'retired' the Sora deployment answered 410 (on the submit, or on a poll or a
|
|
974
|
+
* download the free deployment probe confirmed), or was recorded so in
|
|
975
|
+
* the last 24 h and no WAN key could take the leg; add a WAN key, or
|
|
976
|
+
* deploy a newer model and resetPoolState({ labels: ['AZURE_SORA'] })
|
|
854
977
|
* @returns {Promise<{mp4:Buffer, provider:'wan'|'sora', label:string, model:string, seconds:number, taskId:string, usage:object|null}>}
|
|
855
978
|
*/
|
|
856
979
|
export async function generateClip(opts = {}) {
|
|
@@ -867,17 +990,24 @@ export async function generateClip(opts = {}) {
|
|
|
867
990
|
const clip = await tryProvider(ctx, p, tried);
|
|
868
991
|
if (clip) return clip;
|
|
869
992
|
}
|
|
993
|
+
if (ctx.soraRetired) throw soraSkippedStop(soraConn(o.creds), ctx.soraRetired);
|
|
870
994
|
throw new Error(`generateClip: no video provider available (tried: ${tried.join(', ') || 'none'})`);
|
|
871
995
|
}
|
|
872
996
|
|
|
873
997
|
// One provider's go at the leg: the clip, or null to go on to the next. Sora, once it runs, ends the
|
|
874
|
-
// leg (with a clip or a throw).
|
|
998
|
+
// leg (with a clip or a throw). A Sora deployment recorded retired is skipped before anything is sent.
|
|
875
999
|
async function tryProvider(ctx, p, tried) {
|
|
876
1000
|
if (p === 'wan') {
|
|
877
1001
|
tried.push('wan');
|
|
878
1002
|
return runWan(ctx);
|
|
879
1003
|
}
|
|
880
1004
|
if (p !== 'sora' || !soraReady(ctx)) return null;
|
|
1005
|
+
const rec = retiredIn(loadPoolState(ctx.statePath), soraConn(ctx.creds), ctx.now());
|
|
1006
|
+
if (rec) {
|
|
1007
|
+
ctx.emit({ type: 'skip', provider: 'sora', label: SORA_LABEL, reason: 'retired', retiredAt: rec.retiredAt });
|
|
1008
|
+
ctx.soraRetired = rec;
|
|
1009
|
+
return null;
|
|
1010
|
+
}
|
|
881
1011
|
tried.push('sora');
|
|
882
1012
|
ctx.emit({ type: 'fallback', provider: 'sora', from: tried.slice(0, -1) });
|
|
883
1013
|
return runSora(ctx);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: all-in-one
|
|
3
|
-
description: "코딩 작업을 한 명령으로 계획부터 QA 통과까지 엄격하게 진행. `ralplan` 으로 합의 계획, `ralph` 로 검증 구현을
|
|
4
|
-
argument-hint: "[--short] [--checkpoint] [--critic=critic|architect|codex] [--qa=tests
|
|
3
|
+
description: "코딩 작업을 한 명령으로 계획부터 QA 통과까지 엄격하게 진행. `ralplan` 으로 합의 계획, `ralph` 로 검증 구현을 하고, 두 런타임 모두 `ralph-qa` 의 독립 검토자 3명 이상과 실행기가 돌린 게이트 증거로 마무리. 'all-in-one'/'all in one' 시 사용. 한 줄 수정은 이 스킬 대신 `ralph`, 아이디어 확장은 `autopilot`."
|
|
4
|
+
argument-hint: "[--short] [--checkpoint] [--critic=critic|architect|codex] [--qa=tests,build,lint,typecheck,scenarios] [--codex[=<model>]] [--gemini[=<model>]] [--opencode[=<provider/model>]] [--no-deslop] <task description>"
|
|
5
5
|
level: 4
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -11,8 +11,8 @@ level: 4
|
|
|
11
11
|
|
|
12
12
|
## 0. Prerequisite: OMC 5 with a matching `omc` CLI (check first)
|
|
13
13
|
|
|
14
|
-
This skill orchestrates OMC's `ralplan` → `ralph`, then
|
|
15
|
-
|
|
14
|
+
This skill orchestrates OMC's `ralplan` → `ralph`, then banker's own `ralph-qa`
|
|
15
|
+
as the QA gate. **Check the dependency before Stage 1**; if it is missing or
|
|
16
16
|
stale, **guide installation first** rather than failing mid-pipeline. The `omc`
|
|
17
17
|
check below is for Claude Code; on Codex check OMX instead (`omx --version`), whose
|
|
18
18
|
`ralph` does not use the `omc` CLI.
|
|
@@ -33,11 +33,15 @@ check below is for Claude Code; on Codex check OMX instead (`omx --version`), wh
|
|
|
33
33
|
→ oh-my-claudecode, the `setup-omc` skill, or
|
|
34
34
|
`npm install -g oh-my-claude-sisyphus@latest`), then resume. Do not start a
|
|
35
35
|
pipeline whose Stage 2 will stop.
|
|
36
|
-
-
|
|
37
|
-
|
|
36
|
+
- **Stage 3 is banker's `ralph-qa` on both runtimes.** It ships with banker, so
|
|
37
|
+
the gate needs no OMC or OMX skill; OMC and OMX serve Stages 1 and 2 only.
|
|
38
38
|
- On Codex the equivalent framework is OMX (`omx setup`).
|
|
39
39
|
|
|
40
|
-
**런타임 매핑 (Claude Code ↔ Codex).** Stage 1·2 의 `ralplan`·`ralph` 는 Claude Code에선 OMC 스킬이고 **Codex에선 oh-my-codex(OMX)가 제공하는 동명 스킬**이다. Stage 3 은
|
|
40
|
+
**런타임 매핑 (Claude Code ↔ Codex).** Stage 1·2 의 `ralplan`·`ralph` 는 Claude Code에선 OMC 스킬이고 **Codex에선 oh-my-codex(OMX)가 제공하는 동명 스킬**이다. Stage 3 은 두 런타임 모두 banker `ralph-qa` 다: Claude Code `Skill("banker:ralph-qa")`, Codex npm 길 `$banker-ralph-qa`, 플러그인 길 `$banker:ralph-qa`. Codex 에는 Skill 도구가 없으니 그 `SKILL.md` 를 읽고 그대로 따른다(npm 길 `<S>/../banker-ralph-qa/SKILL.md`, 플러그인 길 `<S>/../ralph-qa/SKILL.md`, `<S>` 는 이 스킬 폴더). `<RQ>` 는 ralph-qa 의 `references` 폴더다(Claude Code 와 Codex 플러그인 길 `<S>/../ralph-qa/references`, Codex npm 길 `<S>/../banker-ralph-qa/references`). 아래 `Skill("oh-my-claudecode:<name>")` 표기는 Claude Code 기준이다.
|
|
41
|
+
|
|
42
|
+
**Codex 의 tmux 밖 실행.** OMX 의 런타임 워크플로(`ralph`, `team` 등)는 OMX tmux 런타임을 요구한다. OMX 의 `AGENTS.md` 는 tmux 밖(Codex App, 일반 `codex`, `codex exec`)이면 그 사실을 알리고 가장 가까운 대체 경로로 계속하라고 정한다(oh-my-codex 0.20.2 `templates/AGENTS.md`). 그래서 tmux 밖이라는 사실만으로는 멈추지 않는다. 그 단계는 이 세션이 그 스킬의 `SKILL.md` 절차를 네이티브 하위 에이전트로 그대로 따르고, 보고에 `<단계>: tmux 밖 대체 실행(OMX 런타임 없음)` 한 줄을 적는다. 종결 낱말은 다른 멈춤 조건과 마지막 ralph-qa 판정으로만 정한다. 대체 실행도 할 수 없으면(하위 에이전트 기능이 꺼짐 등) `STOPPED(omx-runtime-unavailable)` 로 멈추고 tmux 안의 OMX 에서 다시 실행하라고 안내한다.
|
|
43
|
+
|
|
44
|
+
**Codex 의 계획과 상태 경로.** 이 문서의 `.omc/plans/`, `.omc/state/` 는 Claude Code(OMC) 경로다. Codex 에서는 OMX 경로를 쓴다: 계획은 `.omx/plans/`(ralplan 이 쓰는 `prd-*.md`, `test-spec-*.md`), ralph 의 진행 기록은 `.omx/state/<scope>/ralph-progress.json`. Codex 에서 `.omc/` 아래에 계획을 쓰지 않는다.
|
|
41
45
|
|
|
42
46
|
## Purpose
|
|
43
47
|
|
|
@@ -51,18 +55,17 @@ Stage 1 /ralplan --deliberate consensus plan (Planner → Architect → Cri
|
|
|
51
55
|
Stage 2 /ralph --critic=critic PRD-driven persistent build, critic-verified
|
|
52
56
|
│ → implementation + deslop + regression, then ralph self-cancels
|
|
53
57
|
▼
|
|
54
|
-
Stage 3
|
|
55
|
-
→
|
|
58
|
+
Stage 3 ralph-qa --gates=<--qa> 3+ independent reviewers on runner-run gate evidence
|
|
59
|
+
→ ALL-IN-ONE COMPLETE, or honest STOPPED (both runtimes)
|
|
56
60
|
```
|
|
57
61
|
|
|
58
62
|
This skill is a **thin sequential orchestrator**. It does not implement, plan,
|
|
59
|
-
or test directly, and it does **not** create its own state file.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
report honestly.
|
|
63
|
+
or test directly, and it does **not** create its own state file. Each stage
|
|
64
|
+
hands every loop, retry, and verification to the skill it invokes: `ralplan`,
|
|
65
|
+
`ralph`, and banker's `ralph-qa`, whose judge → fix loop runs until its quorum
|
|
66
|
+
says `APPROVE` or its `--max` ends it. Beyond that, its only job is to record the
|
|
67
|
+
pre-change gate baseline, run the stages in order, bridge their handoffs, gate
|
|
68
|
+
each stage on the previous one's success, and report honestly.
|
|
66
69
|
|
|
67
70
|
## Why three stages (and not just ralph)
|
|
68
71
|
|
|
@@ -75,17 +78,20 @@ modes, and each stage's reviewer is independent of the previous stage's author
|
|
|
75
78
|
2. **A partial or unverified build declared "done"** → Stage 2's PRD
|
|
76
79
|
story-by-story persistence + critic verification catch this.
|
|
77
80
|
3. **Integration / regression breakage slipping past the builder's own checks**
|
|
78
|
-
→ Stage 3's
|
|
81
|
+
→ Stage 3's independent quorum over gate evidence the runner, not a model,
|
|
82
|
+
recorded catches this.
|
|
79
83
|
|
|
80
84
|
**On the apparent redundancy of Stage 3:** ralph (Stage 2) already runs its own
|
|
81
85
|
Step-7 reviewer verification and Step-7.6 regression re-run (`omc ralph verify`
|
|
82
86
|
against the baseline it recorded). Stage 3 is still worth running because it is
|
|
83
|
-
*independent* (
|
|
84
|
-
*
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
*independent* (3+ reviewers in contexts that did not build the change),
|
|
88
|
+
*evidence-bound* (each `--qa` goal's real command is run by ralph-qa's
|
|
89
|
+
`gate-evidence.mjs` and kept as an `observed` record; a model's word about a
|
|
90
|
+
command does not count), and *actively fixes* inside ralph-qa's bounded loop.
|
|
91
|
+
If ralph's regression already ran the suite green, the gate usually approves in
|
|
92
|
+
its first iteration (cheap); its value rises when the suite is broad, when
|
|
93
|
+
changes touched many files, or when integration/flaky issues hide behind
|
|
94
|
+
unit-level checks. Keeping it explicit gives a clean, separate PASS signal.
|
|
89
95
|
|
|
90
96
|
## When to use
|
|
91
97
|
|
|
@@ -115,7 +121,8 @@ it explicit gives a clean, separate PASS signal.
|
|
|
115
121
|
| `--short` | Stage 1 runs ralplan **without** `--deliberate` (skips pre-mortem + expanded test plan) for lower-risk work | off → deliberate |
|
|
116
122
|
| `--checkpoint` | Insert an `AskUserQuestion` approval gate between Stage 1 (plan) and Stage 2 (implement) | off → auto-proceed |
|
|
117
123
|
| `--critic=critic\|architect\|codex` | Reviewer passed to ralph's verification | `critic` |
|
|
118
|
-
| `--qa
|
|
124
|
+
| `--qa=<goals>` | The Stage 3 gates, comma-separated: `tests`, `build`, `lint`, `typecheck`, `scenarios` (adversarial scenario rows). Passed to ralph-qa as `--gates` on both runtimes | `tests` |
|
|
125
|
+
| `--codex[=<model>]`, `--gemini[=<model>]`, `--opencode[=<provider/model>]` | Passed through to ralph-qa as external seats. Without them only its backbone of 3+ session-model reviewers sits | none |
|
|
119
126
|
| `--no-deslop` | Passed through to ralph (skip the post-review deslop pass) | off |
|
|
120
127
|
|
|
121
128
|
Everything before the flags / after them that isn't a recognized flag is the
|
|
@@ -147,18 +154,43 @@ then **stops**.
|
|
|
147
154
|
|
|
148
155
|
### Before Stage 2 — record what already fails
|
|
149
156
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
Make the gate folder and run each `--qa` goal's command once on the unchanged
|
|
158
|
+
tree, through ralph-qa's runner, as iteration 0:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
node '<RQ>/gate-evidence.mjs' init --cwd '<repo>' # its "dir" is the gate folder <g>
|
|
162
|
+
node '<RQ>/gate-evidence.mjs' run --dir '<g>' --id tests --cmd '<the tests command>' --timeout 600 --iter 0 --cwd '<repo>'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
One command per gate (no `&&` or `;` chains) and a `--timeout` on each.
|
|
166
|
+
`scenarios` has no baseline: its rows test the change. This **pre-change
|
|
167
|
+
record** (iteration 0 in `<g>/evidence.md`) is the gate's baseline: ralph-qa
|
|
168
|
+
counts a failure with the same command and failure signature as not this
|
|
169
|
+
change's (`baseline`). It covers checks that are not among ralph's feedback
|
|
170
|
+
commands, and on Codex it is the only baseline there is (OMX `ralph` keeps
|
|
171
|
+
none). Never use `git stash` or `git reset` to get a pre-change state for it; if
|
|
172
|
+
the tree already has changes, take the record from a clean copy of HEAD
|
|
173
|
+
(`git worktree add --detach <tmp> HEAD`, run with `--cwd <tmp>`, then
|
|
157
174
|
`git worktree remove <tmp>`). A fresh worktree has no installed dependencies
|
|
158
175
|
(`node_modules`, a venv): link or install them there first, and confirm the
|
|
159
176
|
commands really ran — a record made only of "command not found" errors is no
|
|
160
|
-
baseline. The
|
|
161
|
-
|
|
177
|
+
baseline. The runner writes the folder a command ran in as `<repo>` in the
|
|
178
|
+
failure signature, so a failure in the copy and the same failure in the repo
|
|
179
|
+
match. On Codex the runner writes outside the workspace: ask for approval to
|
|
180
|
+
run it outside the sandbox. The record lives in `<g>`; if the session may
|
|
181
|
+
compact or end before Stage 3, put the `<g>` path in the `ready-compact` note.
|
|
182
|
+
The gate folder lives until Stage 3 has its end word: no cleanup's day rule
|
|
183
|
+
takes it (ralph-qa's gate folder rule).
|
|
184
|
+
|
|
185
|
+
**Not a git repo.** If `init` (or `run`) stops with `not-a-git-tree` (exit 3,
|
|
186
|
+
nothing made or run), first check that the folder the stop names (`checked` in
|
|
187
|
+
its JSON, an absolute path) is the target repo; if not, call it again with
|
|
188
|
+
`--cwd '<repo>'`. Only when the target really is no git repo: the gates cannot
|
|
189
|
+
have evidence (the work tree fingerprint sees no change). Take no baseline, and in Stage 3 hand ralph-qa no `--gates`; it
|
|
190
|
+
then writes `게이트: 선언 없음(git 저장소 아님)` in its report and seat
|
|
191
|
+
instructions. Never run `git init` yourself: tell the user that `git init` and a
|
|
192
|
+
first commit make the gates work next time. The same on both runtimes (Claude
|
|
193
|
+
Code, and Codex on the npm and the plugin route).
|
|
162
194
|
|
|
163
195
|
### Stage 2 — Implement: `/ralph`
|
|
164
196
|
|
|
@@ -208,58 +240,59 @@ criteria → Step-7 reviewer verification → Step-7.5 deslop → Step-7.6 regre
|
|
|
208
240
|
hand; never stash or reset.
|
|
209
241
|
- **Carry the baseline forward.** ralph's own baseline (first iteration) also
|
|
210
242
|
lists failures that existed before the change; ralph treats them as noise
|
|
211
|
-
and reports them at Step 8.
|
|
212
|
-
|
|
243
|
+
and reports them at Step 8. Keep that list for the final report, beside the
|
|
244
|
+
gate baseline in `<g>`.
|
|
213
245
|
- **If ralph reports a fundamental blocker** (same issue across 3+ iterations,
|
|
214
246
|
missing credentials, unclear requirement, external dependency down, or the
|
|
215
247
|
`omc ralph verify` command unavailable): stop and report. Do **not** run
|
|
216
248
|
Stage 3 on a broken or partial build and call it done.
|
|
217
249
|
|
|
218
|
-
### Stage 3 — QA gate
|
|
250
|
+
### Stage 3 — QA gate: banker `ralph-qa` (both runtimes)
|
|
219
251
|
|
|
220
252
|
Precondition: Stage 2's ralph has completed and self-cancelled.
|
|
221
253
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
Report the real outcome:
|
|
259
|
-
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
254
|
+
Invoke ralph-qa (Claude Code `Skill("banker:ralph-qa")`; Codex
|
|
255
|
+
`$banker-ralph-qa`, plugin `$banker:ralph-qa`) with
|
|
256
|
+
`--gates=<the --qa goals> --lens=both`, plus any `--codex`, `--gemini` or
|
|
257
|
+
`--opencode` all-in-one was given. Hand it:
|
|
258
|
+
|
|
259
|
+
- **What to judge:** the change since `HEAD` as Stage 2 began (commits ralph
|
|
260
|
+
made count as part of it), the plan path from Stage 1, and the plan's
|
|
261
|
+
acceptance criteria.
|
|
262
|
+
- **Gate evidence:** the gate folder `<g>` with its iteration-0 baseline (ralph-qa
|
|
263
|
+
uses it, runs no iteration 0 of its own and does not remove it), and
|
|
264
|
+
for each goal the one command and timeout the baseline ran. Add the
|
|
265
|
+
acceptance criterion "each `--qa` goal's real command ran through the runner
|
|
266
|
+
(`gate-evidence.mjs run`) on the tree being judged, as an `observed` record";
|
|
267
|
+
a model's account of a command (`reported`) is not evidence. `<g>` holds the
|
|
268
|
+
gate records only: ralph-qa sends any external-seat payload from a folder of
|
|
269
|
+
its own.
|
|
270
|
+
- **With `scenarios`:** ralph-qa's nine adversarial classes (malformed input,
|
|
271
|
+
repeated interruption, prompt injection, cancel and resume, stale state, dirty
|
|
272
|
+
work tree, hung command, flaky test, misleading success output) each get a
|
|
273
|
+
scenario row run as `scenario-<n>`, or a one-line reason it does not apply.
|
|
274
|
+
- **Baseline rule:** never fix a baseline failure; report it apart. A baseline
|
|
275
|
+
failure whose failing lines point at a file the change touched counts as new
|
|
276
|
+
(as in ralph): the seats raise it as a blocker.
|
|
277
|
+
- **If `<g>` is gone** (the runner stops with `not-a-run-folder`: a logout or
|
|
278
|
+
reboot emptied `$XDG_RUNTIME_DIR`, or it was removed): make a new one with
|
|
279
|
+
`gate-evidence.mjs init` and hand that, with no iteration 0. Never run
|
|
280
|
+
iteration 0 on the changed tree. Failures that were there before then count
|
|
281
|
+
as this change's: put the line `gate baseline: none (<g> was gone)` in the
|
|
282
|
+
report, with Stage 2's ralph baseline list beside it.
|
|
283
|
+
|
|
284
|
+
ralph-qa owns the loop: its seats judge, the author fixes, it runs the gates
|
|
285
|
+
again and the same seats judge again, up to its `--max` (5). all-in-one adds no
|
|
286
|
+
cycle of its own. When it has its end word, run
|
|
287
|
+
`node '<RQ>/gate-evidence.mjs' cleanup --dir '<g>'` (a `<g>` named `ralph-qa.*`,
|
|
288
|
+
made before this version, goes with `node '<RQ>/seat-run.mjs' cleanup --dir '<g>'`).
|
|
289
|
+
|
|
290
|
+
Report the real outcome by ralph-qa's end word (the word before any parenthesis):
|
|
291
|
+
- **`APPROVE`** → "ALL-IN-ONE COMPLETE" with ralph-qa's verdict line, its
|
|
292
|
+
iteration count and its gate block.
|
|
293
|
+
- **`ITERATE`** (its `--max` spent; `원인 gate` when only the gates held it) or
|
|
294
|
+
**`INCONCLUSIVE`** → "STOPPED" with the verdict line, the gate block and the
|
|
295
|
+
blockers left. Do **not** claim success if the gate did not approve.
|
|
263
296
|
|
|
264
297
|
## Orchestrator rules
|
|
265
298
|
|
|
@@ -267,8 +300,8 @@ Report the real outcome:
|
|
|
267
300
|
next begins. No skipping, no reordering, no running two stages' loops at once.
|
|
268
301
|
- Emit one clear progress line at each stage boundary so the user always knows
|
|
269
302
|
where the pipeline is (`[all-in-one] Stage 1/3 — planning…`, etc.).
|
|
270
|
-
- Do not add an all-in-one state file or a second persistence loop. Stages 1–
|
|
271
|
-
own their loops and state;
|
|
303
|
+
- Do not add an all-in-one state file or a second persistence loop. Stages 1–3
|
|
304
|
+
own their loops and state; all-in-one adds none.
|
|
272
305
|
- Treat a sub-skill's internal "stop"/"cancel" as the end of *that stage*, never
|
|
273
306
|
as the end of the pipeline (see the Stage 1 and Stage 2 notes above).
|
|
274
307
|
|
|
@@ -280,8 +313,9 @@ When the pipeline ends (complete or stopped), give a concise honest summary:
|
|
|
280
313
|
(1 line).
|
|
281
314
|
- **Implementation**: stories/stages completed, files changed, the ralph critic
|
|
282
315
|
verdict.
|
|
283
|
-
- **QA**: the
|
|
284
|
-
the baseline failures that predate the
|
|
316
|
+
- **QA**: the `--qa` goals, ralph-qa's verdict line and gate block (APPROVE, or
|
|
317
|
+
STOPPED with its blockers), and the baseline failures that predate the
|
|
318
|
+
change (the `baseline` gates and ralph's Step-8 list), listed apart.
|
|
285
319
|
- **Unmet / scope-limited / deferred**: state plainly — never paper over a gate
|
|
286
320
|
that did not pass.
|
|
287
321
|
|
|
@@ -291,7 +325,8 @@ When the pipeline ends (complete or stopped), give a concise honest summary:
|
|
|
291
325
|
requests don't double-charge; keys stored in payment_requests, 24h TTL"`
|
|
292
326
|
Specific subsystem, concrete behavior, and a storage hint. Stage 1 plans the
|
|
293
327
|
schema + flow with a pre-mortem, Stage 2 implements story-by-story with critic
|
|
294
|
-
sign-off, Stage 3
|
|
328
|
+
sign-off, Stage 3's ralph-qa judges the change on the test suite the runner
|
|
329
|
+
ran. Good fit.
|
|
295
330
|
|
|
296
331
|
**Good** — `"/all-in-one --short --qa=typecheck refactor user_context to drop the
|
|
297
332
|
unused Session import and split the god-object into mixins"`
|
|
@@ -311,10 +346,11 @@ first to expand it into a spec.
|
|
|
311
346
|
- The `omc` CLI check in §0 fails → guide the install/update; do not start.
|
|
312
347
|
- Stage 1 cannot reach consensus → surface best plan, ask the user (don't build).
|
|
313
348
|
- Stage 2 ralph hits a fundamental blocker → stop and report (don't run QA).
|
|
314
|
-
- Stage 3
|
|
315
|
-
|
|
349
|
+
- Stage 3's ralph-qa ends `ITERATE` (its `--max` spent) or `INCONCLUSIVE` →
|
|
350
|
+
report its verdict line and blockers honestly (don't claim success).
|
|
316
351
|
- User says "stop" / "cancel" / "abort" at any point → run
|
|
317
352
|
`/oh-my-claudecode:cancel` and stop.
|
|
353
|
+
- After STOPPED, change no file, not even a one-line fix: report only, until the user gives a new instruction. Nothing in this skill (its description's "one-line fix" pointer included) authorizes an edit after a stop.
|
|
318
354
|
|
|
319
355
|
## Final checklist
|
|
320
356
|
|
|
@@ -323,8 +359,11 @@ first to expand it into a spec.
|
|
|
323
359
|
no-consensus / checkpoint rejection)
|
|
324
360
|
- [ ] Stage 2 received the plan path, completed all PRD stories, passed critic
|
|
325
361
|
verification, and self-cancelled before Stage 3
|
|
362
|
+
- [ ] Before Stage 2: each `--qa` goal but `scenarios` ran once through
|
|
363
|
+
`gate-evidence.mjs run --iter 0` on the unchanged tree
|
|
326
364
|
- [ ] Stages did not overlap (ralph fully ended before the gate began)
|
|
327
|
-
- [ ] Stage 3:
|
|
328
|
-
|
|
365
|
+
- [ ] Stage 3: ralph-qa (`--gates=<the --qa goals>`) ended `APPROVE` on
|
|
366
|
+
`observed` gate records (or STOPPED with its verdict line); baseline
|
|
367
|
+
failures reported apart, not fixed
|
|
329
368
|
- [ ] Final report states plan/implementation/QA outcomes and any unmet items
|
|
330
369
|
plainly
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: omc-patch
|
|
3
|
-
description: "OMC 플러그인이 자동 업데이트된 뒤 사라진 훅 패치를 활성 버전에 다시 적용하고 OMC 마켓플레이스 자동 업데이트를 막음. 옛 킷이 남긴 헬퍼 자리 결함(project-memory 꺼짐)도 찾아 고침. 진단, 적용, 검증, 되돌리기. 'omc-patch'/'OMC 패치'/'OMC 업데이트 뒤 패치'/'훅 timed out'/'훅 프로세스 누적'/'PC 느려짐'/'project-memory 안 됨' 시 사용."
|
|
3
|
+
description: "Claude Code 의 OMC 를 다룸(Codex 에서 실행해도 같음). OMC 플러그인이 자동 업데이트된 뒤 사라진 훅 패치를 활성 버전에 다시 적용하고 OMC 마켓플레이스 자동 업데이트를 막음. 옛 킷이 남긴 헬퍼 자리 결함(project-memory 꺼짐)도 찾아 고침. 진단, 적용, 검증, 되돌리기. 'omc-patch'/'OMC 패치'/'OMC 업데이트 뒤 패치'/'훅 timed out'/'훅 프로세스 누적'/'PC 느려짐'/'project-memory 안 됨' 시 사용."
|
|
4
4
|
argument-hint: "[check | revert]"
|
|
5
5
|
---
|
|
6
6
|
|