mustard-claude 3.1.28 → 3.1.29
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/package.json
CHANGED
|
@@ -1814,21 +1814,19 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1814
1814
|
}];
|
|
1815
1815
|
|
|
1816
1816
|
const patterns = extractPatternsFromStates(states);
|
|
1817
|
-
// retries > 2 triggers the high-retry entry
|
|
1818
|
-
const retryEntry = patterns.find(p => p.name === "high-retry-login-feature");
|
|
1819
|
-
assert.ok(retryEntry, "Expected high-retry entry");
|
|
1817
|
+
// retries > 2 triggers the high-hook-retry entry
|
|
1818
|
+
const retryEntry = patterns.find(p => p.name === "high-hook-retry-login-feature");
|
|
1819
|
+
assert.ok(retryEntry, "Expected high-hook-retry entry");
|
|
1820
1820
|
assert.ok(retryEntry.prescription, "Expected prescription field");
|
|
1821
1821
|
assert.ok(
|
|
1822
1822
|
/delegate investigation via Task\(general-purpose\)/.test(retryEntry.prescription),
|
|
1823
1823
|
"Prescription should instruct delegation via Task(general-purpose)"
|
|
1824
1824
|
);
|
|
1825
1825
|
assert.ok(retryEntry.tags.includes("prescriptive"), "Tags should include 'prescriptive'");
|
|
1826
|
-
|
|
1827
|
-
assert.ok(retryEntry.tags.includes("retry"));
|
|
1826
|
+
assert.ok(retryEntry.tags.includes("hook-retry"));
|
|
1828
1827
|
assert.ok(retryEntry.tags.includes("pipeline"));
|
|
1829
1828
|
assert.ok(retryEntry.tags.includes("lesson"));
|
|
1830
|
-
|
|
1831
|
-
assert.ok(retryEntry.description.includes("4 retries"));
|
|
1829
|
+
assert.ok(retryEntry.description.includes("4 hook-level retries"));
|
|
1832
1830
|
});
|
|
1833
1831
|
|
|
1834
1832
|
it("should emit fragmentation prescription when apiCalls > 50 AND retries > 3", () => {
|
|
@@ -1843,7 +1841,7 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1843
1841
|
}];
|
|
1844
1842
|
|
|
1845
1843
|
const patterns = extractPatternsFromStates(states);
|
|
1846
|
-
// apiCalls > 50 triggers heavy-pipeline; retries > 2 also triggers high-retry.
|
|
1844
|
+
// apiCalls > 50 triggers heavy-pipeline; retries > 2 also triggers high-hook-retry.
|
|
1847
1845
|
const heavyEntry = patterns.find(p => p.name === "heavy-pipeline-big-refactor");
|
|
1848
1846
|
assert.ok(heavyEntry, "Expected heavy-pipeline entry");
|
|
1849
1847
|
assert.ok(heavyEntry.prescription, "Expected prescription field");
|
|
@@ -1858,7 +1856,7 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1858
1856
|
});
|
|
1859
1857
|
|
|
1860
1858
|
it("should emit reactive-iteration prescription when Edit > 15 and Write < 3", () => {
|
|
1861
|
-
// Edit=20 > 15, Write=1 < 3, retries=3 to trigger the high-retry entry
|
|
1859
|
+
// Edit=20 > 15, Write=1 < 3, retries=3 to trigger the high-hook-retry entry
|
|
1862
1860
|
// (needs retries > 2 OR apiCalls > 50 to produce any entry at all).
|
|
1863
1861
|
// Pick retries=3 and small Bash/Agent to avoid L0-violation heuristic dominance
|
|
1864
1862
|
// but note: the heuristic checks order — L0 fires first if bash+edit>3*agent AND retries>2.
|
|
@@ -1873,8 +1871,8 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1873
1871
|
}];
|
|
1874
1872
|
|
|
1875
1873
|
const patterns = extractPatternsFromStates(states);
|
|
1876
|
-
const retryEntry = patterns.find(p => p.name === "high-retry-tweak-hell");
|
|
1877
|
-
assert.ok(retryEntry, "Expected high-retry entry");
|
|
1874
|
+
const retryEntry = patterns.find(p => p.name === "high-hook-retry-tweak-hell");
|
|
1875
|
+
assert.ok(retryEntry, "Expected high-hook-retry entry");
|
|
1878
1876
|
assert.ok(retryEntry.prescription, "Expected prescription field");
|
|
1879
1877
|
assert.ok(
|
|
1880
1878
|
/investigate with Read\+Grep BEFORE editing/.test(retryEntry.prescription),
|
|
@@ -1884,7 +1882,7 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1884
1882
|
});
|
|
1885
1883
|
|
|
1886
1884
|
it("should NOT add prescription or prescriptive tag when no heuristic matches", () => {
|
|
1887
|
-
// retries=3 to trigger high-retry entry, but balanced tools so none of the
|
|
1885
|
+
// retries=3 to trigger high-hook-retry entry, but balanced tools so none of the
|
|
1888
1886
|
// heuristics fire (edit<=15, apiCalls<=50, bash+edit not >3*agent).
|
|
1889
1887
|
const states = [{
|
|
1890
1888
|
specName: "mild-case",
|
|
@@ -1896,13 +1894,12 @@ describe("knowledge-extract prescriptions", () => {
|
|
|
1896
1894
|
}];
|
|
1897
1895
|
|
|
1898
1896
|
const patterns = extractPatternsFromStates(states);
|
|
1899
|
-
const retryEntry = patterns.find(p => p.name === "high-retry-mild-case");
|
|
1900
|
-
assert.ok(retryEntry, "Expected high-retry entry");
|
|
1897
|
+
const retryEntry = patterns.find(p => p.name === "high-hook-retry-mild-case");
|
|
1898
|
+
assert.ok(retryEntry, "Expected high-hook-retry entry");
|
|
1901
1899
|
assert.equal(retryEntry.prescription, undefined, "No prescription when no heuristic matches");
|
|
1902
1900
|
assert.ok(!retryEntry.tags.includes("prescriptive"),
|
|
1903
1901
|
"'prescriptive' tag must NOT be added when no prescription");
|
|
1904
|
-
|
|
1905
|
-
assert.ok(retryEntry.tags.includes("retry"));
|
|
1902
|
+
assert.ok(retryEntry.tags.includes("hook-retry"));
|
|
1906
1903
|
assert.ok(retryEntry.description);
|
|
1907
1904
|
assert.equal(retryEntry.source, "session-knowledge");
|
|
1908
1905
|
});
|
|
@@ -82,15 +82,17 @@ function extractPatternsFromStates(stateObjects) {
|
|
|
82
82
|
var label = state.specName || state._file || 'unknown';
|
|
83
83
|
var prescription = derivePrescription(metrics);
|
|
84
84
|
|
|
85
|
-
// High retry count → lesson
|
|
85
|
+
// High hook-retry count → lesson. Counts hook/sandbox events, not agent
|
|
86
|
+
// redispatches — a clean Pass@1 pipeline can still accumulate dozens.
|
|
86
87
|
if (metrics.retries && metrics.retries > 2) {
|
|
87
88
|
var retryEntry = {
|
|
88
89
|
type: 'convention',
|
|
89
|
-
name: 'high-retry-' + label,
|
|
90
|
-
description: 'Pipeline
|
|
90
|
+
name: 'high-hook-retry-' + label,
|
|
91
|
+
description: 'Pipeline triggered ' + metrics.retries + ' hook-level retries ' +
|
|
92
|
+
'(sandbox/stash-pop/re-prompts — not agent redispatches). Tool breakdown: ' +
|
|
91
93
|
JSON.stringify(metrics.toolBreakdown || {}),
|
|
92
94
|
source: 'session-knowledge',
|
|
93
|
-
tags: ['retry', 'pipeline', 'lesson'],
|
|
95
|
+
tags: ['hook-retry', 'pipeline', 'lesson'],
|
|
94
96
|
};
|
|
95
97
|
if (prescription) {
|
|
96
98
|
retryEntry.prescription = prescription;
|
|
@@ -33,7 +33,7 @@ function main() {
|
|
|
33
33
|
const statesDir = path.join(claudeDir, '.pipeline-states');
|
|
34
34
|
const activeSpecDir = path.join(claudeDir, 'spec', 'active');
|
|
35
35
|
if (fs.existsSync(statesDir)) {
|
|
36
|
-
const files = fs.readdirSync(statesDir).filter(f => f.endsWith('.json'));
|
|
36
|
+
const files = fs.readdirSync(statesDir).filter(f => f.endsWith('.json') && !f.endsWith('.metrics.json'));
|
|
37
37
|
const activeBuckets = [];
|
|
38
38
|
const orphanedBuckets = [];
|
|
39
39
|
for (const f of files) {
|
|
@@ -49,7 +49,7 @@ function main() {
|
|
|
49
49
|
lines.push(`## ${isOrphaned ? 'Orphaned' : 'Active'}: ${name}`);
|
|
50
50
|
lines.push(`- Duration: ${duration}`);
|
|
51
51
|
lines.push(`- API calls: ${m.apiCalls || 0}`);
|
|
52
|
-
lines.push(`-
|
|
52
|
+
lines.push(`- Hook retries: ${m.retries || 0}`);
|
|
53
53
|
if (m.toolBreakdown && Object.keys(m.toolBreakdown).length > 0) {
|
|
54
54
|
lines.push('- Tool breakdown:');
|
|
55
55
|
for (const [tool, count] of Object.entries(m.toolBreakdown).sort((a, b) => b[1] - a[1])) {
|
|
@@ -102,7 +102,7 @@ function main() {
|
|
|
102
102
|
parts.push(`### ${name}`);
|
|
103
103
|
parts.push(`- Duration: ${duration}`);
|
|
104
104
|
parts.push(`- API calls: ${m.apiCalls || 0}`);
|
|
105
|
-
parts.push(`-
|
|
105
|
+
parts.push(`- Hook retries: ${m.retries || 0}`);
|
|
106
106
|
if (m.rtkSavings) {
|
|
107
107
|
parts.push(`- RTK savings: ${m.rtkSavings.pct}% (${Math.round((m.rtkSavings.saved || 0) / 1000)}k tokens)`);
|
|
108
108
|
}
|
|
@@ -119,7 +119,7 @@ function main() {
|
|
|
119
119
|
parts.push('## Averages (last ' + count + ' pipelines)');
|
|
120
120
|
parts.push(`- Avg duration: ${formatMs(Math.round(totalDurationMs / count))}`);
|
|
121
121
|
parts.push(`- Avg API calls: ${Math.round(totalCalls / count)}`);
|
|
122
|
-
parts.push(`- Avg retries: ${Math.round(totalRetries / count)}`);
|
|
122
|
+
parts.push(`- Avg hook retries: ${Math.round(totalRetries / count)}`);
|
|
123
123
|
parts.push('');
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -184,8 +184,9 @@ function main() {
|
|
|
184
184
|
var pass1Pct = Math.round((pass1Count / totalPipelines) * 100);
|
|
185
185
|
var avgRetries = (totalRetrySum / totalPipelines).toFixed(1);
|
|
186
186
|
parts.push('## Pass@1 Metrics');
|
|
187
|
-
parts.push('- Pass@1: ' + pass1Pct + '% (' + pass1Count + '/' + totalPipelines + ' completed
|
|
188
|
-
parts.push('- Avg retries per pipeline: ' + avgRetries);
|
|
187
|
+
parts.push('- Pass@1 (hook-level): ' + pass1Pct + '% (' + pass1Count + '/' + totalPipelines + ' completed with zero hook retries)');
|
|
188
|
+
parts.push('- Avg hook retries per pipeline: ' + avgRetries);
|
|
189
|
+
parts.push('- Note: counts hook/sandbox events, not agent redispatches. True agent-level Pass@1 not yet tracked.');
|
|
189
190
|
parts.push('');
|
|
190
191
|
}
|
|
191
192
|
}
|