ccqa 1.37.0 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/ccqa.mjs +50 -13
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/bin/ccqa.mjs
CHANGED
|
@@ -3726,9 +3726,19 @@ function scrubOutcome(outcome, scrubMap) {
|
|
|
3726
3726
|
}
|
|
3727
3727
|
};
|
|
3728
3728
|
}
|
|
3729
|
+
/**
|
|
3730
|
+
* Pause before the single retry of an errored classification call. Long enough
|
|
3731
|
+
* to ride out a transient network/model hiccup, short enough not to stall the
|
|
3732
|
+
* report when the error is persistent.
|
|
3733
|
+
*/
|
|
3734
|
+
const RETRY_DELAY_MS = 2e3;
|
|
3735
|
+
function sleep(ms) {
|
|
3736
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3737
|
+
}
|
|
3729
3738
|
async function classifyFailure(input, options) {
|
|
3730
|
-
const
|
|
3731
|
-
|
|
3739
|
+
const prompt = buildFailureAnalysisPrompt(input);
|
|
3740
|
+
const invoke = () => invokeClaudeStreaming({
|
|
3741
|
+
prompt,
|
|
3732
3742
|
allowedTools: [
|
|
3733
3743
|
"Read",
|
|
3734
3744
|
"Grep",
|
|
@@ -3741,11 +3751,22 @@ async function classifyFailure(input, options) {
|
|
|
3741
3751
|
...options.model ? { model: options.model } : {},
|
|
3742
3752
|
...options.cwd ? { cwd: options.cwd } : {}
|
|
3743
3753
|
}, () => {});
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3754
|
+
let { result: raw, isError } = await invoke();
|
|
3755
|
+
let retried = false;
|
|
3756
|
+
if (isError) {
|
|
3757
|
+
warn("failure analysis: Claude invocation errored — retrying once");
|
|
3758
|
+
await sleep(RETRY_DELAY_MS);
|
|
3759
|
+
({result: raw, isError} = await invoke());
|
|
3760
|
+
retried = true;
|
|
3761
|
+
}
|
|
3762
|
+
if (isError || !raw) {
|
|
3763
|
+
const cause = isError ? "Claude returned an error result" : "Claude returned no output";
|
|
3764
|
+
return {
|
|
3765
|
+
analysis: unknownAnalysis(retried ? `${cause} (after 1 retry)` : cause),
|
|
3766
|
+
raw: raw ?? "",
|
|
3767
|
+
sdkError: isError
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3749
3770
|
let sawParseableJson = false;
|
|
3750
3771
|
for (const candidate of extractJsonCandidates(raw)) {
|
|
3751
3772
|
let parsed;
|
|
@@ -8147,8 +8168,9 @@ const C$1 = {
|
|
|
8147
8168
|
* diff — so report rows and CI logs look the same whichever target a
|
|
8148
8169
|
* project's specs use.
|
|
8149
8170
|
*
|
|
8150
|
-
* One Claude call per failing spec
|
|
8151
|
-
*
|
|
8171
|
+
* One Claude call per failing spec (two when the first errors and is retried
|
|
8172
|
+
* once), which reads the source itself rather than deferring to a drift audit
|
|
8173
|
+
* run beforehand. It is still one *phase*:
|
|
8152
8174
|
* `beginFailureAnalysis` hands back the state every path shares, so a mixed
|
|
8153
8175
|
* run prints one `failure analysis` banner in one place rather than one per
|
|
8154
8176
|
* execution path. It runs after every spec has executed, so no Claude turn is
|
|
@@ -9065,8 +9087,10 @@ z.object({ error: z.object({
|
|
|
9065
9087
|
* One spec's record of a single run, as stored in a ledger bucket. Identical
|
|
9066
9088
|
* to `LastGreenEntry` plus the commit the environment was running at the time
|
|
9067
9089
|
* — without it a bucket entry can be ordered in wall-clock time but not
|
|
9068
|
-
* *positioned* against the deploy log, which is the only ordering
|
|
9069
|
-
*
|
|
9090
|
+
* *positioned* against the deploy log, which is the only ordering the
|
|
9091
|
+
* staleness verdict may use (ADR-0010). Wall-clock order is fit only for
|
|
9092
|
+
* scheduling within an already-decided set, where a mis-ranking delays a
|
|
9093
|
+
* spec rather than excusing it.
|
|
9070
9094
|
*/
|
|
9071
9095
|
const SpecLedgerEntrySchema = z.object({
|
|
9072
9096
|
gitHead: z.string(),
|
|
@@ -9651,7 +9675,10 @@ function selectSpecsNeedingRerun(specs, report) {
|
|
|
9651
9675
|
const entry = report.specs[specKey(spec)];
|
|
9652
9676
|
const verdict = entry?.verdict ?? "inProgress";
|
|
9653
9677
|
counts.set(verdict, (counts.get(verdict) ?? 0) + 1);
|
|
9654
|
-
if (verdict === "rerunNeeded") selected.push(
|
|
9678
|
+
if (verdict === "rerunNeeded") selected.push({
|
|
9679
|
+
spec,
|
|
9680
|
+
lastRunAt: entry?.lastRun?.at ?? ""
|
|
9681
|
+
});
|
|
9655
9682
|
else if (verdict === "inProgress") {
|
|
9656
9683
|
excludedInProgress++;
|
|
9657
9684
|
if (!entry) excludedUnknownToHub++;
|
|
@@ -9661,8 +9688,9 @@ function selectSpecsNeedingRerun(specs, report) {
|
|
|
9661
9688
|
}
|
|
9662
9689
|
}
|
|
9663
9690
|
}
|
|
9691
|
+
selected.sort((a, b) => a.lastRunAt.localeCompare(b.lastRunAt));
|
|
9664
9692
|
return {
|
|
9665
|
-
selected,
|
|
9693
|
+
selected: selected.map((s) => s.spec),
|
|
9666
9694
|
summary: formatCounts(SUMMARY_ORDER$1, counts),
|
|
9667
9695
|
excludedInProgress,
|
|
9668
9696
|
excludedUnknownToHub,
|
|
@@ -11583,6 +11611,15 @@ ${stepsText}
|
|
|
11583
11611
|
- Do not invent success when blocked: fail honestly with a short reason.
|
|
11584
11612
|
- **Evidence discipline**: when the assertion target is a specific row / message / banner / URL, scroll it into view (or focus the relevant pane) before letting the step end. The "after" screenshot is captured for you automatically — your job is to make sure that screenshot shows the thing your STEP_RESULT line is talking about.
|
|
11585
11613
|
|
|
11614
|
+
### Waiting for asynchronous responses
|
|
11615
|
+
|
|
11616
|
+
Some expected outcomes arrive asynchronously — an automated reply, a background job finishing, a list refreshing. Waiting for them is fine, but the wait has a budget:
|
|
11617
|
+
|
|
11618
|
+
- Prefer bounded probes (\`agent-browser wait --text "..."\`, or a short pause followed by a fresh \`snapshot\`) over long blind sleeps, and keep a rough running total of how long you have waited within this step.
|
|
11619
|
+
- **The total wait within one step must not exceed 3 minutes**, unless the step's own instruction explicitly names a longer wait. Do not keep adding "one more" sleep past the budget.
|
|
11620
|
+
- When the budget is spent and the expected outcome has still not appeared, STOP waiting and emit \`STEP_RESULT|<stepId>|fail|...\`. **Never end your turn without a STEP_RESULT because you were still waiting** — a silent timeout is recorded as a protocol failure and hides the real cause from failure analysis.
|
|
11621
|
+
- The fail reason must state what you waited for, roughly how long in total, and what you observed instead (e.g. "waited ~3 min for a reply to appear after submitting; none appeared, the view still shows only the submitted item").
|
|
11622
|
+
|
|
11586
11623
|
### Output contract (STRICT)
|
|
11587
11624
|
|
|
11588
11625
|
Your final assistant message MUST contain exactly one line of the form:
|
package/dist/package.json
CHANGED