@ggui-ai/ui-gen 0.28.0 → 0.29.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/dist/{adapter-h4_V69LI.d.ts → adapter-DLQ-5COm.d.ts} +1 -1
- package/dist/adapters/base.js +2 -27
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/generation-dispatch.d.ts +14 -6
- package/dist/adapters/generation-dispatch.js +40 -19260
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +25 -3561
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/types.js +2 -9
- package/dist/adapters/types.js.map +1 -1
- package/dist/advanced/index.d.ts +13 -12
- package/dist/advanced/index.js +63 -21954
- package/dist/advanced/index.js.map +1 -1
- package/dist/{bank-Ctdp3FUA.d.ts → bank-LWaiAtaA.d.ts} +1 -1
- package/dist/blueprint-validator.js +6 -2301
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.d.ts +3 -2
- package/dist/boilerplate.js +6 -1867
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +3 -2
- package/dist/check/index.js +6 -1923
- package/dist/check/index.js.map +1 -1
- package/dist/chunk-33B3BAWS.js +24 -0
- package/dist/chunk-33B3BAWS.js.map +1 -0
- package/dist/chunk-3HSGA6NI.js +591 -0
- package/dist/chunk-3HSGA6NI.js.map +1 -0
- package/dist/chunk-3NNNGNTO.js +1707 -0
- package/dist/chunk-3NNNGNTO.js.map +1 -0
- package/dist/chunk-3T2HMTON.js +79 -0
- package/dist/chunk-3T2HMTON.js.map +1 -0
- package/dist/chunk-3ZSSDV3L.js +123 -0
- package/dist/chunk-3ZSSDV3L.js.map +1 -0
- package/dist/chunk-4MBR5GA3.js +99 -0
- package/dist/chunk-4MBR5GA3.js.map +1 -0
- package/dist/chunk-56NJFD55.js +337 -0
- package/dist/chunk-56NJFD55.js.map +1 -0
- package/dist/chunk-5AGTY555.js +26 -0
- package/dist/chunk-5AGTY555.js.map +1 -0
- package/dist/chunk-5EJM7EGY.js +115 -0
- package/dist/chunk-5EJM7EGY.js.map +1 -0
- package/dist/chunk-5KXCQLLR.js +529 -0
- package/dist/chunk-5KXCQLLR.js.map +1 -0
- package/dist/chunk-5VBXHVEH.js +171 -0
- package/dist/chunk-5VBXHVEH.js.map +1 -0
- package/dist/chunk-6KDDEING.js +515 -0
- package/dist/chunk-6KDDEING.js.map +1 -0
- package/dist/chunk-6VDRWAP6.js +123 -0
- package/dist/chunk-6VDRWAP6.js.map +1 -0
- package/dist/chunk-732IBFEJ.js +2400 -0
- package/dist/chunk-732IBFEJ.js.map +1 -0
- package/dist/chunk-73AURS3I.js +46 -0
- package/dist/chunk-73AURS3I.js.map +1 -0
- package/dist/chunk-77H5SKLX.js +8 -0
- package/dist/chunk-77H5SKLX.js.map +1 -0
- package/dist/chunk-7QE3AHLE.js +35 -0
- package/dist/chunk-7QE3AHLE.js.map +1 -0
- package/dist/chunk-A375NNWN.js +11 -0
- package/dist/chunk-A375NNWN.js.map +1 -0
- package/dist/chunk-AOU33EFS.js +140 -0
- package/dist/chunk-AOU33EFS.js.map +1 -0
- package/dist/chunk-BA4QYA6E.js +461 -0
- package/dist/chunk-BA4QYA6E.js.map +1 -0
- package/dist/chunk-DBP764GL.js +3 -0
- package/dist/chunk-DBP764GL.js.map +1 -0
- package/dist/chunk-DUU3ZJDQ.js +41 -0
- package/dist/chunk-DUU3ZJDQ.js.map +1 -0
- package/dist/chunk-DXKRBXNU.js +30 -0
- package/dist/chunk-DXKRBXNU.js.map +1 -0
- package/dist/chunk-FB7OEEAH.js +1467 -0
- package/dist/chunk-FB7OEEAH.js.map +1 -0
- package/dist/chunk-FLRNMZV2.js +18 -0
- package/dist/chunk-FLRNMZV2.js.map +1 -0
- package/dist/chunk-FWJIMKFZ.js +2032 -0
- package/dist/chunk-FWJIMKFZ.js.map +1 -0
- package/dist/chunk-FXRHWYIQ.js +163 -0
- package/dist/chunk-FXRHWYIQ.js.map +1 -0
- package/dist/chunk-G3PMV62Z.js +33 -0
- package/dist/chunk-G3PMV62Z.js.map +1 -0
- package/dist/chunk-GAJI7Y3P.js +13 -0
- package/dist/chunk-GAJI7Y3P.js.map +1 -0
- package/dist/chunk-GYINWMPR.js +2052 -0
- package/dist/chunk-GYINWMPR.js.map +1 -0
- package/dist/chunk-HD6ABIK7.js +484 -0
- package/dist/chunk-HD6ABIK7.js.map +1 -0
- package/dist/chunk-HDQVHYO6.js +100 -0
- package/dist/chunk-HDQVHYO6.js.map +1 -0
- package/dist/chunk-IHUT3SIW.js +7 -0
- package/dist/chunk-IHUT3SIW.js.map +1 -0
- package/dist/chunk-JDH5EGNZ.js +126 -0
- package/dist/chunk-JDH5EGNZ.js.map +1 -0
- package/dist/chunk-JMD4RGSV.js +37 -0
- package/dist/chunk-JMD4RGSV.js.map +1 -0
- package/dist/chunk-KJWGZL5B.js +33 -0
- package/dist/chunk-KJWGZL5B.js.map +1 -0
- package/dist/chunk-MKMDQFZ7.js +86 -0
- package/dist/chunk-MKMDQFZ7.js.map +1 -0
- package/dist/chunk-NF6JUZWF.js +85 -0
- package/dist/chunk-NF6JUZWF.js.map +1 -0
- package/dist/chunk-O2YC6XDC.js +1933 -0
- package/dist/chunk-O2YC6XDC.js.map +1 -0
- package/dist/chunk-OVLH5ICV.js +29 -0
- package/dist/chunk-OVLH5ICV.js.map +1 -0
- package/dist/chunk-PBOYHGSD.js +106 -0
- package/dist/chunk-PBOYHGSD.js.map +1 -0
- package/dist/chunk-PJFH7QWA.js +81 -0
- package/dist/chunk-PJFH7QWA.js.map +1 -0
- package/dist/chunk-PUH4CXGZ.js +284 -0
- package/dist/chunk-PUH4CXGZ.js.map +1 -0
- package/dist/chunk-QLXXPGTV.js +18 -0
- package/dist/chunk-QLXXPGTV.js.map +1 -0
- package/dist/chunk-R5GIGPW2.js +2845 -0
- package/dist/chunk-R5GIGPW2.js.map +1 -0
- package/dist/chunk-RH4IUSTO.js +83 -0
- package/dist/chunk-RH4IUSTO.js.map +1 -0
- package/dist/chunk-S2GVXKKY.js +153 -0
- package/dist/chunk-S2GVXKKY.js.map +1 -0
- package/dist/chunk-TVHGKFJS.js +58 -0
- package/dist/chunk-TVHGKFJS.js.map +1 -0
- package/dist/chunk-U7GALWLG.js +66 -0
- package/dist/chunk-U7GALWLG.js.map +1 -0
- package/dist/chunk-VTC263LT.js +256 -0
- package/dist/chunk-VTC263LT.js.map +1 -0
- package/dist/chunk-WEOXFEVE.js +739 -0
- package/dist/chunk-WEOXFEVE.js.map +1 -0
- package/dist/chunk-WYHP46LT.js +28 -0
- package/dist/chunk-WYHP46LT.js.map +1 -0
- package/dist/chunk-XGLO5LGG.js +274 -0
- package/dist/chunk-XGLO5LGG.js.map +1 -0
- package/dist/chunk-XRBCRKA2.js +29 -0
- package/dist/chunk-XRBCRKA2.js.map +1 -0
- package/dist/chunk-XW7ADFFV.js +340 -0
- package/dist/chunk-XW7ADFFV.js.map +1 -0
- package/dist/chunk-YIQ42IUX.js +34 -0
- package/dist/chunk-YIQ42IUX.js.map +1 -0
- package/dist/chunk-YJZTUY7B.js +101 -0
- package/dist/chunk-YJZTUY7B.js.map +1 -0
- package/dist/chunk-Z3CXME3K.js +107 -0
- package/dist/chunk-Z3CXME3K.js.map +1 -0
- package/dist/classifier/index.js +2 -527
- package/dist/classifier/index.js.map +1 -1
- package/dist/client-JBPCXU7W.js +4 -0
- package/dist/client-JBPCXU7W.js.map +1 -0
- package/dist/compose.js +3 -367
- package/dist/compose.js.map +1 -1
- package/dist/cost-tracker-HHGQ4FTW.js +67 -0
- package/dist/cost-tracker-HHGQ4FTW.js.map +1 -0
- package/dist/{create-ui-generator-BrZHF0cf.d.ts → create-ui-generator-BY-WeaPi.d.ts} +3 -3
- package/dist/{design-mode-DGWN_Gkm.d.ts → design-mode-XyOQmzE0.d.ts} +4 -3
- package/dist/{dispatch-B07TI30d.d.ts → dispatch-8LzTddKw.d.ts} +3 -2
- package/dist/dist-UALN6ZVB.js +543 -0
- package/dist/dist-UALN6ZVB.js.map +1 -0
- package/dist/dupe-break-X6K7QFIS.js +4 -0
- package/dist/dupe-break-X6K7QFIS.js.map +1 -0
- package/dist/evaluation/axis-checks/index.d.ts +5 -4
- package/dist/evaluation/axis-checks/index.js +6 -1914
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +3 -2
- package/dist/evaluation/axis-checks/registry.js +3 -1844
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +49 -132
- package/dist/evaluation/index.js +302 -6466
- package/dist/evaluation/index.js.map +1 -1
- package/dist/evaluation/types.d.ts +3 -2
- package/dist/evaluation/types.js +2 -5
- package/dist/evaluation/types.js.map +1 -1
- package/dist/fragments/index.js +2 -338
- package/dist/fragments/index.js.map +1 -1
- package/dist/{generate-tSO_shQ0.d.ts → generate-DQ4ci90s.d.ts} +1 -1
- package/dist/harness/check/runtime-render/index.d.ts +35 -15
- package/dist/harness/check/runtime-render/index.js +6 -2390
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/check/runtime-render/render-check-worker.js +4 -1739
- package/dist/harness/check/runtime-render/render-check-worker.js.map +1 -1
- package/dist/harness/index.d.ts +3 -2
- package/dist/harness/index.js +23 -5126
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/llm-trace-sink.js +2 -24
- package/dist/harness/llm-trace-sink.js.map +1 -1
- package/dist/harness/prompts.d.ts +2 -2
- package/dist/harness/prompts.js +8 -324
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +6 -5
- package/dist/harness/result-types.js +2 -0
- package/dist/harness/result-types.js.map +1 -1
- package/dist/harness/runtime.d.ts +22 -5
- package/dist/harness/runtime.js +10 -2313
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +3 -2
- package/dist/harness/types-public.js +16 -2954
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +3 -2
- package/dist/harness/validator-trace-sink.js +2 -26
- package/dist/harness/validator-trace-sink.js.map +1 -1
- package/dist/hash.js +2 -39
- package/dist/hash.js.map +1 -1
- package/dist/hashline-5OKREIRM.js +4 -0
- package/dist/hashline-5OKREIRM.js.map +1 -0
- package/dist/index.d.ts +50 -11
- package/dist/index.js +57 -22015
- package/dist/index.js.map +1 -1
- package/dist/llm-evaluator-PN3WFCS4.js +653 -0
- package/dist/llm-evaluator-PN3WFCS4.js.map +1 -0
- package/dist/magic-string.es-2NZTC4GZ.js +1307 -0
- package/dist/magic-string.es-2NZTC4GZ.js.map +1 -0
- package/dist/patch.d.ts +3 -2
- package/dist/patch.js +2 -56
- package/dist/patch.js.map +1 -1
- package/dist/policy-VCYKGSAC.js +5 -0
- package/dist/policy-VCYKGSAC.js.map +1 -0
- package/dist/policy.js +2 -35
- package/dist/policy.js.map +1 -1
- package/dist/primitive-index-2OF6F4TZ.js +131 -0
- package/dist/primitive-index-2OF6F4TZ.js.map +1 -0
- package/dist/primitive-slice-WTMBLYFJ.js +235 -0
- package/dist/primitive-slice-WTMBLYFJ.js.map +1 -0
- package/dist/{prompts-BhNUuRoZ.d.ts → prompts-CLZGywMP.d.ts} +1 -1
- package/dist/provider-adapter-contract.js +10407 -14204
- package/dist/provider-adapter-contract.js.map +1 -1
- package/dist/provider-adapter.js +2 -44
- package/dist/provider-adapter.js.map +1 -1
- package/dist/providers/index.d.ts +89 -1
- package/dist/providers/index.js +115 -44
- package/dist/providers/index.js.map +1 -1
- package/dist/raw-C6KBH5I3.js +141 -0
- package/dist/raw-C6KBH5I3.js.map +1 -0
- package/dist/raw-FXSBXQTZ.js +7 -0
- package/dist/raw-FXSBXQTZ.js.map +1 -0
- package/dist/raw-MURDUPGK.js +8 -0
- package/dist/raw-MURDUPGK.js.map +1 -0
- package/dist/raw-T3GW3UVX.js +8 -0
- package/dist/raw-T3GW3UVX.js.map +1 -0
- package/dist/render-check-host-ZNIS6BJ5.js +5 -0
- package/dist/render-check-host-ZNIS6BJ5.js.map +1 -0
- package/dist/sdk-4JNSDNSR.js +6 -0
- package/dist/sdk-4JNSDNSR.js.map +1 -0
- package/dist/sdk-DIVJMHCX.js +7 -0
- package/dist/sdk-DIVJMHCX.js.map +1 -0
- package/dist/sdk-QRJOCRTS.js +7 -0
- package/dist/sdk-QRJOCRTS.js.map +1 -0
- package/dist/tag-balance-CTHCTRJ7.js +123 -0
- package/dist/tag-balance-CTHCTRJ7.js.map +1 -0
- package/dist/tools/get-primitives-ts.d.ts +1 -1
- package/dist/tools/get-primitives-ts.js +3 -1
- package/dist/tools/get-primitives-ts.js.map +1 -1
- package/dist/tools/render-check-worker.js +3 -40
- package/dist/tools/render-check-worker.js.map +1 -1
- package/dist/{types-public-h8IMnYuh.d.ts → types-public-hYlrerZh.d.ts} +35 -2
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +3 -498
- package/dist/validation/index.js.map +1 -1
- package/dist/{visual-evaluator-C2strxqD.d.ts → visual-evaluator-KskajxD5.d.ts} +14 -4
- package/dist/visual-evaluator-TGEXYQTP.js +12 -0
- package/dist/visual-evaluator-TGEXYQTP.js.map +1 -0
- package/dist/workflows.d.ts +3 -2
- package/dist/workflows.js +2 -151
- package/dist/workflows.js.map +1 -1
- package/package.json +20 -16
- package/src/adapters/claude/sdk.ts +4 -2
- package/src/adapters/claude/tool-bridge.ts +2 -1
- package/src/adapters/generation-dispatch.ts +9 -0
- package/src/adapters/openai/raw.ts +4 -0
- package/src/adapters/openai/sdk.ts +6 -1
- package/src/adapters/openai/tokens.ts +21 -7
- package/src/adapters/tool-bridge.ts +1 -1
- package/src/adapters/tools.ts +1 -1
- package/src/advanced/feedback.ts +1 -2
- package/src/advanced/generator.ts +4 -3
- package/src/boilerplate/free-design-prompt.ts +7 -0
- package/src/boilerplate/generate.ts +18 -5
- package/src/boilerplate/hard-sections.ts +8 -3
- package/src/boilerplate/react-hooks.ts +56 -0
- package/src/boilerplate/system-prompt.ts +12 -3
- package/src/check/run-tier0.ts +233 -8
- package/src/check/type-checker.ts +128 -16
- package/src/coding-agent/tools.ts +26 -3
- package/src/design-mode.ts +4 -9
- package/src/evaluation/axis-checks/checks/state-merge.ts +2 -4
- package/src/evaluation/axis-checks/checks/state-payload.ts +1 -28
- package/src/evaluation/axis-checks/checks/tint.ts +197 -0
- package/src/evaluation/axis-checks/helpers.ts +121 -0
- package/src/evaluation/axis-checks/registry.ts +2 -0
- package/src/evaluation/criteria/__fixtures__/edge-v2-draw2.json +4629 -0
- package/src/evaluation/criteria/bank.ts +1 -1
- package/src/evaluation/criteria/edge-instruments.ts +14 -0
- package/src/evaluation/criteria/edge-probe-v2.ts +352 -0
- package/src/evaluation/criteria/edge-v2.ts +242 -0
- package/src/evaluation/criteria/resolve.ts +24 -5
- package/src/evaluation/index.ts +3 -5
- package/src/evaluation/mcp-server.ts +0 -50
- package/src/evaluation/types-public.ts +6 -1
- package/src/evaluation/visual-evaluator.ts +161 -30
- package/src/harness/check/runtime-render/index.ts +28 -4
- package/src/harness/check/runtime-render/render-check.ts +20 -21
- package/src/harness/claude-agent-sdk-loader.ts +93 -0
- package/src/harness/claude-code-login-query.ts +1 -1
- package/src/harness/coding/generate-task-runner.ts +1 -0
- package/src/harness/coding/run-coding-turn.ts +3 -0
- package/src/harness/coding/run-eval-round.ts +9 -0
- package/src/harness/llm-router.ts +50 -2
- package/src/harness/runtime.ts +17 -0
- package/src/index.ts +9 -0
- package/src/providers/anthropic-tool-call.ts +263 -0
- package/src/providers/index.ts +13 -0
- package/src/tools/get-primitives-ts.ts +1 -1
- package/src/tools/render-check.ts +4 -4
- package/src/validation/primitives.ts +2 -1
- package/src/evaluation/loop.ts +0 -218
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
|
|
3
|
+
// src/harness/coding/dupe-break.ts
|
|
4
|
+
function recordToolExchange(state, name, input, resultText) {
|
|
5
|
+
const key = createHash("sha256").update(name).update("\0").update(JSON.stringify(input) ?? "undefined").update("\0").update(resultText).digest("hex");
|
|
6
|
+
if (state.lastExchangeKey === key) {
|
|
7
|
+
state.consecutiveIdenticalExchanges += 1;
|
|
8
|
+
} else {
|
|
9
|
+
state.lastExchangeKey = key;
|
|
10
|
+
state.consecutiveIdenticalExchanges = 1;
|
|
11
|
+
}
|
|
12
|
+
return state.consecutiveIdenticalExchanges;
|
|
13
|
+
}
|
|
14
|
+
var SAME_EXCHANGE_BREAK_AT = 3;
|
|
15
|
+
var SAME_EXCHANGE_NUDGE = "\n\n[harness] This is the SAME tool call with the SAME result as your previous turn \u2014 repeating it cannot produce new information. Use what you already have and emit an apply_changes (or scoped) call now; one more identical repeat terminates the run.";
|
|
16
|
+
function failureSignatures(resultText) {
|
|
17
|
+
const norm = (text) => text.replace(/[0-9]+/g, "#").replace(/\s+/g, " ").trim();
|
|
18
|
+
const violations = [...resultText.matchAll(/^\[[^\]\n]+\] [^\n]+/gm)].map((m) => norm(m[0]));
|
|
19
|
+
if (violations.length > 0) return [...new Set(violations)];
|
|
20
|
+
const rest = norm(resultText.replace(/^Committed [^\n]*\n/, ""));
|
|
21
|
+
return rest.length > 0 ? [rest] : [];
|
|
22
|
+
}
|
|
23
|
+
function recordWriteFailure(state, resultText) {
|
|
24
|
+
let top;
|
|
25
|
+
for (const signature of failureSignatures(resultText)) {
|
|
26
|
+
const repeats = (state.failureCounts.get(signature) ?? 0) + 1;
|
|
27
|
+
state.failureCounts.set(signature, repeats);
|
|
28
|
+
if (top === void 0 || repeats > top.repeats) top = { signature, repeats };
|
|
29
|
+
}
|
|
30
|
+
return top;
|
|
31
|
+
}
|
|
32
|
+
function clearWriteFailures(state) {
|
|
33
|
+
state.failureCounts.clear();
|
|
34
|
+
}
|
|
35
|
+
var SAME_FAILURE_NUDGE_AT = 3;
|
|
36
|
+
var SAME_FAILURE_BREAK_AT = 5;
|
|
37
|
+
var SAME_FAILURE_NUDGE = "\n\n[harness] This same failure has now been reported for three of your patches. Changing other code does not clear it: re-read that check above and change exactly what it names. Two more reports of it end the run.";
|
|
38
|
+
function createDupeBreakState() {
|
|
39
|
+
return {
|
|
40
|
+
lastFailedPatchFingerprint: null,
|
|
41
|
+
forceEscapeNextTurn: false,
|
|
42
|
+
pendingDiagnosticTurn: false,
|
|
43
|
+
cooldown: 0,
|
|
44
|
+
firedCount: 0,
|
|
45
|
+
scopedEscapeUsedCount: 0,
|
|
46
|
+
awaitingDiagnosticOutcome: false,
|
|
47
|
+
diagnosticFiredCount: 0,
|
|
48
|
+
diagnosticReturnedCount: 0,
|
|
49
|
+
diagnosticBrokeLoopCount: 0,
|
|
50
|
+
recentFailedPatches: [],
|
|
51
|
+
consecutiveBrokenApplies: 0,
|
|
52
|
+
consecutiveNoToolCalls: 0,
|
|
53
|
+
lastExchangeKey: null,
|
|
54
|
+
consecutiveIdenticalExchanges: 0,
|
|
55
|
+
failureCounts: /* @__PURE__ */ new Map()
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function errorClassBucket(errText) {
|
|
59
|
+
if (!errText) return "unknown";
|
|
60
|
+
return errText.toLowerCase().replace(/\s+/g, " ").trim().slice(0, 60);
|
|
61
|
+
}
|
|
62
|
+
function computePatchFingerprint(changes, errText) {
|
|
63
|
+
const sorted = [...changes].sort(
|
|
64
|
+
(a, b) => a.startLine - b.startLine || a.endLine - b.endLine
|
|
65
|
+
);
|
|
66
|
+
const normRanges = sorted.map((c) => `${c.startLine}-${c.endLine}`).join("|");
|
|
67
|
+
const normCode = sorted.map((c) => {
|
|
68
|
+
const lines = Array.isArray(c.code) ? c.code : typeof c.code === "string" ? [c.code] : [];
|
|
69
|
+
return lines.map((line) => String(line).trim()).filter((line) => line.length > 0).join("\n");
|
|
70
|
+
}).join("\n---\n");
|
|
71
|
+
const errBucket = errorClassBucket(errText);
|
|
72
|
+
const h = createHash("sha256");
|
|
73
|
+
h.update(normRanges);
|
|
74
|
+
h.update("|");
|
|
75
|
+
h.update(normCode);
|
|
76
|
+
h.update("|");
|
|
77
|
+
h.update(errBucket);
|
|
78
|
+
return h.digest("hex");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { SAME_EXCHANGE_BREAK_AT, SAME_EXCHANGE_NUDGE, SAME_FAILURE_BREAK_AT, SAME_FAILURE_NUDGE, SAME_FAILURE_NUDGE_AT, clearWriteFailures, computePatchFingerprint, createDupeBreakState, errorClassBucket, failureSignatures, recordToolExchange, recordWriteFailure };
|
|
82
|
+
//# sourceMappingURL=chunk-RH4IUSTO.js.map
|
|
83
|
+
//# sourceMappingURL=chunk-RH4IUSTO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/harness/coding/dupe-break.ts"],"names":[],"mappings":"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","file":"chunk-RH4IUSTO.js","sourcesContent":["// Duplicate-patch break.\n//\n// Failure mode this addresses: the LLM re-submits a byte-identical\n// `apply_changes` patch after a PATCH_INVALID response, each time\n// failing with the same esbuild error. The retry prompt looks similar\n// enough that the model's output is effectively a fixed point.\n//\n// Detector: fingerprint each PATCH_INVALID turn by (normalized ranges,\n// normalized code payload, error-class bucket). On match with the prior\n// patch turn's fingerprint, flip `forceEscapeNextTurn` so the next turn\n// is restricted to a narrow escape tool — escaping the loop. A cooldown\n// prevents oscillation if the forced escape also fails.\n//\n// The escape tool that fires is `APPLY_CHANGES_TOOL_SCOPED` (a single\n// change, ≤20 lines) — a narrow blast radius that preserves the rest of\n// the file.\n//\n// All per-session state lives in `DupeBreakState`, attached to the\n// `CodingSession` and mutated in place by `run-coding-turn`. Gated\n// behind `ContextPolicy.breakDuplicatePatch`.\n\nimport { createHash } from \"node:crypto\";\n\n/** Per-session dupe-break state machine. Mutated in place; initialize via\n * {@link createDupeBreakState}. */\n/** Compact summary of one prior failed patch, kept for diagnostic-mode\n * retry-prompt enumeration. Bounded ring (cap 2 most-recent). */\nexport interface RecentFailedPatch {\n /** Sorted-then-joined ranges, e.g. `\"47-47|71-75\"`. Display-only. */\n rangesShort: string;\n /** First 200 chars of normalized code (joined). Display-only. */\n codeHead: string;\n /** Error-class bucket (see {@link errorClassBucket}). Display-only. */\n errClass: string;\n /** Full SHA-256 hex; the diagnostic prompt only shows the first 12 chars\n * but the full hex is used to detect \"next patch fingerprint differs\"\n * for Gate 2 of #43. */\n fingerprint: string;\n}\n\nexport interface DupeBreakState {\n /** Fingerprint of the most recent PATCH_INVALID patch turn. `null` when\n * there's no prior failure or the chain was broken by a success. */\n lastFailedPatchFingerprint: string | null;\n /** Set by detection (`escape` action); consumed by selectTurnTools on\n * the next turn. */\n forceEscapeNextTurn: boolean;\n /** Set by detection (`diagnostic` action); consumed by run-coding-turn\n * prompt assembly on the next turn. */\n pendingDiagnosticTurn: boolean;\n /** Turns remaining in the no-re-entry window after an intervention\n * fires. Decrements on every turn; detection only fires when\n * `cooldown === 0`. */\n cooldown: number;\n /** Number of times the dupe-break mechanism has fired this generation —\n * telemetry / audit. Gate 1 (#42/#43): DUPLICATE_PATCH_BREAK count. */\n firedCount: number;\n /** #42 — count of forced-escape turns that emitted a conforming scoped\n * tool call (1 change, ≤20 lines). Dormant under #43 profile. */\n scopedEscapeUsedCount: number;\n /** #43 — true when the immediately prior turn rendered the diagnostic\n * retry prompt. Read by the post-tool-call block to score outcomes\n * (`diagnosticReturnedCount`, `diagnosticBrokeLoopCount`). Cleared\n * the same turn it's read. */\n awaitingDiagnosticOutcome: boolean;\n /** #43 — count of diagnostic-prompt renders this generation (Gate 1\n * for the diagnostic profile). Should equal firedCount when\n * `dupeBreakAction === \"diagnostic\"`. */\n diagnosticFiredCount: number;\n /** #43 — count of times the LLM's response after a diagnostic prompt\n * included a parseable `DIAG:` commit_message (proxy for \"did the\n * model engage with the structured diagnosis request\"). */\n diagnosticReturnedCount: number;\n /** #43 — count of times the next turn after a diagnostic prompt\n * produced a DIFFERENT fingerprint (or a PASS). Gate 2 lever — if\n * this lags `diagnosticFiredCount`, the lever didn't change\n * reasoning state. */\n diagnosticBrokeLoopCount: number;\n /** Bounded ring of the last 2 failed-patch summaries, used to\n * populate the diagnostic retry prompt. Newest first. */\n recentFailedPatches: RecentFailedPatch[];\n /** Count of consecutive PATCH_APPLIED_BROKEN results (apply-and-warn\n * semantics). Resets on any clean apply. When ≥3, selectTurnTools\n * advertises `REWRITE_TOOL` as the only authoring tool — an escape\n * from a tangled broken workspace. */\n consecutiveBrokenApplies: number;\n /** Count of consecutive turns where the model returned zero tool\n * calls. This can happen when turn 1 produces a broken patch\n * (preflight fail) and turn 2 returns no tool call. A single\n * no-tool-call returns \"continue\" so the outer loop re-prompts\n * (with the prior broken-patch context still in scope). Two\n * consecutive no-tool-calls breaks the loop — the model\n * is genuinely stuck. */\n consecutiveNoToolCalls: number;\n /** ggui#404 — hash of the previous turn's (tool name + input + RESULT)\n * exchange. `null` until the first exchange is recorded. */\n lastExchangeKey: string | null;\n /** ggui#404 — how many CONSECUTIVE turns produced a byte-identical\n * (call, result) exchange. Identical input alone is not proof of a\n * loop (a re-read after a patch legitimately repeats input with a\n * fresh result); an identical call yielding an identical result is\n * information-free — the model learned nothing it didn't already\n * have. 1 = first occurrence; 2 = one repeat (nudge); 3 = break. */\n consecutiveIdenticalExchanges: number;\n /** ggui#1791 — for each failure signature ({@link failureSignatures}), how\n * many failed writes (`apply_changes` / `rewrite`) have reported it since\n * the last write that passed, whatever the patch and whatever failed in\n * between. Cleared when a write passes. */\n failureCounts: Map<string, number>;\n}\n\n/**\n * ggui#404 same-call circuit breaker — record one completed tool\n * exchange and return how many consecutive turns have produced this\n * exact (name, input, result) triple. claude-balanced burned 11 turns\n * calling `get_available_icons` identically; a repeated identical\n * exchange is the constraint-alignment signature of an over-constrained\n * system with no solution path, so the caller nudges at 2 and breaks\n * the loop at {@link SAME_EXCHANGE_BREAK_AT}.\n */\nexport function recordToolExchange(\n state: DupeBreakState,\n name: string,\n input: unknown,\n resultText: string,\n): number {\n const key = createHash(\"sha256\")\n .update(name)\n .update(\"\\u0000\")\n .update(JSON.stringify(input) ?? \"undefined\")\n .update(\"\\u0000\")\n .update(resultText)\n .digest(\"hex\");\n if (state.lastExchangeKey === key) {\n state.consecutiveIdenticalExchanges += 1;\n } else {\n state.lastExchangeKey = key;\n state.consecutiveIdenticalExchanges = 1;\n }\n return state.consecutiveIdenticalExchanges;\n}\n\n/** Third consecutive identical exchange ⇒ the loop can never progress —\n * the caller breaks the run instead of burning the remaining turns. */\nexport const SAME_EXCHANGE_BREAK_AT = 3;\n\n/** Appended to the SECOND identical exchange's tool result — one explicit\n * recovery chance before the break. */\nexport const SAME_EXCHANGE_NUDGE =\n \"\\n\\n[harness] This is the SAME tool call with the SAME result as your \" +\n \"previous turn — repeating it cannot produce new information. Use what \" +\n \"you already have and emit an apply_changes (or scoped) call now; one \" +\n \"more identical repeat terminates the run.\";\n\n/**\n * ggui#1791 — the failures a failed write reported, one signature per failing\n * check, with what changes between two identical failures removed: every\n * digit (line and column numbers, counts) and runs of whitespace.\n *\n * A self-check result lists its violations as `[category] description` lines;\n * each one is its own signature, so a check that fails on every turn reads as\n * the same failure whether or not another check fails beside it. A result with\n * no violation line (a build error, a rejected patch) is one signature: its\n * text without the `Committed <oid>: \"<message>\"` line, which carries a fresh\n * oid and the model's own message every turn.\n *\n * The patch fingerprint above keys on the PATCH, so the same failure under a\n * different patch each turn (a reworded comment, a moved line) never reads as\n * stuck, and a run goes to the turn cap. These key on the FAILURE.\n */\nexport function failureSignatures(resultText: string): string[] {\n const norm = (text: string): string => text.replace(/[0-9]+/g, \"#\").replace(/\\s+/g, \" \").trim();\n const violations = [...resultText.matchAll(/^\\[[^\\]\\n]+\\] [^\\n]+/gm)].map((m) => norm(m[0]));\n if (violations.length > 0) return [...new Set(violations)];\n const rest = norm(resultText.replace(/^Committed [^\\n]*\\n/, \"\"));\n return rest.length > 0 ? [rest] : [];\n}\n\n/** The failure a write has reported most often since the last pass, and how often. */\nexport interface RepeatedFailure {\n readonly signature: string;\n readonly repeats: number;\n}\n\n/**\n * ggui#1791 — record one failed write: count each of its signatures once, and\n * return the one now reported most often since the last passing write\n * (undefined when the result carried no recognisable failure).\n */\nexport function recordWriteFailure(state: DupeBreakState, resultText: string): RepeatedFailure | undefined {\n let top: RepeatedFailure | undefined;\n for (const signature of failureSignatures(resultText)) {\n const repeats = (state.failureCounts.get(signature) ?? 0) + 1;\n state.failureCounts.set(signature, repeats);\n if (top === undefined || repeats > top.repeats) top = { signature, repeats };\n }\n return top;\n}\n\n/** ggui#1791 — a write passed: every count starts over. */\nexport function clearWriteFailures(state: DupeBreakState): void {\n state.failureCounts.clear();\n}\n\n/** A failure reported for the third time since the last pass ⇒ one explicit nudge. */\nexport const SAME_FAILURE_NUDGE_AT = 3;\n\n/** A failure reported for the fifth time since the last pass ⇒ the loop is not\n * converging; the caller ends the run, which ships what the turn cap would\n * have shipped. */\nexport const SAME_FAILURE_BREAK_AT = 5;\n\n/** Appended to the tool result of the {@link SAME_FAILURE_NUDGE_AT}th identical failure. */\nexport const SAME_FAILURE_NUDGE =\n \"\\n\\n[harness] This same failure has now been reported for three of your \" +\n \"patches. Changing other code does not clear it: re-read that check above and \" +\n \"change exactly what it names. Two more reports of it end the run.\";\n\nexport function createDupeBreakState(): DupeBreakState {\n return {\n lastFailedPatchFingerprint: null,\n forceEscapeNextTurn: false,\n pendingDiagnosticTurn: false,\n cooldown: 0,\n firedCount: 0,\n scopedEscapeUsedCount: 0,\n awaitingDiagnosticOutcome: false,\n diagnosticFiredCount: 0,\n diagnosticReturnedCount: 0,\n diagnosticBrokeLoopCount: 0,\n recentFailedPatches: [],\n consecutiveBrokenApplies: 0,\n consecutiveNoToolCalls: 0,\n lastExchangeKey: null,\n consecutiveIdenticalExchanges: 0,\n failureCounts: new Map(),\n };\n}\n\n/** Structure of one change entry in an `apply_changes` tool call.\n *\n * `code` should be `string[]` per the tool schema, but Google Gemini has\n * been observed to emit a single `string` instead. Typed as the union so\n * callers don't have to cast — {@link computePatchFingerprint} normalizes\n * both shapes internally. */\nexport interface PatchChange {\n startLine: number;\n endLine: number;\n code: readonly string[] | string;\n}\n\n/**\n * Bucket an esbuild error message into a coarse class so \"same patch,\n * different error\" registers as distinct. Reads the first diagnostic\n * phrase (up to the first period or colon, lowercased, whitespace\n * collapsed). Stable across trivial line/column variations.\n */\nexport function errorClassBucket(errText: string): string {\n if (!errText) return \"unknown\";\n return errText\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 60);\n}\n\n/**\n * Compute a fingerprint of a failed `apply_changes` attempt.\n *\n * Three components, each normalized before hashing so trivial whitespace\n * shifts in the LLM's output don't dodge detection:\n *\n * 1. Ranges: sorted by startLine, serialized as `\"47-47|71-75|89-89\"`.\n * 2. Code: per-change trim each line, drop empties, join with `\\n`;\n * changes joined with a separator. Captures the LLM's\n * intent without penalizing trailing whitespace.\n * 3. Error: {@link errorClassBucket} of the esbuild message.\n *\n * Full SHA-256 (hex). Short-hash for logging is the first 12 chars.\n */\nexport function computePatchFingerprint(\n changes: readonly PatchChange[],\n errText: string,\n): string {\n // Sort BEFORE extracting ranges + code so a re-ordered changes array\n // with identical content produces an identical fingerprint.\n const sorted = [...changes].sort(\n (a, b) => a.startLine - b.startLine || a.endLine - b.endLine,\n );\n const normRanges = sorted.map((c) => `${c.startLine}-${c.endLine}`).join(\"|\");\n const normCode = sorted\n .map((c) => {\n // Defensive: providers occasionally emit `code` as a single string\n // instead of `string[]` despite the schema (observed: Google Gemini\n // on apply_changes calls). Normalize both shapes here so the\n // fingerprint is provider-agnostic and never crashes.\n const lines = Array.isArray(c.code)\n ? c.code\n : typeof c.code === \"string\"\n ? [c.code]\n : [];\n return lines\n .map((line) => String(line).trim())\n .filter((line) => line.length > 0)\n .join(\"\\n\");\n })\n .join(\"\\n---\\n\");\n const errBucket = errorClassBucket(errText);\n const h = createHash(\"sha256\");\n h.update(normRanges);\n h.update(\"|\");\n h.update(normCode);\n h.update(\"|\");\n h.update(errBucket);\n return h.digest(\"hex\");\n}\n"]}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// src/workflows.ts
|
|
2
|
+
var identityParser = (raw) => raw;
|
|
3
|
+
var SINGLE_PASS = {
|
|
4
|
+
id: "single_pass@1",
|
|
5
|
+
name: "single_pass",
|
|
6
|
+
description: "One LLM-driven impl loop. Used for risk:low + risk:medium contract.",
|
|
7
|
+
phases: [
|
|
8
|
+
{
|
|
9
|
+
id: "impl",
|
|
10
|
+
tasks: [
|
|
11
|
+
{
|
|
12
|
+
id: "generate",
|
|
13
|
+
systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
|
|
14
|
+
contextBuilder: (ctx) => `User prompt: ${ctx.prompt}
|
|
15
|
+
|
|
16
|
+
Boilerplate is pre-written. Fill it in with apply_changes.`,
|
|
17
|
+
outputFormat: "tool-call",
|
|
18
|
+
outputParser: identityParser,
|
|
19
|
+
outputName: "source"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
};
|
|
25
|
+
var STAGED = {
|
|
26
|
+
id: "staged@1",
|
|
27
|
+
name: "staged",
|
|
28
|
+
description: "plan \u2192 execute. One architect task then one coder task.",
|
|
29
|
+
phases: [
|
|
30
|
+
{
|
|
31
|
+
id: "plan",
|
|
32
|
+
tasks: [
|
|
33
|
+
{
|
|
34
|
+
id: "architect",
|
|
35
|
+
systemPrompt: "You are a UI architect. Produce a plan, no code.",
|
|
36
|
+
contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,
|
|
37
|
+
outputFormat: "structured",
|
|
38
|
+
outputParser: identityParser,
|
|
39
|
+
outputName: "plan",
|
|
40
|
+
maxTokens: 800
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "execute",
|
|
46
|
+
tasks: [
|
|
47
|
+
{
|
|
48
|
+
id: "coder",
|
|
49
|
+
systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
|
|
50
|
+
contextBuilder: (ctx) => `User prompt: ${ctx.prompt}
|
|
51
|
+
|
|
52
|
+
Plan:
|
|
53
|
+
${ctx.priorResults.plan ?? "(no plan)"}
|
|
54
|
+
|
|
55
|
+
Implement per plan with apply_changes.`,
|
|
56
|
+
inputs: ["plan"],
|
|
57
|
+
outputFormat: "tool-call",
|
|
58
|
+
outputParser: identityParser,
|
|
59
|
+
outputName: "source"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
var STAGED_CONCURRENT = {
|
|
66
|
+
id: "staged_concurrent@1",
|
|
67
|
+
name: "staged-concurrent",
|
|
68
|
+
description: "plan \u2192 [types \u2225 hooks \u2225 jsx] \u2192 integrate. DAG with parallel skeleton phase.",
|
|
69
|
+
phases: [
|
|
70
|
+
{
|
|
71
|
+
id: "plan",
|
|
72
|
+
tasks: [
|
|
73
|
+
{
|
|
74
|
+
id: "architect",
|
|
75
|
+
systemPrompt: "Plan the UI. No code.",
|
|
76
|
+
contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,
|
|
77
|
+
outputFormat: "structured",
|
|
78
|
+
outputParser: identityParser,
|
|
79
|
+
outputName: "plan",
|
|
80
|
+
maxTokens: 600
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
id: "skeleton",
|
|
86
|
+
tasks: [
|
|
87
|
+
{
|
|
88
|
+
id: "types",
|
|
89
|
+
systemPrompt: "Emit only type declarations for the contract.",
|
|
90
|
+
contextBuilder: (ctx) => `Emit TypeScript types for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
|
|
91
|
+
inputs: ["plan"],
|
|
92
|
+
outputFormat: "structured",
|
|
93
|
+
outputParser: identityParser,
|
|
94
|
+
outputName: "types",
|
|
95
|
+
maxTokens: 400
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: "hooks",
|
|
99
|
+
systemPrompt: "Emit only hook declarations (useState/useEffect/useStream).",
|
|
100
|
+
contextBuilder: (ctx) => `Emit hooks for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
|
|
101
|
+
inputs: ["plan"],
|
|
102
|
+
outputFormat: "structured",
|
|
103
|
+
outputParser: identityParser,
|
|
104
|
+
outputName: "hooks",
|
|
105
|
+
maxTokens: 400
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "jsx",
|
|
109
|
+
systemPrompt: "Emit only the render JSX tree skeleton.",
|
|
110
|
+
contextBuilder: (ctx) => `Emit JSX for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? "(n/a)"}`,
|
|
111
|
+
inputs: ["plan"],
|
|
112
|
+
outputFormat: "structured",
|
|
113
|
+
outputParser: identityParser,
|
|
114
|
+
outputName: "jsx",
|
|
115
|
+
maxTokens: 400
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "integrate",
|
|
121
|
+
tasks: [
|
|
122
|
+
{
|
|
123
|
+
id: "glue",
|
|
124
|
+
systemPrompt: (ctx) => ctx.harness.how.systemPrompt,
|
|
125
|
+
contextBuilder: (ctx) => `Combine into one component. Types:
|
|
126
|
+
${ctx.priorResults.types}
|
|
127
|
+
|
|
128
|
+
Hooks:
|
|
129
|
+
${ctx.priorResults.hooks}
|
|
130
|
+
|
|
131
|
+
JSX:
|
|
132
|
+
${ctx.priorResults.jsx}`,
|
|
133
|
+
inputs: ["types", "hooks", "jsx"],
|
|
134
|
+
outputFormat: "tool-call",
|
|
135
|
+
outputParser: identityParser,
|
|
136
|
+
outputName: "source"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
};
|
|
142
|
+
var WORKFLOWS = {
|
|
143
|
+
single_pass: SINGLE_PASS,
|
|
144
|
+
staged: STAGED,
|
|
145
|
+
staged_concurrent: STAGED_CONCURRENT
|
|
146
|
+
};
|
|
147
|
+
function pickWorkflow(_classification) {
|
|
148
|
+
return WORKFLOWS.single_pass;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { WORKFLOWS, pickWorkflow };
|
|
152
|
+
//# sourceMappingURL=chunk-S2GVXKKY.js.map
|
|
153
|
+
//# sourceMappingURL=chunk-S2GVXKKY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/workflows.ts"],"names":[],"mappings":"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","file":"chunk-S2GVXKKY.js","sourcesContent":["// packages/ui-gen/src/workflows.ts\n//\n// Workflow registry + classification-driven picker. Each workflow\n// describes an execution topology (phases × tasks) for producing source\n// from a contract + prompt; the harness runtime owns actual LLM calls.\n//\n// Workflow shapes are validated shipping defaults — even `staged` /\n// `staged-concurrent` are reserved-but-registered topologies the picker\n// may route to in future risk-tier routing. Classification-driven\n// routing itself is deliberately conservative today (always\n// `single_pass`); changing the picker is a behavior change that should\n// be validated against the generation benchmark suite.\n//\n// Public surface is intentionally minimal: consumers import `WORKFLOWS`\n// (the map) + `pickWorkflow` (the router) + `WorkflowId` (the key\n// type). Individual topology constants (SINGLE_PASS, STAGED,\n// STAGED_CONCURRENT) are internal — access them via\n// `WORKFLOWS.single_pass` etc.\n\nimport type { Classification } from \"./classifier/axes.js\";\nimport type { Workflow } from \"./harness/types-public.js\";\n\n/** Identity parser — used for tasks whose output is already a string. */\nconst identityParser = (raw: unknown): string => raw as string;\n\n/**\n * single_pass — one phase, one task. The current default. The task runs\n * the existing impl/patch/eval-fix loop as a single atomic block.\n */\nconst SINGLE_PASS: Workflow = {\n id: \"single_pass@1\",\n name: \"single_pass\",\n description: \"One LLM-driven impl loop. Used for risk:low + risk:medium contract.\",\n phases: [\n {\n id: \"impl\",\n tasks: [\n {\n id: \"generate\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `User prompt: ${ctx.prompt}\\n\\nBoilerplate is pre-written. Fill it in with apply_changes.`,\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\n/**\n * staged — plan phase then execute phase. For risk:high contract where\n * decomposing planning from authoring reduces light-model cognitive load.\n *\n * Registered but not yet routed by `pickWorkflow` — the executor wires\n * architect/coder TaskRunners through a separate dispatch path in core/.\n */\nconst STAGED: Workflow = {\n id: \"staged@1\",\n name: \"staged\",\n description: \"plan → execute. One architect task then one coder task.\",\n phases: [\n {\n id: \"plan\",\n tasks: [\n {\n id: \"architect\",\n systemPrompt: \"You are a UI architect. Produce a plan, no code.\",\n contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"plan\",\n maxTokens: 800,\n },\n ],\n },\n {\n id: \"execute\",\n tasks: [\n {\n id: \"coder\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `User prompt: ${ctx.prompt}\\n\\nPlan:\\n${ctx.priorResults.plan ?? \"(no plan)\"}\\n\\nImplement per plan with apply_changes.`,\n inputs: [\"plan\"],\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\n/**\n * staged-concurrent — plan, then parallel skeleton tasks, then integrate.\n * Reserved shape for risk:high + multi-axis contract where the LLM\n * benefits from breaking structural concerns apart.\n */\nconst STAGED_CONCURRENT: Workflow = {\n id: \"staged_concurrent@1\",\n name: \"staged-concurrent\",\n description: \"plan → [types ∥ hooks ∥ jsx] → integrate. DAG with parallel skeleton phase.\",\n phases: [\n {\n id: \"plan\",\n tasks: [\n {\n id: \"architect\",\n systemPrompt: \"Plan the UI. No code.\",\n contextBuilder: (ctx) => `Plan the UI for: ${ctx.prompt}`,\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"plan\",\n maxTokens: 600,\n },\n ],\n },\n {\n id: \"skeleton\",\n tasks: [\n {\n id: \"types\",\n systemPrompt: \"Emit only type declarations for the contract.\",\n contextBuilder: (ctx) =>\n `Emit TypeScript types for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"types\",\n maxTokens: 400,\n },\n {\n id: \"hooks\",\n systemPrompt: \"Emit only hook declarations (useState/useEffect/useStream).\",\n contextBuilder: (ctx) =>\n `Emit hooks for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"hooks\",\n maxTokens: 400,\n },\n {\n id: \"jsx\",\n systemPrompt: \"Emit only the render JSX tree skeleton.\",\n contextBuilder: (ctx) =>\n `Emit JSX for: ${ctx.prompt}. Plan: ${ctx.priorResults.plan ?? \"(n/a)\"}`,\n inputs: [\"plan\"],\n outputFormat: \"structured\",\n outputParser: identityParser,\n outputName: \"jsx\",\n maxTokens: 400,\n },\n ],\n },\n {\n id: \"integrate\",\n tasks: [\n {\n id: \"glue\",\n systemPrompt: (ctx) => ctx.harness.how.systemPrompt,\n contextBuilder: (ctx) =>\n `Combine into one component. Types:\\n${ctx.priorResults.types}\\n\\nHooks:\\n${ctx.priorResults.hooks}\\n\\nJSX:\\n${ctx.priorResults.jsx}`,\n inputs: [\"types\", \"hooks\", \"jsx\"],\n outputFormat: \"tool-call\",\n outputParser: identityParser,\n outputName: \"source\",\n },\n ],\n },\n ],\n};\n\nexport const WORKFLOWS = {\n single_pass: SINGLE_PASS,\n staged: STAGED,\n staged_concurrent: STAGED_CONCURRENT,\n} as const;\n\nexport type WorkflowId = keyof typeof WORKFLOWS;\n\n/**\n * Pick a workflow based on classification shape. One dispatch rule —\n * kept small on purpose. Changing this mapping is a first-class\n * experiment.\n *\n * Deliberately conservative — always `single_pass`. Classification-\n * driven routing to `staged` / `staged-concurrent` will follow once\n * the workflow executor can actually run non-single_pass shapes end-\n * to-end on the dispatch path.\n */\nexport function pickWorkflow(_classification: Classification): Workflow {\n return WORKFLOWS.single_pass;\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// src/patch.ts
|
|
2
|
+
function applyLineRanges(sourceBefore, rawChanges) {
|
|
3
|
+
if (rawChanges.length === 0) {
|
|
4
|
+
return { ok: false, error: "No changes provided." };
|
|
5
|
+
}
|
|
6
|
+
const changes = rawChanges.map((c, i) => ({
|
|
7
|
+
startLine: c.startLine,
|
|
8
|
+
endLine: c.endLine,
|
|
9
|
+
code: [...c.code],
|
|
10
|
+
description: c.description ?? `change ${i + 1}`
|
|
11
|
+
})).sort((a, b) => a.startLine - b.startLine);
|
|
12
|
+
for (const c of changes) {
|
|
13
|
+
if (typeof c.startLine !== "number" || typeof c.endLine !== "number") {
|
|
14
|
+
return { ok: false, error: `Change "${c.description}" missing startLine or endLine.` };
|
|
15
|
+
}
|
|
16
|
+
if (c.code.length === 0) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: `Change "${c.description}" has empty code. Use [""] to delete lines.`
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
for (let i = 1; i < changes.length; i++) {
|
|
24
|
+
if (changes[i].startLine <= changes[i - 1].endLine) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
error: `Changes overlap \u2014 "${changes[i - 1].description}" (lines ${changes[i - 1].startLine}-${changes[i - 1].endLine}) overlaps with "${changes[i].description}" (lines ${changes[i].startLine}-${changes[i].endLine}).`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const fileLines = sourceBefore.split("\n");
|
|
32
|
+
for (const c of changes) {
|
|
33
|
+
if (c.startLine < 1 || c.endLine < c.startLine || c.startLine > fileLines.length) {
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: `Invalid line range ${c.startLine}-${c.endLine} for "${c.description}". File has ${fileLines.length} lines.`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const resultLines = [...fileLines];
|
|
41
|
+
for (let i = changes.length - 1; i >= 0; i--) {
|
|
42
|
+
const c = changes[i];
|
|
43
|
+
const deleteCount = c.endLine - c.startLine + 1;
|
|
44
|
+
resultLines.splice(c.startLine - 1, deleteCount, ...c.code);
|
|
45
|
+
}
|
|
46
|
+
return { ok: true, sourceAfter: resultLines.join("\n") };
|
|
47
|
+
}
|
|
48
|
+
var defaultApplyPatch = async ({ sourceBefore, changes }) => {
|
|
49
|
+
const result = applyLineRanges(sourceBefore, changes);
|
|
50
|
+
if (result.ok) {
|
|
51
|
+
return { ok: true, sourceAfter: result.sourceAfter };
|
|
52
|
+
}
|
|
53
|
+
return { ok: false, error: result.error };
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { applyLineRanges, defaultApplyPatch };
|
|
57
|
+
//# sourceMappingURL=chunk-TVHGKFJS.js.map
|
|
58
|
+
//# sourceMappingURL=chunk-TVHGKFJS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/patch.ts"],"names":[],"mappings":"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","file":"chunk-TVHGKFJS.js","sourcesContent":["// packages/ui-gen/src/patch.ts\n//\n// Pure line-range patch implementation. Mirrors the `apply_changes` tool\n// logic (from coding-agent/tools.ts) without workspace / git / preflight\n// coupling — the harness exposes this as the default `PatchFn` so\n// variants can override with alternative patch grammars (diff3,\n// atomic-write, inline-markup, etc.) while reusing the orchestration\n// around them.\n//\n// Invariants:\n// - Changes sorted ascending by startLine.\n// - No overlapping ranges.\n// - All line numbers within [1, fileLines].\n// - Applied in reverse order to preserve upstream line numbers.\n//\n// This is the default patch function — every production harness uses it\n// unless a variant overrides `what.applyPatch`.\n\nimport type { PatchFn } from \"./harness/types-public.js\";\n\n/** Core pure logic — exported separately for tests + alternative wrappers. */\nexport function applyLineRanges(\n sourceBefore: string,\n rawChanges: ReadonlyArray<{\n startLine: number;\n endLine: number;\n code: readonly string[];\n description?: string;\n }>,\n): { ok: true; sourceAfter: string } | { ok: false; error: string } {\n if (rawChanges.length === 0) {\n return { ok: false, error: \"No changes provided.\" };\n }\n\n // Normalize — stable copy, sort ascending by startLine\n const changes = rawChanges\n .map((c, i) => ({\n startLine: c.startLine,\n endLine: c.endLine,\n code: [...c.code],\n description: c.description ?? `change ${i + 1}`,\n }))\n .sort((a, b) => a.startLine - b.startLine);\n\n // Required fields + non-empty code\n for (const c of changes) {\n if (typeof c.startLine !== \"number\" || typeof c.endLine !== \"number\") {\n return { ok: false, error: `Change \"${c.description}\" missing startLine or endLine.` };\n }\n if (c.code.length === 0) {\n return {\n ok: false,\n error: `Change \"${c.description}\" has empty code. Use [\"\"] to delete lines.`,\n };\n }\n }\n\n // Overlaps\n for (let i = 1; i < changes.length; i++) {\n if (changes[i].startLine <= changes[i - 1].endLine) {\n return {\n ok: false,\n error:\n `Changes overlap — \"${changes[i - 1].description}\" (lines ` +\n `${changes[i - 1].startLine}-${changes[i - 1].endLine}) overlaps with ` +\n `\"${changes[i].description}\" (lines ${changes[i].startLine}-${changes[i].endLine}).`,\n };\n }\n }\n\n // Line-number bounds\n const fileLines = sourceBefore.split(\"\\n\");\n for (const c of changes) {\n if (c.startLine < 1 || c.endLine < c.startLine || c.startLine > fileLines.length) {\n return {\n ok: false,\n error:\n `Invalid line range ${c.startLine}-${c.endLine} for \"${c.description}\". ` +\n `File has ${fileLines.length} lines.`,\n };\n }\n }\n\n // Apply in reverse to preserve line numbers\n const resultLines = [...fileLines];\n for (let i = changes.length - 1; i >= 0; i--) {\n const c = changes[i];\n const deleteCount = c.endLine - c.startLine + 1;\n resultLines.splice(c.startLine - 1, deleteCount, ...c.code);\n }\n\n return { ok: true, sourceAfter: resultLines.join(\"\\n\") };\n}\n\n/**\n * Harness-compatible wrapper around `applyLineRanges`. The default\n * patch function attached to every new harness's `what.applyPatch`.\n * Variants can override with alternative implementations (e.g., diff3\n * merge, atomic file write, etc.) to test different patch grammars\n * end-to-end.\n */\nexport const defaultApplyPatch: PatchFn = async ({ sourceBefore, changes }) => {\n const result = applyLineRanges(sourceBefore, changes);\n if (result.ok) {\n return { ok: true, sourceAfter: result.sourceAfter };\n }\n return { ok: false, error: result.error };\n};\n"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { REGISTRY, axisCheckTraceEnabled } from './chunk-GYINWMPR.js';
|
|
2
|
+
import { matches } from './chunk-PUH4CXGZ.js';
|
|
3
|
+
import { createHash } from 'crypto';
|
|
4
|
+
|
|
5
|
+
function runAxisChecks(classification, input) {
|
|
6
|
+
const facts = {
|
|
7
|
+
sourceCode: input.sourceCode,
|
|
8
|
+
...input.contract !== void 0 ? { contract: input.contract } : {},
|
|
9
|
+
originalPrompt: input.originalPrompt,
|
|
10
|
+
classification,
|
|
11
|
+
...input.designMode !== void 0 ? { designMode: input.designMode } : {},
|
|
12
|
+
...input.canvas !== void 0 ? { canvas: input.canvas } : {},
|
|
13
|
+
...input.fixtureProps !== void 0 ? { fixtureProps: input.fixtureProps } : {}
|
|
14
|
+
};
|
|
15
|
+
if (input.compiledCode === null) {
|
|
16
|
+
traceAxisChecksSkipped(facts, "compiledCode null \u2014 no check ran");
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const axisInput = { ...facts, compiledCode: input.compiledCode };
|
|
20
|
+
return runGatedAxisChecks(
|
|
21
|
+
REGISTRY.filter((check) => matches(classification.vector, check)),
|
|
22
|
+
axisInput
|
|
23
|
+
).issues;
|
|
24
|
+
}
|
|
25
|
+
function runGatedAxisChecks(checks, input) {
|
|
26
|
+
const issues = [];
|
|
27
|
+
const firedIds = [];
|
|
28
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const check of checks) {
|
|
30
|
+
if (seen.has(check.id)) continue;
|
|
31
|
+
seen.add(check.id);
|
|
32
|
+
firedIds.push(check.id);
|
|
33
|
+
issues.push(...check.run(input));
|
|
34
|
+
}
|
|
35
|
+
if (axisCheckTraceEnabled()) {
|
|
36
|
+
const line = {
|
|
37
|
+
...traceFacts(input),
|
|
38
|
+
matched: [...firedIds],
|
|
39
|
+
issues: issues.map((i) => ({ id: i.subcategory ?? i.category, result: i.result }))
|
|
40
|
+
};
|
|
41
|
+
console.log(JSON.stringify({ axisCheckTrace: line }));
|
|
42
|
+
}
|
|
43
|
+
return { issues, firedIds };
|
|
44
|
+
}
|
|
45
|
+
function traceAxisChecksSkipped(facts, note) {
|
|
46
|
+
if (!axisCheckTraceEnabled()) return;
|
|
47
|
+
const line = { ...traceFacts(facts), matched: [], issues: [], note };
|
|
48
|
+
console.log(JSON.stringify({ axisCheckTrace: line }));
|
|
49
|
+
}
|
|
50
|
+
function traceFacts(input) {
|
|
51
|
+
const propsSpec = input.contract?.propsSpec;
|
|
52
|
+
return {
|
|
53
|
+
sourceSha256: createHash("sha256").update(input.sourceCode, "utf8").digest("hex"),
|
|
54
|
+
originalPrompt: input.originalPrompt,
|
|
55
|
+
designMode: input.designMode ?? "constrained",
|
|
56
|
+
classification: input.classification.vector,
|
|
57
|
+
propsSpecKeys: Object.keys(propsSpec ?? {}),
|
|
58
|
+
propsSpecPropertyKeys: Object.keys(propsSpec?.properties ?? {}),
|
|
59
|
+
// No default here, unlike designMode: an absent canvas is a fact about the caller, not a guess to paper over.
|
|
60
|
+
...input.canvas !== void 0 ? { canvas: input.canvas } : {}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { runAxisChecks, runGatedAxisChecks, traceAxisChecksSkipped };
|
|
65
|
+
//# sourceMappingURL=chunk-U7GALWLG.js.map
|
|
66
|
+
//# sourceMappingURL=chunk-U7GALWLG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/evaluation/axis-checks/dispatch.ts"],"names":[],"mappings":"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","file":"chunk-U7GALWLG.js","sourcesContent":["// Axis-keyed dispatcher. Iterates the flat REGISTRY, runs each check\n// whose gate matches the classification's axis vector, and accumulates\n// issues.\n\nimport type { DataContract, JsonObject } from \"@ggui-ai/protocol\";\nimport type { Classification } from \"../../classifier/index.js\";\nimport type { EvalIssue } from \"../types-public.js\";\nimport { REGISTRY } from \"./registry.js\";\nimport { matches, type AxisCheck, type AxisCheckInput } from \"./types.js\";\nimport { axisCheckTraceEnabled } from \"./helpers.js\";\nimport { createHash } from \"node:crypto\";\nimport type { CanvasClass, DesignMode } from \"../../design-mode.js\";\n\nexport interface RunAxisChecksInput {\n sourceCode: string;\n compiledCode: string | null;\n contract?: DataContract;\n originalPrompt: string;\n /** Which triad produced the source — see `AxisCheckInput.designMode`. */\n designMode?: DesignMode;\n /** The canvas the source is judged for — see `AxisCheckInput.canvas` (ggui#1117); absent = no rendering context. */\n canvas?: CanvasClass;\n /** The props the source was rendered with — see `AxisCheckInput.fixtureProps` (ggui#1285); absent = the echo check stands down. */\n fixtureProps?: JsonObject;\n}\n\nexport function runAxisChecks(\n classification: Classification,\n input: RunAxisChecksInput,\n): EvalIssue[] {\n const facts: AxisTraceFacts = {\n sourceCode: input.sourceCode,\n ...(input.contract !== undefined ? { contract: input.contract } : {}),\n originalPrompt: input.originalPrompt,\n classification,\n ...(input.designMode !== undefined ? { designMode: input.designMode } : {}),\n ...(input.canvas !== undefined ? { canvas: input.canvas } : {}),\n ...(input.fixtureProps !== undefined ? { fixtureProps: input.fixtureProps } : {}),\n };\n if (input.compiledCode === null) {\n traceAxisChecksSkipped(facts, \"compiledCode null — no check ran\");\n return [];\n }\n const axisInput: AxisCheckInput = { ...facts, compiledCode: input.compiledCode };\n return runGatedAxisChecks(\n REGISTRY.filter((check) => matches(classification.vector, check)),\n axisInput,\n ).issues;\n}\n\nexport interface AxisRunResult {\n readonly issues: EvalIssue[];\n /** Check ids run, in registry order, each once. */\n readonly firedIds: string[];\n}\n\n/**\n * Run a PRE-GATED list of checks once each — the one runner the served\n * loop (`run-check.ts`, over the harness's pre-filtered `axisChecks`) and\n * `runAxisChecks` (gate + run) share, so the ggui#1046 trace line prints on\n * both paths.\n */\nexport function runGatedAxisChecks(checks: readonly AxisCheck[], input: AxisCheckInput): AxisRunResult {\n const issues: EvalIssue[] = [];\n const firedIds: string[] = [];\n const seen = new Set<string>();\n for (const check of checks) {\n if (seen.has(check.id)) continue;\n seen.add(check.id);\n firedIds.push(check.id);\n issues.push(...check.run(input));\n }\n if (axisCheckTraceEnabled()) {\n const line: AxisCheckTrace = {\n ...traceFacts(input),\n matched: [...firedIds],\n issues: issues.map((i) => ({ id: i.subcategory ?? i.category, result: i.result })),\n };\n console.log(JSON.stringify({ axisCheckTrace: line }));\n }\n return { issues, firedIds };\n}\n\n/** The dispatcher's line for a round where no check could run (a null compile), flag-gated like the rest. */\nexport function traceAxisChecksSkipped(facts: AxisTraceFacts, note: string): void {\n if (!axisCheckTraceEnabled()) return;\n const line: AxisCheckTrace = { ...traceFacts(facts), matched: [], issues: [], note };\n console.log(JSON.stringify({ axisCheckTrace: line }));\n}\n\n/** The input facts a round's verdict is built from — `AxisCheckInput` minus the compile. */\nexport type AxisTraceFacts = Omit<AxisCheckInput, \"compiledCode\">;\n\n/** One trace line per round (ggui#1046): the input facts a verdict was built from, the gates that matched, the issues that came out. */\nexport interface AxisCheckTrace {\n readonly sourceSha256: string;\n readonly originalPrompt: string;\n readonly designMode: string;\n readonly classification: Classification[\"vector\"];\n readonly propsSpecKeys: readonly string[];\n readonly propsSpecPropertyKeys: readonly string[];\n /** The canvas the verdict was built for (ggui#1117) — present only when the input carried one. */\n readonly canvas?: CanvasClass;\n readonly matched: readonly string[];\n readonly issues: ReadonlyArray<{ readonly id: string; readonly result: EvalIssue[\"result\"] }>;\n readonly note?: string;\n}\n\nfunction traceFacts(input: AxisTraceFacts): Omit<AxisCheckTrace, \"matched\" | \"issues\"> {\n const propsSpec = input.contract?.propsSpec;\n return {\n sourceSha256: createHash(\"sha256\").update(input.sourceCode, \"utf8\").digest(\"hex\"),\n originalPrompt: input.originalPrompt,\n designMode: input.designMode ?? \"constrained\",\n classification: input.classification.vector,\n propsSpecKeys: Object.keys(propsSpec ?? {}),\n propsSpecPropertyKeys: Object.keys(propsSpec?.properties ?? {}),\n // No default here, unlike designMode: an absent canvas is a fact about the caller, not a guess to paper over.\n ...(input.canvas !== undefined ? { canvas: input.canvas } : {}),\n };\n}\n"]}
|