@olegkoval/agent-skills 1.49.2 โ†’ 1.51.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.
Files changed (75) hide show
  1. package/.github/copilot-instructions.md +1 -0
  2. package/.github/prompts/coderabbitloop.prompt.md +90 -15
  3. package/.github/prompts/codexloop.prompt.md +33 -6
  4. package/.github/prompts/copilotloop.prompt.md +302 -0
  5. package/.github/prompts/geminiloop.prompt.md +34 -6
  6. package/.github/prompts/qodoloop.prompt.md +18 -0
  7. package/.kiro/steering/coderabbitloop.md +90 -15
  8. package/.kiro/steering/codexloop.md +33 -6
  9. package/.kiro/steering/copilotloop.md +301 -0
  10. package/.kiro/steering/geminiloop.md +34 -6
  11. package/.kiro/steering/qodoloop.md +18 -0
  12. package/.windsurf/rules/coderabbitloop.md +90 -15
  13. package/.windsurf/rules/codexloop.md +33 -6
  14. package/.windsurf/rules/copilotloop.md +300 -0
  15. package/.windsurf/rules/geminiloop.md +34 -6
  16. package/.windsurf/rules/qodoloop.md +18 -0
  17. package/README.md +1 -0
  18. package/adapters/claude/olko-github-pr/skills/coderabbitloop/SKILL.md +91 -16
  19. package/adapters/claude/olko-github-pr/skills/coderabbitloop/references/graphql-queries.md +41 -9
  20. package/adapters/claude/olko-github-pr/skills/codexloop/SKILL.md +35 -8
  21. package/adapters/claude/olko-github-pr/skills/copilotloop/SKILL.md +309 -0
  22. package/adapters/claude/olko-github-pr/skills/geminiloop/SKILL.md +36 -8
  23. package/adapters/claude/olko-github-pr/skills/lekker-review/SKILL.md +26 -1
  24. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/completeness-critic.md +12 -0
  25. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/implementation.md +26 -1
  26. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/prover.md +8 -1
  27. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/test-quality.md +20 -2
  28. package/adapters/claude/olko-github-pr/skills/lekker-review/references/agents/verifier.md +25 -0
  29. package/adapters/claude/olko-github-pr/skills/lekker-review/references/fix-mode.md +23 -0
  30. package/adapters/claude/olko-github-pr/skills/qodoloop/SKILL.md +19 -1
  31. package/adapters/claude/olko-github-pr/skills/qodoloop/references/graphql-queries.md +19 -2
  32. package/adapters/codex/olko-github-pr/README.md +1 -0
  33. package/adapters/cursor/olko-github-pr/skills/coderabbitloop/SKILL.md +91 -16
  34. package/adapters/cursor/olko-github-pr/skills/coderabbitloop/references/graphql-queries.md +41 -9
  35. package/adapters/cursor/olko-github-pr/skills/codexloop/SKILL.md +35 -8
  36. package/adapters/cursor/olko-github-pr/skills/copilotloop/SKILL.md +309 -0
  37. package/adapters/cursor/olko-github-pr/skills/geminiloop/SKILL.md +36 -8
  38. package/adapters/cursor/olko-github-pr/skills/qodoloop/SKILL.md +19 -1
  39. package/adapters/cursor/olko-github-pr/skills/qodoloop/references/graphql-queries.md +19 -2
  40. package/adapters/grok/olko-github-pr/skills/coderabbitloop/SKILL.md +91 -16
  41. package/adapters/grok/olko-github-pr/skills/coderabbitloop/references/graphql-queries.md +41 -9
  42. package/adapters/grok/olko-github-pr/skills/codexloop/SKILL.md +35 -8
  43. package/adapters/grok/olko-github-pr/skills/copilotloop/SKILL.md +309 -0
  44. package/adapters/grok/olko-github-pr/skills/geminiloop/SKILL.md +36 -8
  45. package/adapters/grok/olko-github-pr/skills/qodoloop/SKILL.md +19 -1
  46. package/adapters/grok/olko-github-pr/skills/qodoloop/references/graphql-queries.md +19 -2
  47. package/catalog/skills.json +23 -0
  48. package/package.json +1 -1
  49. package/plugins/olko-apple-kit/.claude-plugin/plugin.json +1 -1
  50. package/plugins/olko-creative/.claude-plugin/plugin.json +1 -1
  51. package/plugins/olko-garmin-kit/.claude-plugin/plugin.json +1 -1
  52. package/plugins/olko-git-tools/.claude-plugin/plugin.json +1 -1
  53. package/plugins/olko-github-pr/.claude-plugin/plugin.json +1 -1
  54. package/plugins/olko-github-pr/skills/coderabbitloop/SKILL.md +91 -16
  55. package/plugins/olko-github-pr/skills/coderabbitloop/references/graphql-queries.md +41 -9
  56. package/plugins/olko-github-pr/skills/codexloop/SKILL.md +35 -8
  57. package/plugins/olko-github-pr/skills/copilotloop/SKILL.md +308 -0
  58. package/plugins/olko-github-pr/skills/geminiloop/SKILL.md +36 -8
  59. package/plugins/olko-github-pr/skills/lekker-review/SKILL.md +26 -1
  60. package/plugins/olko-github-pr/skills/lekker-review/references/agents/completeness-critic.md +12 -0
  61. package/plugins/olko-github-pr/skills/lekker-review/references/agents/implementation.md +26 -1
  62. package/plugins/olko-github-pr/skills/lekker-review/references/agents/prover.md +8 -1
  63. package/plugins/olko-github-pr/skills/lekker-review/references/agents/test-quality.md +20 -2
  64. package/plugins/olko-github-pr/skills/lekker-review/references/agents/verifier.md +25 -0
  65. package/plugins/olko-github-pr/skills/lekker-review/references/fix-mode.md +23 -0
  66. package/plugins/olko-github-pr/skills/lekker-review/workflow.js +87 -5
  67. package/plugins/olko-github-pr/skills/qodoloop/SKILL.md +19 -1
  68. package/plugins/olko-github-pr/skills/qodoloop/references/graphql-queries.md +19 -2
  69. package/plugins/olko-obsidian/.claude-plugin/plugin.json +1 -1
  70. package/plugins/olko-product/.claude-plugin/plugin.json +1 -1
  71. package/plugins/olko-reflection/.claude-plugin/plugin.json +1 -1
  72. package/plugins/olko-release/.claude-plugin/plugin.json +1 -1
  73. package/plugins/olko-skill-meta/.claude-plugin/plugin.json +1 -1
  74. package/plugins/olko-web-ops/.claude-plugin/plugin.json +1 -1
  75. package/scripts/lib/catalog.mjs +1 -1
@@ -8,11 +8,30 @@ export const meta = {
8
8
  // Schemas
9
9
  // ---------------------------------------------------------------------------
10
10
 
11
+ const BOUNDARY_SCHEMA = {
12
+ type: 'object',
13
+ required: ['entryPoint', 'consumer'],
14
+ properties: {
15
+ entryPoint: { type: 'string', minLength: 1, pattern: '\\S' },
16
+ decisionPoint: { type: 'string' },
17
+ realizationPoint: { type: 'string' },
18
+ consumer: { type: 'string', minLength: 1, pattern: '\\S' },
19
+ stateOwner: { type: 'string' },
20
+ evidenceClass: { type: 'string' },
21
+ identityDimensions: { type: 'array', items: { type: 'string' } },
22
+ transitions: { type: 'array', items: { type: 'string' } },
23
+ },
24
+ }
25
+
11
26
  const FINDINGS_ARRAY_SCHEMA = {
12
27
  type: 'array',
13
28
  items: {
14
29
  type: 'object',
15
30
  required: ['file', 'line', 'severity', 'title', 'description', 'badCode', 'fix'],
31
+ anyOf: [
32
+ { properties: { severity: { enum: ['observation', 'idiomatic'] } } },
33
+ { required: ['boundary'] },
34
+ ],
16
35
  properties: {
17
36
  file: { type: 'string' },
18
37
  line: { type: 'integer' },
@@ -23,6 +42,7 @@ const FINDINGS_ARRAY_SCHEMA = {
23
42
  fix: { type: 'string' },
24
43
  precedent: { type: 'string' },
25
44
  rule: { type: 'string', minLength: 1, pattern: '\\S' },
45
+ boundary: BOUNDARY_SCHEMA,
26
46
  },
27
47
  },
28
48
  }
@@ -267,6 +287,41 @@ function shouldVerify(finding) {
267
287
  return finding.severity === 'critical' || finding.severity === 'important'
268
288
  }
269
289
 
290
+ /**
291
+ * Does the finding carry enough of a composed boundary map to attempt a
292
+ * proof? Requires an entry point and a consumer, plus at least one of a
293
+ * realization point, state owner, or recorded transition.
294
+ */
295
+ function hasBoundaryProofSurface(finding) {
296
+ const boundary = finding && finding.boundary
297
+ if (!boundary || typeof boundary !== 'object') {
298
+ return false
299
+ }
300
+ const hasText = function(value) {
301
+ return typeof value === 'string' && value.trim().length > 0
302
+ }
303
+ const hasList = function(value) {
304
+ return Array.isArray(value) && value.length > 0
305
+ }
306
+ return hasText(boundary.entryPoint)
307
+ && hasText(boundary.consumer)
308
+ && (
309
+ hasText(boundary.realizationPoint)
310
+ || hasText(boundary.stateOwner)
311
+ || hasList(boundary.transitions)
312
+ )
313
+ }
314
+
315
+ /**
316
+ * Does this finding qualify for the Prove stage? Every Critical finding
317
+ * qualifies; an Important finding only qualifies when it has a composed
318
+ * boundary map to prove against.
319
+ */
320
+ function shouldProve(finding) {
321
+ return finding.severity === 'critical'
322
+ || (finding.severity === 'important' && hasBoundaryProofSurface(finding))
323
+ }
324
+
270
325
  function normalizeProof(result) {
271
326
  const hasText = function(value) {
272
327
  return typeof value === 'string' && value.trim().length > 0
@@ -520,7 +575,29 @@ const budgetAtStart = budget.spent()
520
575
  // rule-specific checks and skip only its runtime-oriented challenges.
521
576
  // -------------------------------------------------------------------------
522
577
 
578
+ // A model verdict cannot replace the required production boundary map.
579
+ function enforceBoundary(finding) {
580
+ if (!shouldVerify(finding)) return finding
581
+ const boundary = finding.boundary
582
+ const hasText = function(value) {
583
+ return typeof value === 'string' && value.trim().length > 0
584
+ }
585
+ if (boundary && typeof boundary === 'object' && !Array.isArray(boundary)
586
+ && hasText(boundary.entryPoint) && hasText(boundary.consumer)) {
587
+ return finding
588
+ }
589
+ downgradedCount++
590
+ const unverified = Object.assign({}, finding, {
591
+ severity: 'observation',
592
+ verificationStatus: 'unverified',
593
+ verifierReasoning: 'Missing boundary object or identified production entry point/downstream consumer; downgraded to non-blocking',
594
+ })
595
+ delete unverified.proof
596
+ return unverified
597
+ }
598
+
523
599
  async function verifyAll(findings) {
600
+ findings = findings.map(enforceBoundary)
524
601
  const inScope = findings.filter(function(f) {
525
602
  return shouldVerify(f)
526
603
  })
@@ -704,7 +781,8 @@ const budgetAtStart = budget.spent()
704
781
  }
705
782
 
706
783
  // Verify the new finding through the same verifier path
707
- const newFinding = Object.assign({}, reResult.findings[0])
784
+ const newFinding = enforceBoundary(Object.assign({}, reResult.findings[0]))
785
+ if (newFinding.verificationStatus === 'unverified') return [newFinding]
708
786
  newFinding._dimension = `critic:${angle.axis}`
709
787
 
710
788
  agentCount++
@@ -749,9 +827,13 @@ const budgetAtStart = budget.spent()
749
827
 
750
828
  } // end ENGINE === 'workflow' branch
751
829
 
830
+ // Recheck after critic dedup and imported results, before proof promotion.
831
+ finalFindings = finalFindings.map(enforceBoundary)
832
+
752
833
  // -------------------------------------------------------------------------
753
- // Prove: for each Critical finding (excluding hard rules, which are policy
754
- // violations with no runtime failure to demonstrate), attempt to produce an
834
+ // Prove: for each Critical finding and each Important finding with a
835
+ // composed boundary map (excluding hard rules, which are policy violations
836
+ // with no runtime failure to demonstrate), attempt to produce an
755
837
  // executable failing test in the worktree. Only runs with a worktree and
756
838
  // outside scan depth, and is capped so a pathological finding count can't
757
839
  // blow the budget.
@@ -770,7 +852,7 @@ const budgetAtStart = budget.spent()
770
852
 
771
853
  if (worktreePath && depth !== 'scan') {
772
854
  const proveCandidates = finalFindings.filter(function(f) {
773
- return f.severity === 'critical' && !isHardRule(f)
855
+ return shouldProve(f) && !isHardRule(f)
774
856
  })
775
857
 
776
858
  if (proveCandidates.length > 0) {
@@ -779,7 +861,7 @@ const budgetAtStart = budget.spent()
779
861
  const capped = proveCandidates.slice(0, 5)
780
862
  const skipped = proveCandidates.length - capped.length
781
863
  if (skipped > 0) {
782
- log(`Prove: capping at 5 provers, skipping ${skipped} additional critical finding(s)`)
864
+ log(`Prove: capping at 5 provers, skipping ${skipped} additional finding(s)`)
783
865
  }
784
866
 
785
867
  await batched(capped.map(function(finding) {
@@ -8,7 +8,7 @@ description: >
8
8
  addressed against Qodo's review, or says "run qodoloop" / "satisfy Qodo" / "resolve Qodo comments".
9
9
  compatibility: Requires git and gh (GitHub CLI) authenticated, with Qodo Merge installed on the repo.
10
10
  metadata:
11
- version: "1.0"
11
+ version: "1.1"
12
12
  allowed-tools: Bash(gh:*) Bash(git:*)
13
13
  ---
14
14
 
@@ -85,6 +85,14 @@ Run the paginated GraphQL query in `references/graphql-queries.md` (`unresolvedQ
85
85
 
86
86
  Build the working set: all `recommended` threads, plus `optional` ones too if `--include-optional`.
87
87
 
88
+ Mark each thread as seen with an ๐Ÿ‘€ reaction on its first comment (`databaseId` from the query), so
89
+ the bot and a watching human can tell it is being worked. GitHub's reaction set is fixed; `eyes` is
90
+ the only "looking at it" value:
91
+
92
+ ```bash
93
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=eyes
94
+ ```
95
+
88
96
  #### C. Check exit conditions
89
97
 
90
98
  Stop if the working set is empty, or max iterations reached.
@@ -121,6 +129,16 @@ This is the "answer to the comments" half of the job, not optional cleanup, and
121
129
  Pass the thread id and reply text as GraphQL **variables** (`-f threadId=... -f body=...`), never interpolated into the query string itself: a reply containing a quote, backtick, or newline breaks (or worse, injects into) a hand-built query. Then resolve with `resolveReviewThread` (see references file).
122
130
  - **Blocked** findings: reply explaining exactly why (false positive / needs a human call), but **do not resolve**: leave the thread open. A blocked finding that gets silently resolved is a false "done".
123
131
 
132
+ Then record each disposition as a reaction on the thread's first comment: the learning signal, and
133
+ a visible marker for a human scanning the PR. ๐Ÿ‘ (`+1`) for a fixed finding, ๐Ÿ‘Ž (`-1`) for a
134
+ blocked/rebutted one. Reply first, react, then resolve: a reaction never replaces the reply.
135
+
136
+ ```bash
137
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=+1
138
+ # blocked/rebutted finding:
139
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=-1
140
+ ```
141
+
124
142
  Go back to step A.
125
143
 
126
144
  ### 3. Report
@@ -26,7 +26,7 @@ query($cursor: String) {
26
26
  id
27
27
  isResolved
28
28
  comments(first: 1) {
29
- nodes { body path line author { login } }
29
+ nodes { databaseId body path line author { login } }
30
30
  }
31
31
  }
32
32
  }
@@ -60,7 +60,7 @@ while :; do
60
60
  nodes {
61
61
  id
62
62
  isResolved
63
- comments(first: 1) { nodes { body path line author { login } } }
63
+ comments(first: 1) { nodes { databaseId body path line author { login } } }
64
64
  }
65
65
  }
66
66
  }
@@ -126,6 +126,23 @@ the branch (SKILL.md ยง2E-F): resolving first and pushing second means a
126
126
  failed push leaves GitHub showing the finding as handled when it isn't. Never
127
127
  resolve a blocked/skipped finding at all; reply to it and leave it open.
128
128
 
129
+ ## React to a comment (the bot's learning signal)
130
+
131
+ Reacting needs the comment's REST id, which is why `databaseId` is selected in
132
+ the thread query above. The reaction set is fixed; only eight values exist:
133
+ `+1`, `-1`, `laugh`, `confused`, `heart`, `hooray`, `rocket`, `eyes`.
134
+
135
+ ```bash
136
+ # ๐Ÿ‘€ as soon as you start working a finding
137
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=eyes
138
+ # ๐Ÿ‘ when it was accepted and fixed, ๐Ÿ‘Ž when it was rebutted (the correction signal)
139
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=+1
140
+ gh api --method POST repos/{owner}/{repo}/pulls/comments/<DATABASE_ID>/reactions -f content=-1
141
+ ```
142
+
143
+ React after the reply and before the resolve, so GitHub records the reason and
144
+ the disposition together. A reaction never replaces the reply.
145
+
129
146
  ## Fetch the rollup issue comment (context only, not the source of truth)
130
147
 
131
148
  Useful for the human-readable summary counts (bugs/rule-violations) in your
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-obsidian",
3
3
  "description": "Keep an Obsidian vault in sync with work: PR sync, task rollover, morning routine.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-product",
3
3
  "description": "Take a product idea to a shippable build: MVP passes, full-stack scaffolds, UX/UI quality loops, launch plans.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-reflection",
3
3
  "description": "Look back and improve: self-critique, retrospectives, performance review, rapid learning.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-release",
3
3
  "description": "Ship a release: semantic-release setup, changelogs, store listing copy, release-day routine.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-skill-meta",
3
3
  "description": "Author and maintain agent skills and the AI toolchain itself.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-web-ops",
3
3
  "description": "Operate a website: WAF rules, search console audits, analytics bootstrap, docs indexes.",
4
- "version": "1.49.2",
4
+ "version": "1.51.0",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -6,7 +6,7 @@ export const PLUGIN_ASSIGNMENT = {
6
6
  'olko-github-pr': {
7
7
  description: 'Drive GitHub pull requests to merge-ready: review-bot loops, CI fixes, descriptions, dependency triage.',
8
8
  skills: ['pr-finalize', 'pr-finalize-complete', 'pr-to-green', 'pr-description-writer',
9
- 'qodoloop', 'coderabbitloop', 'codexloop', 'geminiloop', 'ci-fix-loop',
9
+ 'qodoloop', 'coderabbitloop', 'codexloop', 'copilotloop', 'geminiloop', 'ci-fix-loop',
10
10
  'dependabot-triage', 'lekker-review'],
11
11
  },
12
12
  'olko-git-tools': {