@olegkoval/agent-skills 1.43.0 → 1.44.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/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +85 -2
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/pricing.json +9 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-conventions.md +158 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-implementation.md +76 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-quality.md +87 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-simplification.md +63 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-test-quality.md +172 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/phase4-comparison.md +42 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profile.md +347 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-deep.md +82 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-medium.md +81 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/fixtures/context.json +3 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/fixtures/house-rules.md +11 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/fixtures/revmux-report.json +179 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/install-revmux-prompts.sh +66 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/revmux-adapter.mjs +261 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/revmux-engine.sh +156 -0
- package/adapters/claude/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +76 -0
- package/package.json +1 -1
- package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +85 -2
- package/plugins/olko-github-pr/skills/lekker-review/references/pricing.json +9 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-conventions.md +158 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-implementation.md +76 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-quality.md +87 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-simplification.md +63 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/lenses/lekker-test-quality.md +172 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/phase4-comparison.md +42 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profile.md +347 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-deep.md +82 -0
- package/plugins/olko-github-pr/skills/lekker-review/references/revmux/profiles/lekker-medium.md +81 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/fixtures/context.json +3 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/fixtures/house-rules.md +11 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/fixtures/revmux-report.json +179 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/install-revmux-prompts.sh +66 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/revmux-adapter.mjs +261 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/revmux-engine.sh +156 -0
- package/plugins/olko-github-pr/skills/lekker-review/scripts/selftest.mjs +76 -0
- package/plugins/olko-github-pr/skills/lekker-review/workflow.js +43 -6
- package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
- package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
|
@@ -183,5 +183,81 @@ if (!hasRouting) {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
console.log('\nrevmux adapter: fixture mapping')
|
|
187
|
+
{
|
|
188
|
+
const { execFileSync, spawnSync } = await import('node:child_process')
|
|
189
|
+
const fixturePath = join(SKILL, 'scripts', 'fixtures', 'revmux-report.json')
|
|
190
|
+
const contextPath = join(SKILL, 'scripts', 'fixtures', 'context.json')
|
|
191
|
+
const pricingPath = join(SKILL, 'references', 'pricing.json')
|
|
192
|
+
const adapterPath = join(SKILL, 'scripts', 'revmux-adapter.mjs')
|
|
193
|
+
const adapterArgs = [adapterPath, fixturePath, '--pricing', pricingPath, '--context', contextPath]
|
|
194
|
+
const out = execFileSync('node', adapterArgs, { encoding: 'utf8' })
|
|
195
|
+
const adapted = JSON.parse(out)
|
|
196
|
+
|
|
197
|
+
check('engine tag', adapted.engine, 'revmux')
|
|
198
|
+
check('critical confirmed kept critical',
|
|
199
|
+
adapted.findings.some(f => f.title.includes('Race between webhook retry') && f.severity === 'critical'), true)
|
|
200
|
+
check('major refined -> important, agreedBy from 2 sources',
|
|
201
|
+
(() => {
|
|
202
|
+
const f = adapted.findings.find(f => f.title.includes('Discount stacking'))
|
|
203
|
+
return f && f.severity === 'important' && Array.isArray(f.agreedBy) && f.agreedBy.length === 2
|
|
204
|
+
})(), true)
|
|
205
|
+
check('minor + lekker-conventions lens -> idiomatic',
|
|
206
|
+
adapted.findings.find(f => f.title.includes('naming matrix'))?.severity, 'idiomatic')
|
|
207
|
+
check('immaterial verdict dropped, not re-promoted',
|
|
208
|
+
adapted.findings.some(f => f.title.includes('Unused import')), false)
|
|
209
|
+
check('rejected non-hard-rule dropped',
|
|
210
|
+
adapted.findings.some(f => f.title.includes('double-count a tip')), false)
|
|
211
|
+
check('TS-1 rejected but corroborated by quoted code IS re-promoted to critical',
|
|
212
|
+
(() => {
|
|
213
|
+
const f = adapted.findings.find(f => f.title.includes('Unsafe cast on inventory adjustment'))
|
|
214
|
+
return f && f.severity === 'critical' && f.rule === 'TS-1'
|
|
215
|
+
})(), true)
|
|
216
|
+
check('TS-1 rejected with no corroborating code stays dropped',
|
|
217
|
+
adapted.findings.some(f => f.title.includes('Type safety concern in inventory handler')), false)
|
|
218
|
+
check('prose without an extracted snippet leaves badCode empty',
|
|
219
|
+
adapted.findings.find(f => f.title.includes('no retry backoff'))?.badCode, '')
|
|
220
|
+
check('configured custom hard rule with quoted code is re-promoted',
|
|
221
|
+
adapted.findings.find(f => f.title.includes('Session token is logged'))?.severity, 'critical')
|
|
222
|
+
check('configured custom hard rule without quoted code stays dropped',
|
|
223
|
+
adapted.findings.some(f => f.title.includes('Possible session concern')), false)
|
|
224
|
+
check('pre_existing becomes observation with Pre-existing: prefix',
|
|
225
|
+
(() => {
|
|
226
|
+
const f = adapted.findings.find(f => f.title.includes('no retry backoff'))
|
|
227
|
+
return f && f.severity === 'observation' && f.description.startsWith('Pre-existing:')
|
|
228
|
+
})(), true)
|
|
229
|
+
check('open_questions pass through as questions',
|
|
230
|
+
adapted.questions.length, 1)
|
|
231
|
+
check('degraded agent surfaced by name',
|
|
232
|
+
adapted.degraded, ['adversarial'])
|
|
233
|
+
check('droppedCount counts four rejected or immaterial findings', adapted.droppedCount, 4)
|
|
234
|
+
check('hardRuleCount counts built-in and custom re-promotions', adapted.hardRuleCount, 2)
|
|
235
|
+
check('totalUsd computed from known pricing', typeof adapted.totalUsd === 'number' && adapted.totalUsd > 0, true)
|
|
236
|
+
check('malformed token rows do not make totalUsd NaN', Number.isFinite(adapted.totalUsd), true)
|
|
237
|
+
check('malformed token rows keep their own usd unknown',
|
|
238
|
+
adapted.agents.find(a => a.name === 'malformed-cost')?.usd, null)
|
|
239
|
+
check('no pricingMissing when all models are priced', adapted.pricingMissing, undefined)
|
|
240
|
+
check('test-quality coverage verdict is populated from attributed findings',
|
|
241
|
+
adapted.coverageVerdict.includes('Operator-flip mutation'), true)
|
|
242
|
+
check('mutation-slip summary is populated from attributed findings',
|
|
243
|
+
adapted.mutationSlip.includes('retry guard'), true)
|
|
244
|
+
check('mock smells are structured from attributed findings', adapted.mockSmells.length, 1)
|
|
245
|
+
|
|
246
|
+
const noPricingOut = execFileSync('node', [adapterPath, fixturePath, '--context', contextPath], { encoding: 'utf8' })
|
|
247
|
+
const noPricingAdapted = JSON.parse(noPricingOut)
|
|
248
|
+
check('without a pricing file every model is pricingMissing',
|
|
249
|
+
noPricingAdapted.pricingMissing?.includes('claude-sonnet-5'), true)
|
|
250
|
+
check('without a pricing file totalUsd is null', noPricingAdapted.totalUsd, null)
|
|
251
|
+
|
|
252
|
+
for (const [label, badArgs] of [
|
|
253
|
+
['report', [adapterPath, join(SKILL, 'SKILL.md')]],
|
|
254
|
+
['pricing', [adapterPath, fixturePath, '--pricing', join(SKILL, 'SKILL.md'), '--context', contextPath]],
|
|
255
|
+
]) {
|
|
256
|
+
const failedRun = spawnSync('node', badArgs, { encoding: 'utf8' })
|
|
257
|
+
check(`invalid ${label} JSON exits 2`, failedRun.status, 2)
|
|
258
|
+
check(`invalid ${label} JSON has a clear error`, failedRun.stderr.includes(`${label} JSON`), true)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
186
262
|
console.log(failed === 0 ? '\nall checks passed\n' : `\n${failed} check(s) FAILED\n`)
|
|
187
263
|
process.exit(failed === 0 ? 0 : 1)
|
|
@@ -364,8 +364,14 @@ const {
|
|
|
364
364
|
reviewBatchPlan,
|
|
365
365
|
maxConcurrent,
|
|
366
366
|
targetLabel: targetLabelArg,
|
|
367
|
+
engine: engineArg,
|
|
368
|
+
findingsFile,
|
|
367
369
|
} = input
|
|
368
370
|
|
|
371
|
+
// 'revmux' skips straight to Prove on pre-computed findings, so Prove's
|
|
372
|
+
// worktree/depth rules aren't duplicated in the adapter.
|
|
373
|
+
const ENGINE = (engineArg === 'revmux') ? 'revmux' : 'workflow'
|
|
374
|
+
|
|
369
375
|
const targetLabel = targetLabelArg || `PR #${prNumber}`
|
|
370
376
|
|
|
371
377
|
if (!repoSlug || (!prNumber && !targetLabelArg) || !depth || !diffFile || !contextFile || !promptDir) {
|
|
@@ -374,6 +380,9 @@ if (!repoSlug || (!prNumber && !targetLabelArg) || !depth || !diffFile || !conte
|
|
|
374
380
|
'): ' + JSON.stringify({ repoSlug, prNumber, targetLabel, depth, diffFile, contextFile, promptDir })
|
|
375
381
|
)
|
|
376
382
|
}
|
|
383
|
+
if (ENGINE === 'revmux' && !findingsFile) {
|
|
384
|
+
throw new Error('lekker-review workflow: engine "revmux" requires findingsFile (adapter output)')
|
|
385
|
+
}
|
|
377
386
|
|
|
378
387
|
// Concurrency. The review stage is self-limiting: five dimensions means five
|
|
379
388
|
// agents, so it runs them all at once. The other stages are not. Verify,
|
|
@@ -386,7 +395,7 @@ const REVIEW_PLAN = (Array.isArray(reviewBatchPlan) && reviewBatchPlan.length >
|
|
|
386
395
|
const FANOUT_PLAN = [Math.max(1, maxConcurrent || 5)]
|
|
387
396
|
const targetMetadata = JSON.stringify({ targetLabel })
|
|
388
397
|
|
|
389
|
-
log(`args ok: ${targetLabel} in ${repoSlug}, depth=${depth}, reviewPlan=[${REVIEW_PLAN}], fanout=${FANOUT_PLAN[0]}`)
|
|
398
|
+
log(`args ok: ${targetLabel} in ${repoSlug}, depth=${depth}, reviewPlan=[${REVIEW_PLAN}], fanout=${FANOUT_PLAN[0]}, engine=${ENGINE}`)
|
|
390
399
|
|
|
391
400
|
const budgetAtStart = budget.spent()
|
|
392
401
|
|
|
@@ -580,6 +589,32 @@ const budgetAtStart = budget.spent()
|
|
|
580
589
|
// contradictory verdicts) on the same issue found by two dimensions.
|
|
581
590
|
// -------------------------------------------------------------------------
|
|
582
591
|
|
|
592
|
+
let finalFindings
|
|
593
|
+
let implementationResult = {}
|
|
594
|
+
let testQualityResult = {}
|
|
595
|
+
let revmuxPassthrough = null
|
|
596
|
+
|
|
597
|
+
if (ENGINE === 'revmux') {
|
|
598
|
+
const adapterOutput = JSON.parse(readFileSync(findingsFile, 'utf8'))
|
|
599
|
+
finalFindings = (adapterOutput.findings || []).map(function(f) {
|
|
600
|
+
return Object.assign({}, f)
|
|
601
|
+
})
|
|
602
|
+
droppedCount = adapterOutput.droppedCount || 0
|
|
603
|
+
hardRuleCount = adapterOutput.hardRuleCount || 0
|
|
604
|
+
agentCount = adapterOutput.agentCount || 0
|
|
605
|
+
implementationResult = adapterOutput
|
|
606
|
+
testQualityResult = adapterOutput
|
|
607
|
+
revmuxPassthrough = {
|
|
608
|
+
questions: adapterOutput.questions || [],
|
|
609
|
+
agents: adapterOutput.agents || [],
|
|
610
|
+
degraded: adapterOutput.degraded || [],
|
|
611
|
+
totalTokens: adapterOutput.totalTokens,
|
|
612
|
+
totalUsd: adapterOutput.totalUsd,
|
|
613
|
+
pricingMissing: adapterOutput.pricingMissing || [],
|
|
614
|
+
}
|
|
615
|
+
log(`revmux engine: loaded ${finalFindings.length} finding(s) from ${findingsFile} (dropped=${droppedCount}, hardRule=${hardRuleCount}); skipping Review/Verify/Critic`)
|
|
616
|
+
} else {
|
|
617
|
+
|
|
583
618
|
phase('Review')
|
|
584
619
|
|
|
585
620
|
log(`Review: ${dimensions.length} dimension(s) in batches of [${REVIEW_PLAN}]`)
|
|
@@ -589,10 +624,10 @@ const budgetAtStart = budget.spent()
|
|
|
589
624
|
}), REVIEW_PLAN)
|
|
590
625
|
|
|
591
626
|
const reviewResults = reviewed.filter(Boolean)
|
|
592
|
-
|
|
627
|
+
implementationResult = reviewResults.find(function(result) {
|
|
593
628
|
return result.key === 'implementation'
|
|
594
629
|
}) || {}
|
|
595
|
-
|
|
630
|
+
testQualityResult = reviewResults.find(function(result) {
|
|
596
631
|
return result.key === 'test-quality'
|
|
597
632
|
}) || {}
|
|
598
633
|
const deduped = dedup(reviewResults.flatMap(function(result) {
|
|
@@ -613,7 +648,7 @@ const budgetAtStart = budget.spent()
|
|
|
613
648
|
// Critic (deep only)
|
|
614
649
|
// -------------------------------------------------------------------------
|
|
615
650
|
|
|
616
|
-
|
|
651
|
+
finalFindings = verifiedFindings
|
|
617
652
|
|
|
618
653
|
if (depth === 'deep') {
|
|
619
654
|
phase('Critic')
|
|
@@ -712,6 +747,8 @@ const budgetAtStart = budget.spent()
|
|
|
712
747
|
}
|
|
713
748
|
}
|
|
714
749
|
|
|
750
|
+
} // end ENGINE === 'workflow' branch
|
|
751
|
+
|
|
715
752
|
// -------------------------------------------------------------------------
|
|
716
753
|
// Prove: for each Critical finding (excluding hard rules, which are policy
|
|
717
754
|
// violations with no runtime failure to demonstrate), attempt to produce an
|
|
@@ -791,7 +828,7 @@ const budgetAtStart = budget.spent()
|
|
|
791
828
|
return clean
|
|
792
829
|
})
|
|
793
830
|
|
|
794
|
-
return {
|
|
831
|
+
return Object.assign({
|
|
795
832
|
findings: output,
|
|
796
833
|
droppedCount,
|
|
797
834
|
downgradedCount,
|
|
@@ -805,4 +842,4 @@ const budgetAtStart = budget.spent()
|
|
|
805
842
|
mockSmells: Array.isArray(testQualityResult.mockSmells) ? testQualityResult.mockSmells : [],
|
|
806
843
|
outputTokens: budget.spent() - budgetAtStart,
|
|
807
844
|
turnTokensTotal: budget.spent(),
|
|
808
|
-
}
|
|
845
|
+
}, Object.assign({ engine: ENGINE }, revmuxPassthrough || {}))
|