Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .oxlint/harlanzw.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Oxlint reads a plugin from the default export. eslint-plugin-harlanzw
// exports it by name, so this re-export adapts it.
import { plugin } from 'eslint-plugin-harlanzw'

export default plugin
35 changes: 33 additions & 2 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"correctness": "error"
},
"plugins": ["import", "oxc", "typescript", "vue"],
"jsPlugins": ["./.oxlint/harlanzw.mjs"],
"rules": {
"eqeqeq": ["error", "smart"],
"no-debugger": "error",
Expand All @@ -14,7 +15,37 @@
"ignoreReadBeforeAssign": true
}
],
"require-yield": "off"
"require-yield": "off",
"harlanzw/no-silent-catch": "error",
"harlanzw/nuxt-await-navigate-to": "error",
"harlanzw/nuxt-no-random": "error",
"harlanzw/nuxt-no-redundant-component-imports": "error",
"harlanzw/nuxt-no-redundant-import-meta": "error",
"harlanzw/nuxt-no-self-layer-alias": "error",
"harlanzw/nuxt-no-side-effects-in-async-data-handler": "error",
"harlanzw/nuxt-no-side-effects-in-setup": "error",
"harlanzw/nuxt-no-unsafe-date": "error",
"harlanzw/nuxt-prefer-layer-alias": "error",
"harlanzw/nuxt-prefer-nuxt-link-over-router-link": "error",
"harlanzw/prefer-node-style-text": "error",
"harlanzw/vue-no-async-lifecycle-hook": "error",
"harlanzw/vue-no-faux-composables": "error",
"harlanzw/vue-no-nested-reactivity": "error",
"harlanzw/vue-no-passing-refs-as-props": "error",
"harlanzw/vue-no-reactive-destructuring": "error",
"harlanzw/vue-no-reactivity-after-await": "error",
"harlanzw/vue-no-torefs-on-props": "error",
"harlanzw/vue-no-unresolvable-define-emits": "error",
"harlanzw/vue-prefer-define-emits-object-syntax": "error",
"harlanzw/vue-require-composable-prefix": "error"
},
"ignorePatterns": ["**/.generated/**"]
"ignorePatterns": ["**/.generated/**"],
"overrides": [
{
"files": ["**/test/fixtures/**"],
"rules": {
"harlanzw/nuxt-no-side-effects-in-setup": "off"
}
}
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"@opencode/plugin": "catalog:",
"@types/node": "catalog:",
"@types/semver": "catalog:",
"eslint-plugin-harlanzw": "catalog:",
"oxfmt": "catalog:",
"oxlint": "catalog:",
"semver": "catalog:",
Expand Down
2 changes: 1 addition & 1 deletion packages/advocaat/test/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ describe('jev api', () => {
},
})

await client.systemOne({ state: null, questions: { q: noul() } }).catch(() => undefined)
await expect(client.systemOne({ state: null, questions: { q: noul() } })).rejects.toBeDefined()

expect(calls).toBe(1)
})
Expand Down
2 changes: 2 additions & 0 deletions packages/wolfstar-github-agent/src/worker-github-evidence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ export function jobExecutionContext(
readingScript = false
if (scriptLines.length > 0) current.run = redactSecrets(scriptLines.join('\n')).slice(0, 4_000)
} else if (readingScript && scriptLines.join('\n').length < 4_000) {
// GitHub Actions logs carry these literal sequences. The line is parsed, not printed.
// oxlint-disable-next-line harlanzw/prefer-node-style-text
scriptLines.push(line.replaceAll('\x1B[36;1m', '').replaceAll('\x1B[0m', ''))
}
if (match?.[1] === 'working-directory') current.workingDirectory = safeText(match[2]!)
Expand Down
2 changes: 2 additions & 0 deletions packages/wolfstar-github-agent/test/opencode-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function request(overrides: Partial<AgentTurnRequest> = {}): AgentTurnRequest {
}
}

/* oxlint-disable harlanzw/prefer-node-style-text -- the child prints the exact ANSI bytes real opencode writes. */
/** One real child process that replays a fixed opencode run. */
function replay(
lines: unknown[],
Expand All @@ -44,6 +45,7 @@ function replay(
`
return (args: string[]) => spawn(process.execPath, ['-e', script, ...args], { stdio: ['ignore', 'pipe', 'pipe'] })
}
/* oxlint-enable harlanzw/prefer-node-style-text */

async function collect(events: AsyncIterable<AgentEvent>): Promise<AgentEvent[]> {
const items: AgentEvent[] = []
Expand Down
572 changes: 541 additions & 31 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ catalog:
citty: ^0.2.2
consola: ^3.4.2
esbuild: 0.28.2
eslint-plugin-harlanzw: ^0.23.0
ghostty-web: 0.4.0
h3: ^2.0.5
image-size: ^2.0.4
Expand Down
3 changes: 2 additions & 1 deletion wolfstar-agent-kit/skills/hogwild/scripts/hw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { spawnSync } from 'node:child_process'
import process from 'node:process'
import { styleText } from 'node:util'
import { plan, stepArgv } from './plan.ts'

const result = plan(process.argv.slice(2))
Expand All @@ -13,7 +14,7 @@ if (result._tag === 'Err') {
}

for (const step of result.steps) {
if (step.title) console.log(`\x1B[1m# ${step.title} (${step.host})\x1B[0m`)
if (step.title) console.log(styleText('bold', `# ${step.title} (${step.host})`))
const [file, ...args] = stepArgv(step)
const { status } = spawnSync(file as string, args, { stdio: 'inherit' })
if (status !== 0) {
Expand Down
2 changes: 1 addition & 1 deletion wolfstar-agent-kit/skills/pkg-conform/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ See `references/` for detailed templates:
3. [ ] `.github/workflows/test.yml` - action versions and Markdown path filtering
4. [ ] `.editorconfig` - standard config
5. [ ] `.gitignore` - standard patterns
6. [ ] ESLint config - antfu + `eslint-plugin-wolfstarzw`. Package: `eslint.config.mjs`; Site: `eslint.config.js`
6. [ ] Lint config - `.oxlintrc.json` and `.oxfmtrc.json`, plus `eslint-plugin-harlanzw` loaded through `.oxlint/harlanzw.mjs`. See `references/configs.md`
7. [ ] `tsconfig.json` - Package: `module: preserve`, `moduleDetection: force`; Site: `extends .nuxt/tsconfig.json`
8. [ ] Git hooks - `lint-staged` in devDeps, `pre-commit` runs `lint-staged`
9. [ ] `AGENTS.md` - router shape, 30 to 80 lines. No `CLAUDE.md`, no `CONTEXT.md`. See `../../references/root-docs.md`
Expand Down
3 changes: 3 additions & 0 deletions wolfstar-agent-kit/skills/pkg-conform/references/catalogs.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ catalog:
'@arethetypeswrong/cli': ^0.18.2
'@types/node': ^25.2.1
bumpp: ^10.4.1
eslint-plugin-harlanzw: ^0.23.0
lint-staged: ^16.3.2
obuild: ^0.4.24
oxfmt: ^0.65.0
Expand All @@ -37,6 +38,7 @@ catalog:
'@arethetypeswrong/cli': ^0.18.2
'@types/node': ^25.2.1
bumpp: ^10.4.1
eslint-plugin-harlanzw: ^0.23.0
lint-staged: ^16.3.2
obuild: ^0.4.24
oxfmt: ^0.65.0
Expand All @@ -54,6 +56,7 @@ ignoredBuiltDependencies:
```json
{
"devDependencies": {
"eslint-plugin-harlanzw": "catalog:",
"oxfmt": "catalog:",
"oxlint": "catalog:",
"vitest": "catalog:",
Expand Down
31 changes: 31 additions & 0 deletions wolfstar-agent-kit/skills/pkg-conform/references/configs.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,37 @@ coverage
}
```

### eslint-plugin-harlanzw

Oxlint loads ESLint plugins as `jsPlugins` and reads the plugin from the default export.
`eslint-plugin-harlanzw` exports it by name, so re-export it:

```js
// .oxlint/harlanzw.mjs
import { plugin } from 'eslint-plugin-harlanzw'

export default plugin
```

Add `"jsPlugins": ["./.oxlint/harlanzw.mjs"]` to `.oxlintrc.json`, then enable rules as `harlanzw/<rule>`:

```json
{
"jsPlugins": ["./.oxlint/harlanzw.mjs"],
"rules": {
"harlanzw/no-silent-catch": "error",
"harlanzw/nuxt-await-navigate-to": "error",
"harlanzw/nuxt-no-random": "error",
"harlanzw/nuxt-no-unsafe-date": "error",
"harlanzw/vue-no-reactive-destructuring": "error",
"harlanzw/vue-no-reactivity-after-await": "error"
}
}
```

Only rules that read a script run. Oxlint does not run Vue template rules (`link-*`, `vue-no-ref-access-in-templates`) or the Markdown rules (`ai-deslop-*`, `prompt-*`, `docs-*`).
Run a new rule across the repository as `warn` first. `no-test-file-reads`, `prefer-satisfies`, `vue-no-resolve-component-in-composables`, and `nuxt-prefer-navigate-to-over-router-push-replace` raise false positives on common patterns, so enable them only after a count.

## .oxfmtrc.json

```json
Expand Down