@lythos/skill-arena 0.9.6 → 0.9.7

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lythos/skill-arena",
3
- "version": "0.9.6",
3
+ "version": "0.9.7",
4
4
  "description": "Skill Arena — benchmark skill effectiveness with controlled-variable comparison",
5
5
  "keywords": [
6
6
  "ai-agent",
package/src/cli.ts CHANGED
@@ -593,11 +593,11 @@ async function runProgrammaticArena(argv: string[]) {
593
593
  const configPath = (options as Record<string, string | undefined>).config!
594
594
 
595
595
  const toml = parseArenaToml(readFileSync(configPath, 'utf-8'))
596
+ const { dirname } = await import('node:path')
596
597
  const result = await runArenaFromToml({
597
598
  toml,
598
- taskPath: toml.arena.task.startsWith('/') || toml.arena.task.startsWith('./')
599
- ? toml.arena.task
600
- : (options as Record<string, string | undefined>).task ?? toml.arena.task,
599
+ taskPath: toml.arena.task,
600
+ configDir: dirname(configPath), // resolve relative paths against config file dir
601
601
  outDir: (options as Record<string, string | undefined>).out,
602
602
  dryRun,
603
603
  })
package/src/runner.ts CHANGED
@@ -43,10 +43,23 @@ export async function runArenaFromToml(opts: {
43
43
  outDir?: string
44
44
  dryRun?: boolean
45
45
  log?: (msg: string) => void
46
+ configDir?: string // for resolving relative paths
46
47
  }): Promise<ArenaResult | { plan: ReturnType<typeof buildExecutionPlan> }> {
47
- const { toml, taskPath, outDir, dryRun, log } = opts
48
+ const { toml, taskPath, outDir, dryRun, log, configDir } = opts
48
49
 
49
- const plan = buildExecutionPlan(toml)
50
+ // Resolve relative paths against config dir (anti-footgun: cwd may differ)
51
+ const resolvePath = (p: string) => {
52
+ if (p.startsWith('/')) return p
53
+ if (configDir) return resolve(configDir, p)
54
+ return resolve(p)
55
+ }
56
+ const taskAbs = resolvePath(taskPath)
57
+ const resolvedToml: ArenaToml = {
58
+ ...toml,
59
+ side: toml.side.map(s => ({ ...s, deck: resolvePath(s.deck) })),
60
+ }
61
+
62
+ const plan = buildExecutionPlan(resolvedToml)
50
63
 
51
64
  // dry-run: return plan without executing
52
65
  if (dryRun) {
@@ -58,13 +71,13 @@ export async function runArenaFromToml(opts: {
58
71
 
59
72
  const arenaId = `arena-${stamp()}`
60
73
  const artifactsDir = outDir || join(process.cwd(), 'runs', arenaId)
61
- const resolved = resolveSides(toml)
74
+ const resolved = resolveSides(resolvedToml)
62
75
 
63
76
  // Build manifest
64
77
  const manifest = ArenaManifest.parse({
65
78
  id: arenaId,
66
79
  created_at: new Date().toISOString(),
67
- task: readFileSync(resolve(taskPath), 'utf-8').slice(0, 200),
80
+ task: readFileSync(taskAbs, 'utf-8').slice(0, 200),
68
81
  mode: 'decks',
69
82
  participants: [...new Map(resolved.map(r => [r.side.name, r])).values()].map(r => ({
70
83
  id: r.side.name,
@@ -73,7 +86,7 @@ export async function runArenaFromToml(opts: {
73
86
  deck: r.side.deck,
74
87
  description: `${r.playerName} × ${r.side.deck}`,
75
88
  })),
76
- criteria: toml.arena.criteria,
89
+ criteria: resolvedToml.arena.criteria,
77
90
  status: 'running',
78
91
  })
79
92