pantheon-opencode 1.5.0-beta.1 → 1.5.0-beta.10

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 (82) hide show
  1. package/.pantheon/code-mode/manifest.json +21 -0
  2. package/CHANGELOG.md +1026 -0
  3. package/README.md +171 -16
  4. package/README.pt-BR.md +99 -13
  5. package/bin/pantheon-init.mjs +178 -21
  6. package/package.json +23 -14
  7. package/plugin.json +1 -1
  8. package/pyproject.toml +65 -0
  9. package/scripts/code_mode_server.py +431 -55
  10. package/scripts/cost.mjs +30 -14
  11. package/scripts/doctor.mjs +178 -9
  12. package/scripts/install/cli-ui.mjs +17 -11
  13. package/scripts/install/config-migration.mjs +4 -6
  14. package/scripts/install/opencode.mjs +137 -35
  15. package/scripts/install/plugin.mjs +3 -33
  16. package/scripts/install/shared.mjs +43 -2
  17. package/scripts/install/strings.mjs +129 -0
  18. package/scripts/install-mcp.mjs +1 -0
  19. package/scripts/manifest-inventory.mjs +410 -0
  20. package/scripts/mcp_persistence_server.py +537 -128
  21. package/scripts/package-evidence.mjs +242 -0
  22. package/scripts/probe-context-rehydrate.mjs +240 -0
  23. package/scripts/probe-pantheon-cost.mjs +313 -0
  24. package/scripts/release-beta-version.mjs +56 -60
  25. package/scripts/sync-artifacts.mjs +169 -0
  26. package/scripts/sync-tui.mjs +121 -53
  27. package/scripts/test-opencode-v1-v2-sandbox.sh +367 -96
  28. package/scripts/validation-policy.mjs +7 -7
  29. package/scripts/version-check.mjs +113 -108
  30. package/scripts/versioning.mjs +230 -86
  31. package/src/agents/mnemosyne.md +1 -1
  32. package/src/agents/zeus.md +2 -2
  33. package/src/mcp/code_mode_server.py +431 -55
  34. package/src/mcp/mcp_persistence_server.py +537 -128
  35. package/src/pantheon/auto-wake.ts +1 -5
  36. package/src/pantheon/background-job-board.ts +43 -1
  37. package/src/pantheon/compaction-handoff.ts +304 -0
  38. package/src/pantheon/cost-command.ts +345 -62
  39. package/src/pantheon/delegate-manager.ts +390 -8
  40. package/src/pantheon/delegation-finalize.ts +32 -0
  41. package/src/pantheon/delegation.ts +235 -18
  42. package/src/pantheon/file-persistence-salvage.ts +64 -0
  43. package/src/pantheon/file-persistence.ts +194 -45
  44. package/src/pantheon/native-probe.ts +234 -0
  45. package/src/pantheon/native-task-status.ts +139 -0
  46. package/src/pantheon/provider-capabilities.ts +221 -0
  47. package/src/pantheon/provider-stream-tracker.ts +182 -0
  48. package/src/pantheon/shared-board.ts +37 -0
  49. package/src/pantheon/task-result-guard.ts +107 -0
  50. package/src/pantheon/token-opt.ts +146 -12
  51. package/src/pantheon/tool-ceiling.ts +159 -0
  52. package/src/pantheon/v2-events.ts +18 -1
  53. package/src/plugin-v2.ts +2 -14
  54. package/src/plugin.ts +28 -17
  55. package/src/plugins/pantheon-hooks.ts +51 -0
  56. package/src/plugins/tui/dist/server.d.ts +1 -1
  57. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  58. package/src/plugins/tui/dist/server.js +1 -1
  59. package/src/plugins/tui/dist/server.js.map +1 -1
  60. package/src/plugins/tui/dist/tui.d.ts +116 -27
  61. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  62. package/src/plugins/tui/dist/tui.js +414 -150
  63. package/src/plugins/tui/dist/tui.js.map +1 -1
  64. package/src/plugins/tui/dist/tui.tsx +447 -84
  65. package/src/plugins/tui/package-lock.json +2 -2
  66. package/src/plugins/tui/package.json +1 -1
  67. package/src/plugins/tui/src/index.tsx +447 -84
  68. package/.pantheon/code-mode/.gitkeep +0 -0
  69. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-1.json +0 -8
  70. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-10.json +0 -8
  71. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-11.json +0 -8
  72. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-2.json +0 -8
  73. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-3.json +0 -8
  74. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-4.json +0 -8
  75. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-5.json +0 -8
  76. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-6.json +0 -8
  77. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-7.json +0 -8
  78. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-8.json +0 -8
  79. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/checkpoint-9.json +0 -8
  80. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/heartbeat.json +0 -8
  81. package/.pantheon/code-mode/.pantheon/deepwork/initial-token-40k/session.json +0 -11
  82. package/src/pantheon/delegate-task-adapter.ts +0 -444
@@ -22,9 +22,10 @@ import { fileURLToPath } from 'node:url'
22
22
  const __dirname = path.dirname(fileURLToPath(import.meta.url))
23
23
  const ROOT = path.resolve(__dirname, '..')
24
24
 
25
- const REQUIRED_NODE_MAJOR = 18
25
+ const REQUIRED_NODE_MAJOR = 22
26
26
  if (parseInt(process.versions.node.split('.')[0], 10) < REQUIRED_NODE_MAJOR) {
27
27
  console.error(`❌ Node.js >= ${REQUIRED_NODE_MAJOR} required (current: ${process.versions.node})`)
28
+ console.error(' Install a newer Node via nvm: https://github.com/nvm-sh/nvm')
28
29
  process.exit(1)
29
30
  }
30
31
 
@@ -50,9 +51,13 @@ function printUsage() {
50
51
  console.log(' npx pantheon-opencode init --interactive # Force interactive TUI mode')
51
52
  console.log(' npx pantheon-opencode init --headless # Force non-interactive mode')
52
53
  console.log(' npx pantheon-opencode init -y # Skip confirmations, use defaults')
54
+ console.log(' npx pantheon-opencode init --components agents,skills,instructions')
53
55
  console.log(' npx pantheon-opencode init --opencode-version v1|v2|auto')
54
56
  console.log(' npx pantheon-opencode init --preset <name> # Install and activate model preset')
55
57
  console.log(' npx pantheon-opencode set-tier <name> # Set active model preset (global)')
58
+ console.log(
59
+ ' npx pantheon-opencode update [--stable] # Update package + re-run init (default: beta channel)',
60
+ )
56
61
  console.log(
57
62
  ' npx pantheon-opencode set-tier <name> --project # Set active model preset (project)',
58
63
  )
@@ -112,6 +117,78 @@ async function main() {
112
117
  process.exit(result.status ?? 1)
113
118
  }
114
119
 
120
+ // beta.5: one-command update — check npm dist-tag, install, re-init.
121
+ // Default channel is `beta` (the prerelease line); `--stable` uses `latest`.
122
+ if (command === 'update') {
123
+ const channel = args.includes('--stable') ? 'latest' : 'beta'
124
+ const current = readVersion()
125
+ const { spawnSync } = await import('node:child_process')
126
+ const _S = (await import('../scripts/install/strings.mjs')).strings()
127
+
128
+ console.log(`Pantheon OpenCode v${current} — checking the "${channel}" channel...`)
129
+ const view = spawnSync('npm', ['view', `pantheon-opencode@${channel}`, 'version'], {
130
+ encoding: 'utf8',
131
+ timeout: 30_000,
132
+ })
133
+ const latest = (view.stdout || '').trim().split('\n').filter(Boolean).pop()
134
+ if (view.status !== 0 || !latest) {
135
+ console.error(
136
+ `❌ Could not reach the npm registry: ${(view.stderr || view.stdout || '').trim() || 'no version returned'}`,
137
+ )
138
+ process.exit(1)
139
+ }
140
+
141
+ // Prerelease-aware compare: core (major.minor.patch) first, then the
142
+ // beta counter; a stable release outranks any beta of the same core.
143
+ const parsePantheonVersion = (v) => {
144
+ const m = String(v)
145
+ .trim()
146
+ .match(/^(\d+)\.(\d+)\.(\d+)(?:-beta\.(\d+))?$/)
147
+ if (!m) return null
148
+ return {
149
+ core: [+m[1], +m[2], +m[3]],
150
+ beta: m[4] === undefined ? Number.POSITIVE_INFINITY : +m[4],
151
+ }
152
+ }
153
+ const cmp = (a, b) => {
154
+ const pa = parsePantheonVersion(a)
155
+ const pb = parsePantheonVersion(b)
156
+ if (!pa || !pb) return 0
157
+ for (let i = 0; i < 3; i++) {
158
+ if (pa.core[i] !== pb.core[i]) return pa.core[i] - pb.core[i]
159
+ }
160
+ return pa.beta - pb.beta
161
+ }
162
+ if (cmp(latest, current) <= 0) {
163
+ console.log(`✅ Already up to date (installed v${current}; ${channel} channel: v${latest}).`)
164
+ return
165
+ }
166
+
167
+ console.log(`Updating v${current} → v${latest} (channel: ${channel})...`)
168
+ const install = spawnSync('npm', ['install', '-g', `pantheon-opencode@${channel}`], {
169
+ stdio: 'inherit',
170
+ })
171
+ if (install.status !== 0) {
172
+ console.error('❌ npm install failed — the previous installation is untouched.')
173
+ process.exit(install.status ?? 1)
174
+ }
175
+
176
+ // Refresh config/venv/MCP entries with the NEW package (resolved via
177
+ // PATH — the freshly installed global bin).
178
+ const init = spawnSync('pantheon-opencode', ['init', '--yes', '--headless'], {
179
+ stdio: 'inherit',
180
+ shell: process.platform === 'win32',
181
+ })
182
+ if (init.status !== 0 || init.error) {
183
+ console.error(
184
+ '⚠️ Updated, but the config refresh did not complete — run `npx pantheon-opencode init` manually.',
185
+ )
186
+ process.exit(init.status ?? 1)
187
+ }
188
+ console.log(`✅ Updated to v${latest}.`)
189
+ return
190
+ }
191
+
115
192
  if (args.includes('--help')) {
116
193
  printUsage()
117
194
  process.exit(0)
@@ -195,11 +272,49 @@ async function main() {
195
272
  const isProject = args.includes('--project')
196
273
  const isDryRun = args.includes('--dry-run')
197
274
  const skipMCP = args.includes('--no-mcp')
198
- const forceReinstall = args.includes('--force')
275
+ // --clean is an alias of --force (both wipe component dirs + recreate venv).
276
+ const forceReinstall = args.includes('--force') || args.includes('--clean')
199
277
  const runDoctor = args.includes('--doctor')
200
278
  const forceInteractive = args.includes('--interactive')
201
279
  const forceHeadless = args.includes('--headless')
202
280
  const autoYes = args.includes('--yes') || args.includes('-y')
281
+
282
+ // beta.5: warn on unrecognized flags instead of silently ignoring them.
283
+ const VALUE_FLAGS = new Set([
284
+ '--preset',
285
+ '--model',
286
+ '--small-model',
287
+ '--version',
288
+ '--opencode-version',
289
+ '--components',
290
+ ])
291
+ for (let i = 1; i < args.length; i++) {
292
+ const arg = args[i]
293
+ if (!arg.startsWith('--') || arg === '--help') continue
294
+ if (VALUE_FLAGS.has(arg)) {
295
+ i++ // skip the flag's value
296
+ continue
297
+ }
298
+ const bare = arg.split('=', 1)[0]
299
+ if (
300
+ !VALUE_FLAGS.has(bare) &&
301
+ ![
302
+ '--project',
303
+ '--dry-run',
304
+ '--no-mcp',
305
+ '--force',
306
+ '--clean',
307
+ '--doctor',
308
+ '--interactive',
309
+ '--headless',
310
+ '--yes',
311
+ '-y',
312
+ ].includes(bare)
313
+ ) {
314
+ console.error(`⚠️ Unknown option ignored: ${arg}`)
315
+ }
316
+ }
317
+
203
318
  const presetIndex = args.indexOf('--preset')
204
319
  const presetOpt = presetIndex >= 0 ? (args[presetIndex + 1] ?? null) : null
205
320
  // Explicit top-level model overrides for the generated config.
@@ -207,8 +322,9 @@ async function main() {
207
322
  const modelOpt = modelIndex >= 0 ? (args[modelIndex + 1] ?? null) : null
208
323
  const smallModelIndex = args.indexOf('--small-model')
209
324
  const smallModelOpt = smallModelIndex >= 0 ? (args[smallModelIndex + 1] ?? null) : null
210
- // --version v1|v2 labels the install target (informational; the config is
211
- // shared and V1-shaped under both versions). Invalid values fail fast.
325
+ // --version v1|v2|auto labels the install target. `auto` resolves the
326
+ // generation from the opencode binary at install time (see
327
+ // scripts/install/opencode-version.mjs). Invalid values fail fast.
212
328
  const versionIndex = args.indexOf('--version')
213
329
  const legacyVersionIndex = args.indexOf('--opencode-version')
214
330
  const inlineVersion = args.find((arg) => arg.startsWith('--opencode-version='))
@@ -218,20 +334,61 @@ async function main() {
218
334
  : legacyVersionIndex >= 0
219
335
  ? (args[legacyVersionIndex + 1] ?? null)
220
336
  : (inlineVersion?.split('=', 2)[1] ?? null)
221
- if (versionOpt !== null && versionOpt !== 'v1' && versionOpt !== 'v2') {
222
- console.error(`❌ Invalid --version "${versionOpt}" — expected v1 or v2`)
337
+ if (
338
+ versionOpt !== null &&
339
+ versionOpt !== 'v1' &&
340
+ versionOpt !== 'v2' &&
341
+ versionOpt !== 'auto'
342
+ ) {
343
+ console.error(`❌ Invalid --version "${versionOpt}" — expected v1, v2 or auto`)
223
344
  process.exit(1)
224
345
  }
225
346
 
226
- const components = ['agents', 'skills', 'instructions', 'commands', 'plugins']
227
- if (!skipMCP) components.push('runtime')
347
+ // --components agents,skills,... narrows the install; --no-mcp drops the
348
+ // runtime component. Unknown component names fail fast (typo protection).
349
+ const KNOWN_COMPONENTS = ['agents', 'skills', 'instructions', 'commands', 'plugins', 'runtime']
350
+ const componentsIndex = args.indexOf('--components')
351
+ const inlineComponents = args.find((arg) => arg.startsWith('--components='))
352
+ const componentsOpt =
353
+ componentsIndex >= 0
354
+ ? (args[componentsIndex + 1] ?? null)
355
+ : (inlineComponents?.split('=', 2)[1] ?? null)
356
+ let requestedComponents = null
357
+ if (componentsOpt !== null) {
358
+ requestedComponents = componentsOpt
359
+ .split(',')
360
+ .map((c) => c.trim())
361
+ .filter(Boolean)
362
+ const unknown = requestedComponents.filter((c) => !KNOWN_COMPONENTS.includes(c))
363
+ if (requestedComponents.length === 0 || unknown.length > 0) {
364
+ console.error(
365
+ `❌ Invalid --components "${componentsOpt}" — expected comma-separated names from: ${KNOWN_COMPONENTS.join(', ')}`,
366
+ )
367
+ process.exit(1)
368
+ }
369
+ }
370
+
371
+ const components = requestedComponents ?? [
372
+ 'agents',
373
+ 'skills',
374
+ 'instructions',
375
+ 'commands',
376
+ 'plugins',
377
+ ]
378
+ if (!skipMCP && !components.includes('runtime')) components.push('runtime')
379
+ if (skipMCP) {
380
+ const runtimeIndex = components.indexOf('runtime')
381
+ if (runtimeIndex >= 0) components.splice(runtimeIndex, 1)
382
+ }
228
383
 
229
384
  // Version info
230
385
  const version = readVersion()
386
+ const { strings } = await import('../scripts/install/strings.mjs')
387
+ const S = strings()
231
388
 
232
389
  console.log('')
233
390
  if (!forceInteractive || isDryRun) {
234
- console.log(`Pantheon OpenCode v${version} — ${isDryRun ? 'DRY RUN' : 'Installing...'}`)
391
+ console.log(`Pantheon OpenCode v${version} — ${isDryRun ? S.dryRun : S.installing}`)
235
392
  console.log('')
236
393
  }
237
394
 
@@ -248,15 +405,17 @@ async function main() {
248
405
  version: versionOpt ?? 'v1',
249
406
  })
250
407
  } catch (err) {
251
- console.error(
252
- `❌ Installation failed: ${err.message}\n Run with --no-mcp to skip Python dependencies:\n npx pantheon-opencode init --no-mcp\n Or retry with --force to recreate the venv:\n npx pantheon-opencode init --force`,
253
- )
408
+ if (err?.message === 'Canceled') {
409
+ console.error(S.canceled)
410
+ process.exit(130)
411
+ }
412
+ console.error(`${S.installFailed(err.message)}\n${S.failHintNoMcp}\n${S.failHintForce}`)
254
413
  process.exit(1)
255
414
  }
256
415
 
257
416
  if (runDoctor && !isDryRun) {
258
417
  console.log('')
259
- console.log(' Running health check...')
418
+ console.log(` ${S.runningHealthCheck}`)
260
419
  try {
261
420
  const { spawnSync } = await import('node:child_process')
262
421
  const doctorScript = path.join(ROOT, 'scripts', 'doctor.mjs')
@@ -268,16 +427,14 @@ async function main() {
268
427
 
269
428
  console.log('')
270
429
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
271
- console.log(` ✅ Pantheon OpenCode v${version} installed!`)
430
+ console.log(` ${S.installedTitle(version)}`)
272
431
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
273
432
  console.log('')
274
- console.log(' Next steps:')
275
- console.log(' 1. Verify installation:')
276
- console.log(' npx pantheon-opencode doctor')
277
- console.log(' 2. Launch OpenCode')
278
- console.log(' 3. Invoke agents with @agent-name in chat')
279
- console.log(' 4. For project-local install:')
280
- console.log(' npx pantheon-opencode init --project')
433
+ console.log(` ${S.nextSteps}`)
434
+ console.log(` ${S.nextVerify}`)
435
+ console.log(` ${S.nextLaunch}`)
436
+ console.log(` ${S.nextAgents}`)
437
+ console.log(` ${S.nextProject}`)
281
438
  console.log('')
282
439
 
283
440
  return
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pantheon-opencode",
3
- "version": "1.5.0-beta.1",
3
+ "version": "1.5.0-beta.10",
4
4
  "description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -28,26 +28,31 @@
28
28
  "version:status": "node scripts/versioning.mjs status",
29
29
  "version:apply": "node scripts/versioning.mjs apply",
30
30
  "version:check": "node scripts/version-check.mjs",
31
- "release:dry-run": "node scripts/versioning.mjs status && node scripts/release-notes.mjs && npm pack --dry-run",
31
+ "release:dry-run": "node scripts/versioning.mjs status && node scripts/release-notes.mjs && node scripts/package-evidence.mjs",
32
+ "package:evidence": "node scripts/package-evidence.mjs",
33
+ "package:validate": "node scripts/validate-package.mjs",
32
34
  "publish:next": "npm publish --tag next --access public",
33
- "lint": "npx biome ci .",
34
- "typecheck": "npx tsc --noEmit",
35
+ "lint": "biome ci .",
36
+ "typecheck": "tsc --noEmit",
35
37
  "audit": "npm audit --audit-level=high",
36
38
  "secret-scan": "node scripts/secret-scan.mjs",
37
39
  "hooks:install": "pre-commit install",
38
40
  "hooks:update": "pre-commit autoupdate",
39
- "test:security": "npm run secret-scan && node tests/test_install_mcp_vision.mjs && node tests/test_doctor_layers.mjs",
41
+ "test:security": "npm run secret-scan",
40
42
  "test:node": "node --test tests/*.mjs tests/pantheon/*.mjs",
41
- "test:ts": "for f in tests/pantheon/*.test.ts; do if [ \"$f\" = tests/pantheon/plugin-v2-contract.test.ts ]; then NODE_OPTIONS=--conditions=import npx tsx \"$f\"; else npx tsx \"$f\"; fi || exit 1; done",
42
- "test": "python3 -m pytest tests/ -q 2>&1; status=$?; if [ \"$status\" -eq 5 ]; then echo \"No tests found\"; fi; exit \"$status\"",
43
- "test:ci": "python3 -m pytest tests/ -q --tb=short 2>&1"
43
+ "test:ts": "for f in tests/pantheon/*.test.ts; do if [ \"$f\" = tests/pantheon/plugin-v2-contract.test.ts ]; then NODE_OPTIONS=--conditions=import tsx \"$f\"; else tsx \"$f\"; fi || exit 1; done",
44
+ "test:all": "npm run test:ci && npm run test:node && npm run test:ts",
45
+ "test": "npm run test:all",
46
+ "test:ci": "python3 -m pytest -q --tb=short 2>&1"
44
47
  },
45
48
  "bin": {
46
49
  "pantheon-opencode": "bin/pantheon-init.mjs"
47
50
  },
48
51
  "files": [
49
52
  "LICENSE",
53
+ "package-lock.json",
50
54
  "plugin.json",
55
+ "pyproject.toml",
51
56
  "scripts/install/*.mjs",
52
57
  "scripts/*.py",
53
58
  "src/plugin.ts",
@@ -64,6 +69,7 @@
64
69
  "!src/agents/README.md",
65
70
  "bin/*.mjs",
66
71
  "AGENTS.md",
72
+ "CHANGELOG.md",
67
73
  "opencode.json",
68
74
  "src/mcp/*.py",
69
75
  "src/instructions/*.instructions.md",
@@ -83,14 +89,17 @@
83
89
  "!**/*.pyc"
84
90
  ],
85
91
  "dependencies": {
86
- "@opencode-ai/plugin": "1.18.18",
87
- "js-yaml": "^4.3.0",
92
+ "@opencode-ai/plugin": "1.18.30",
93
+ "js-yaml": "^4.3.2",
88
94
  "zod": "4.1.8"
89
95
  },
90
96
  "devDependencies": {
91
- "@commitlint/cli": "^19.8.0",
92
- "@commitlint/config-conventional": "^19.8.0",
93
- "husky": "^9.1.7"
97
+ "@biomejs/biome": "2.5.13",
98
+ "@commitlint/cli": "21.2.2",
99
+ "@commitlint/config-conventional": "21.2.2",
100
+ "husky": "^9.1.7",
101
+ "tsx": "4.23.13",
102
+ "typescript": "6.0.3"
94
103
  },
95
104
  "repository": {
96
105
  "type": "git",
@@ -111,7 +120,7 @@
111
120
  "author": "ils15",
112
121
  "license": "MIT",
113
122
  "engines": {
114
- "node": ">=18"
123
+ "node": ">=22"
115
124
  },
116
125
  "preferGlobal": true
117
126
  }
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pantheon",
3
3
  "publisher": "ils15",
4
- "version": "1.5.0-beta.1",
4
+ "version": "1.5.0-beta.10",
5
5
  "displayName": "Pantheon",
6
6
  "description": "Conductor-Delegate orchestration platform with 14 specialized agents, 21 skills, and OpenCode support.",
7
7
  "agents": "./src/agents",
package/pyproject.toml ADDED
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64"]
3
+ build-backend = "setuptools.backends._legacy:_Backend"
4
+
5
+ [project]
6
+ name = "pantheon"
7
+ version = "1.5.0-beta.10"
8
+ description = "Multi-agent orchestration framework"
9
+ requires-python = ">=3.11"
10
+ dependencies = []
11
+
12
+ [tool.pytest.ini_options]
13
+ # `tests/` holds the main suite; the two entries below are orphaned test
14
+ # modules that live next to the code they cover and are collected here so
15
+ # pytest (and therefore `npm test`) exercises them instead of letting them
16
+ # rot as dead code.
17
+ testpaths = [
18
+ "tests",
19
+ "scripts/vector_memory/test_memory.py",
20
+ "benchmarks/beta2/test_beta2.py",
21
+ ]
22
+ asyncio_mode = "auto"
23
+ addopts = "-v --tb=short"
24
+
25
+ [tool.ruff]
26
+ line-length = 88
27
+ target-version = "py311"
28
+
29
+ [tool.ruff.lint]
30
+ select = ["E", "F", "W", "I", "N", "UP", "B", "SIM", "PL", "RUF", "C901"]
31
+ ignore = ["E501"]
32
+
33
+ [tool.ruff.lint.per-file-ignores]
34
+ "__init__.py" = ["F401"]
35
+ # Legacy command-line scripts intentionally use hyphenated filenames.
36
+ "scripts/ci-validate-yaml.py" = ["N999"]
37
+ "scripts/scrub-secrets.py" = ["N999"]
38
+ # These modules defer optional/heavy imports until the corresponding command is used.
39
+ "scripts/vector_memory/*.py" = ["PLC0415"]
40
+ "tests/test_code_mode_args.py" = ["PLC0415"]
41
+ "tests/test_code_mode_sandbox.py" = ["PLC0415", "N806"]
42
+ "tests/test_code_mode_server.py" = ["PLC0415"]
43
+ "tests/test_eval_store.py" = ["PLC0415", "PLR2004"]
44
+ "tests/test_memory_mcp_server.py" = ["PLC0415", "PLR2004"]
45
+ # Existing public APIs and test fixtures are intentionally broad/simple; refactoring
46
+ # them would be behavior-affecting rather than a mechanical lint correction.
47
+ "scripts/code_mode_server.py" = ["PLR0913"]
48
+ "src/mcp/code_mode_server.py" = ["PLR0913"]
49
+ "scripts/mcp_persistence_server.py" = ["PLR0913"]
50
+ "src/mcp/mcp_persistence_server.py" = ["PLR0913"]
51
+ "scripts/memory_mcp_server.py" = ["C901"]
52
+ "scripts/vector_memory/index.py" = ["C901", "PLR0913", "PLR2004", "PLW0603", "PLW2901"]
53
+ "scripts/vector_memory/cli.py" = ["PLR2004"]
54
+ "scripts/vector_memory/query.py" = ["PLR0913"]
55
+ "src/mcp/eval_store.py" = ["PLR2004"]
56
+ "tests/test_code_mode_frontmatter.py" = ["PLR2004"]
57
+ "tests/test_eval_judge.py" = ["PLR2004"]
58
+ "tests/test_eval_static.py" = ["PLR2004"]
59
+ "tests/test_mcp_persistence_server.py" = ["PLR2004"]
60
+
61
+ [tool.mypy]
62
+ python_version = "3.11"
63
+ strict = true
64
+ ignore_missing_imports = true
65
+ disallow_untyped_defs = true