@olegkoval/agent-skills 1.41.1 → 1.41.3

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.
@@ -41,9 +41,17 @@ function liftConst(name) {
41
41
  }
42
42
 
43
43
  const preamble = [
44
- liftConst('HARD_RULES'),
44
+ // HARD_RULES is absent from the current workflow.js: the allowlist went away
45
+ // with the exemption it gated. It is still lifted-with-a-fallback rather than
46
+ // dropped, because this suite must stay runnable against an OLDER workflow.js
47
+ // (see the target argument above) to prove it discriminates. Without the
48
+ // fallback the old file throws ReferenceError instead of reporting FAIL, and a
49
+ // suite that crashes on the pre-fix input has proved nothing.
50
+ (() => { try { return liftConst('HARD_RULES') } catch { return 'const HARD_RULES = []' } })(),
45
51
  (() => { try { return liftConst('SAME_ISSUE_LINE_WINDOW') } catch { return 'const SAME_ISSUE_LINE_WINDOW = 30' } })(),
46
52
  "const SEVERITY_RANK = { observation: 0, idiomatic: 1, important: 2, critical: 3 }",
53
+ // hardRuleCorroborated is likewise gone from the current file and kept in this
54
+ // list for the same reason: an older workflow.js calls it from isHardRule.
47
55
  ...['titleTokens', 'sameIssue', 'nearbyLines', 'spanWithinWindow', 'hardRuleCorroborated',
48
56
  'isHardRule', 'longest', 'mergeFindings', 'dedup', 'shouldVerify'].map(n => {
49
57
  try { return lift(n) } catch { return `function ${n}() { throw new Error('${n} absent from this workflow.js') }` }
@@ -98,46 +106,51 @@ check('different files never merge', dedup([
98
106
  { file: 'b.ts', line: 7, severity: 'critical', title: 'Off-by-one loop skips the first line', badCode: '', description: '' },
99
107
  ]).length, 2)
100
108
 
101
- console.log('\nhard rules: a tag must be corroborated to skip verification')
102
- // Regression: any agent could bypass the verifier by writing rule: "TS-1".
103
- // Observed live - a test-coverage finding and a comment-policy finding both did.
104
- check('TS-1 on a comment-policy finding is NOT exempt',
105
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 6, title: 'Comment restates the function', badCode: '/** Sum a cart. */', description: 'a comment earns its place' }), false)
106
- check('TS-1 on a test-coverage finding is NOT exempt',
107
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 8, title: 'No test coverage', badCode: 'for (let i = 1;', description: 'zero test files added' }), false)
108
- check('an unknown rule string is NOT exempt',
109
- isHardRule({ rule: 'MADE-UP', file: 'a.ts', line: 1, title: 't', badCode: 'x as Foo', description: '' }), false)
110
- // TS-1 is judged on quoted code only: prose is full of `as` and `any`.
111
- check('the word "any" in PROSE alone is NOT exempt',
112
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'fails on any cart with items', badCode: 'total += lines[i].price', description: 'any agent could trip this' }), false)
113
- check('the phrase "such as" in prose alone is NOT exempt',
114
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'issue', badCode: 'const n = 1', description: 'a primitive such as String is used' }), false)
109
+ // This section used to assert that a `rule` tag had to be corroborated against a
110
+ // hardcoded HARD_RULES list before it could SKIP verification. That guard existed
111
+ // because a fabricated tag could buy exemption. It is gone because the exemption
112
+ // is gone: shouldVerify now returns true for every Critical and Important finding,
113
+ // and a hard rule takes the verifier's rule-specific anchor and applicability path
114
+ // instead of its runtime challenges, validated against the configured canonical
115
+ // rules file. A hardcoded list also could not recognise a custom house rule, which
116
+ // the current design supports on purpose.
117
+ //
118
+ // So the tag no longer buys a free pass; it selects a verification path. The
119
+ // predicate is correspondingly narrow: does this finding claim a rule at all.
120
+ console.log('\nhard rules: the tag selects a verification path, it does not skip one')
121
+ // Regression, still worth holding: a finding with no rule tag must never be
122
+ // treated as one. That is what routes it to the runtime challenges.
123
+ check('no rule tag is not a hard rule',
124
+ isHardRule({ file: 'a.ts', line: 1, title: 't', badCode: 'x as Foo', description: '' }), false)
125
+ check('an empty rule tag is not a hard rule',
126
+ isHardRule({ rule: '', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
127
+ check('a whitespace-only rule tag is not a hard rule',
128
+ isHardRule({ rule: ' ', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
129
+ check('a non-string rule tag is not a hard rule',
130
+ isHardRule({ rule: 1, file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
115
131
 
116
- console.log('\nhard rules: genuine violations must STILL be exempt')
117
- check('TS-1 with a real cast', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: 'const x = y as Foo;', description: '' }), true)
118
- check('TS-1 with a real any', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
119
- check('TS-2 with a .js path', isHardRule({ rule: 'TS-2', file: 'web/thing.js', line: 1, title: 'js added', badCode: '', description: '' }), true)
120
- check('GQL-1 with a nodes query',isHardRule({ rule: 'GQL-1', file: 'q.graphql', line: 1, title: 'no pageInfo', badCode: 'products { nodes { id } }', description: '' }), true)
121
- check('PR-1 anchored on the PR title', isHardRule({ rule: 'PR-1', file: 'PR title', line: 1, title: 'missing prefix', badCode: '', description: '' }), true)
122
- // A cast to a lowercase built-in is as much a TS-1 violation as a cast to a
123
- // named type. Missing it sent a genuine hard rule to a verifier that cannot
124
- // answer a policy claim, where it could be dropped.
125
- for (const cast of ['x as string', 'x as number', 'x as unknown as Foo', 'x as const', 'x as boolean']) {
126
- check(`TS-1 corroborated by \`${cast}\``,
127
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: cast, description: '' }), true)
132
+ console.log('\nhard rules: built-in and custom tags both route to rule-specific verification')
133
+ for (const rule of ['TS-1', 'TS-2', 'GQL-1', 'PR-1']) {
134
+ check(`built-in ${rule} is a hard rule`,
135
+ isHardRule({ rule, file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), true)
128
136
  }
129
- check('TS-1 corroborated by an any annotation',
130
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
131
- check('TS-1 corroborated by an any[] ',
132
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'const xs: any[] = []', description: '' }), true)
137
+ // A house rule defined in the operator's canonical rules file cannot be known to
138
+ // this workflow. Rejecting it here is what a hardcoded list did, and it silently
139
+ // disabled every custom rule a deployment configured.
140
+ check('a custom house rule is a hard rule',
141
+ isHardRule({ rule: 'SEC-1', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), true)
133
142
 
134
- console.log('\nverification scope by depth')
143
+ console.log('\nverification scope: depth controls breadth, never the trust bar')
135
144
  const crit = { severity: 'critical' }, imp = { severity: 'important' }, obs = { severity: 'observation' }
136
- check('scan verifies nothing', [crit, imp, obs].map(f => shouldVerify(f, 'scan')), [false, false, false])
137
- check('medium verifies criticals only', [crit, imp, obs].map(f => shouldVerify(f, 'medium')), [true, false, false])
138
- check('deep verifies crit + important', [crit, imp, obs].map(f => shouldVerify(f, 'deep')), [true, true, false])
139
- check('a corroborated hard rule is never verified',
140
- shouldVerify({ severity: 'critical', rule: 'TS-2', file: 'x.js', badCode: '', description: '', title: '' }, 'deep'), false)
145
+ // shouldVerify takes one argument now. Depth used to be able to switch verification
146
+ // off entirely, which meant a scan-depth review shipped unverified Criticals.
147
+ check('shouldVerify takes the finding alone', shouldVerify.length, 1)
148
+ check('critical and important are verified, observation is not',
149
+ [crit, imp, obs].map(f => shouldVerify(f)), [true, true, false])
150
+ check('a hard rule is NOT exempt from verification',
151
+ shouldVerify({ severity: 'critical', rule: 'TS-2', file: 'x.js', badCode: '', description: '', title: '' }), true)
152
+ check('a custom hard rule is NOT exempt either',
153
+ shouldVerify({ severity: 'critical', rule: 'SEC-1', file: 'x.ts', badCode: '', description: '', title: '' }), true)
141
154
 
142
155
  // Per-host model routing is optional: a deployment may pin models per host via
143
156
  // a MODEL_TABLE, or leave every agent() call to name its own model. Test it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olegkoval/agent-skills",
3
- "version": "1.41.1",
3
+ "version": "1.41.3",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-apple-kit",
3
3
  "description": "Build and ship Apple platform apps: macOS menubar apps, App Store submissions.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-creative",
3
3
  "description": "Creative and personal projects: photo galleries, music players, listings, wiki editing.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-garmin-kit",
3
3
  "description": "Build, test and publish Garmin Connect IQ watch faces.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-git-tools",
3
3
  "description": "Everyday git and GitHub CLI operations: conventional commits, branch hygiene.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "olko-github-pr",
3
3
  "description": "Drive GitHub pull requests to merge-ready: review-bot loops, CI fixes, descriptions, dependency triage.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },
@@ -41,9 +41,17 @@ function liftConst(name) {
41
41
  }
42
42
 
43
43
  const preamble = [
44
- liftConst('HARD_RULES'),
44
+ // HARD_RULES is absent from the current workflow.js: the allowlist went away
45
+ // with the exemption it gated. It is still lifted-with-a-fallback rather than
46
+ // dropped, because this suite must stay runnable against an OLDER workflow.js
47
+ // (see the target argument above) to prove it discriminates. Without the
48
+ // fallback the old file throws ReferenceError instead of reporting FAIL, and a
49
+ // suite that crashes on the pre-fix input has proved nothing.
50
+ (() => { try { return liftConst('HARD_RULES') } catch { return 'const HARD_RULES = []' } })(),
45
51
  (() => { try { return liftConst('SAME_ISSUE_LINE_WINDOW') } catch { return 'const SAME_ISSUE_LINE_WINDOW = 30' } })(),
46
52
  "const SEVERITY_RANK = { observation: 0, idiomatic: 1, important: 2, critical: 3 }",
53
+ // hardRuleCorroborated is likewise gone from the current file and kept in this
54
+ // list for the same reason: an older workflow.js calls it from isHardRule.
47
55
  ...['titleTokens', 'sameIssue', 'nearbyLines', 'spanWithinWindow', 'hardRuleCorroborated',
48
56
  'isHardRule', 'longest', 'mergeFindings', 'dedup', 'shouldVerify'].map(n => {
49
57
  try { return lift(n) } catch { return `function ${n}() { throw new Error('${n} absent from this workflow.js') }` }
@@ -98,46 +106,51 @@ check('different files never merge', dedup([
98
106
  { file: 'b.ts', line: 7, severity: 'critical', title: 'Off-by-one loop skips the first line', badCode: '', description: '' },
99
107
  ]).length, 2)
100
108
 
101
- console.log('\nhard rules: a tag must be corroborated to skip verification')
102
- // Regression: any agent could bypass the verifier by writing rule: "TS-1".
103
- // Observed live - a test-coverage finding and a comment-policy finding both did.
104
- check('TS-1 on a comment-policy finding is NOT exempt',
105
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 6, title: 'Comment restates the function', badCode: '/** Sum a cart. */', description: 'a comment earns its place' }), false)
106
- check('TS-1 on a test-coverage finding is NOT exempt',
107
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 8, title: 'No test coverage', badCode: 'for (let i = 1;', description: 'zero test files added' }), false)
108
- check('an unknown rule string is NOT exempt',
109
- isHardRule({ rule: 'MADE-UP', file: 'a.ts', line: 1, title: 't', badCode: 'x as Foo', description: '' }), false)
110
- // TS-1 is judged on quoted code only: prose is full of `as` and `any`.
111
- check('the word "any" in PROSE alone is NOT exempt',
112
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'fails on any cart with items', badCode: 'total += lines[i].price', description: 'any agent could trip this' }), false)
113
- check('the phrase "such as" in prose alone is NOT exempt',
114
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'issue', badCode: 'const n = 1', description: 'a primitive such as String is used' }), false)
109
+ // This section used to assert that a `rule` tag had to be corroborated against a
110
+ // hardcoded HARD_RULES list before it could SKIP verification. That guard existed
111
+ // because a fabricated tag could buy exemption. It is gone because the exemption
112
+ // is gone: shouldVerify now returns true for every Critical and Important finding,
113
+ // and a hard rule takes the verifier's rule-specific anchor and applicability path
114
+ // instead of its runtime challenges, validated against the configured canonical
115
+ // rules file. A hardcoded list also could not recognise a custom house rule, which
116
+ // the current design supports on purpose.
117
+ //
118
+ // So the tag no longer buys a free pass; it selects a verification path. The
119
+ // predicate is correspondingly narrow: does this finding claim a rule at all.
120
+ console.log('\nhard rules: the tag selects a verification path, it does not skip one')
121
+ // Regression, still worth holding: a finding with no rule tag must never be
122
+ // treated as one. That is what routes it to the runtime challenges.
123
+ check('no rule tag is not a hard rule',
124
+ isHardRule({ file: 'a.ts', line: 1, title: 't', badCode: 'x as Foo', description: '' }), false)
125
+ check('an empty rule tag is not a hard rule',
126
+ isHardRule({ rule: '', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
127
+ check('a whitespace-only rule tag is not a hard rule',
128
+ isHardRule({ rule: ' ', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
129
+ check('a non-string rule tag is not a hard rule',
130
+ isHardRule({ rule: 1, file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), false)
115
131
 
116
- console.log('\nhard rules: genuine violations must STILL be exempt')
117
- check('TS-1 with a real cast', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: 'const x = y as Foo;', description: '' }), true)
118
- check('TS-1 with a real any', isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
119
- check('TS-2 with a .js path', isHardRule({ rule: 'TS-2', file: 'web/thing.js', line: 1, title: 'js added', badCode: '', description: '' }), true)
120
- check('GQL-1 with a nodes query',isHardRule({ rule: 'GQL-1', file: 'q.graphql', line: 1, title: 'no pageInfo', badCode: 'products { nodes { id } }', description: '' }), true)
121
- check('PR-1 anchored on the PR title', isHardRule({ rule: 'PR-1', file: 'PR title', line: 1, title: 'missing prefix', badCode: '', description: '' }), true)
122
- // A cast to a lowercase built-in is as much a TS-1 violation as a cast to a
123
- // named type. Missing it sent a genuine hard rule to a verifier that cannot
124
- // answer a policy claim, where it could be dropped.
125
- for (const cast of ['x as string', 'x as number', 'x as unknown as Foo', 'x as const', 'x as boolean']) {
126
- check(`TS-1 corroborated by \`${cast}\``,
127
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'cast', badCode: cast, description: '' }), true)
132
+ console.log('\nhard rules: built-in and custom tags both route to rule-specific verification')
133
+ for (const rule of ['TS-1', 'TS-2', 'GQL-1', 'PR-1']) {
134
+ check(`built-in ${rule} is a hard rule`,
135
+ isHardRule({ rule, file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), true)
128
136
  }
129
- check('TS-1 corroborated by an any annotation',
130
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'function f(x: any) {}', description: '' }), true)
131
- check('TS-1 corroborated by an any[] ',
132
- isHardRule({ rule: 'TS-1', file: 'a.ts', line: 1, title: 'any', badCode: 'const xs: any[] = []', description: '' }), true)
137
+ // A house rule defined in the operator's canonical rules file cannot be known to
138
+ // this workflow. Rejecting it here is what a hardcoded list did, and it silently
139
+ // disabled every custom rule a deployment configured.
140
+ check('a custom house rule is a hard rule',
141
+ isHardRule({ rule: 'SEC-1', file: 'a.ts', line: 1, title: 't', badCode: '', description: '' }), true)
133
142
 
134
- console.log('\nverification scope by depth')
143
+ console.log('\nverification scope: depth controls breadth, never the trust bar')
135
144
  const crit = { severity: 'critical' }, imp = { severity: 'important' }, obs = { severity: 'observation' }
136
- check('scan verifies nothing', [crit, imp, obs].map(f => shouldVerify(f, 'scan')), [false, false, false])
137
- check('medium verifies criticals only', [crit, imp, obs].map(f => shouldVerify(f, 'medium')), [true, false, false])
138
- check('deep verifies crit + important', [crit, imp, obs].map(f => shouldVerify(f, 'deep')), [true, true, false])
139
- check('a corroborated hard rule is never verified',
140
- shouldVerify({ severity: 'critical', rule: 'TS-2', file: 'x.js', badCode: '', description: '', title: '' }, 'deep'), false)
145
+ // shouldVerify takes one argument now. Depth used to be able to switch verification
146
+ // off entirely, which meant a scan-depth review shipped unverified Criticals.
147
+ check('shouldVerify takes the finding alone', shouldVerify.length, 1)
148
+ check('critical and important are verified, observation is not',
149
+ [crit, imp, obs].map(f => shouldVerify(f)), [true, true, false])
150
+ check('a hard rule is NOT exempt from verification',
151
+ shouldVerify({ severity: 'critical', rule: 'TS-2', file: 'x.js', badCode: '', description: '', title: '' }), true)
152
+ check('a custom hard rule is NOT exempt either',
153
+ shouldVerify({ severity: 'critical', rule: 'SEC-1', file: 'x.ts', badCode: '', description: '', title: '' }), true)
141
154
 
142
155
  // Per-host model routing is optional: a deployment may pin models per host via
143
156
  // a MODEL_TABLE, or leave every agent() call to name its own model. Test it
@@ -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.41.1",
4
+ "version": "1.41.3",
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, launch plans.",
4
- "version": "1.41.1",
4
+ "version": "1.41.3",
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.41.1",
4
+ "version": "1.41.3",
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.41.1",
4
+ "version": "1.41.3",
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.41.1",
4
+ "version": "1.41.3",
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.41.1",
4
+ "version": "1.41.3",
5
5
  "author": {
6
6
  "name": "Oleg Koval"
7
7
  },