pantheon-opencode 1.5.1 → 1.6.0-beta.1

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 (62) hide show
  1. package/.pantheon/code-mode/README.md +4 -2
  2. package/.pantheon/code-mode/checkpoint_session.py +138 -102
  3. package/.pantheon/code-mode/compress-inline.py +102 -57
  4. package/.pantheon/code-mode/manifest.json +2 -8
  5. package/CHANGELOG.md +22 -0
  6. package/README.md +86 -52
  7. package/README.pt-BR.md +63 -43
  8. package/commands/pantheon-optimize.md +2 -2
  9. package/package.json +13 -1
  10. package/plugin.json +1 -1
  11. package/pyproject.toml +8 -15
  12. package/scripts/build-agents-md.mjs +2 -2
  13. package/scripts/check-plugin-v2-coverage.mjs +213 -0
  14. package/scripts/ci-validate-yaml.py +7 -5
  15. package/scripts/code_mode_server.py +116 -24
  16. package/scripts/doctor.mjs +85 -28
  17. package/scripts/install/cli-ui.mjs +1 -1
  18. package/scripts/install/config-migration.mjs +2 -2
  19. package/scripts/install/health-check.mjs +6 -19
  20. package/scripts/install/interactive.mjs +6 -6
  21. package/scripts/install/migrate.mjs +1 -1
  22. package/scripts/install/state.mjs +27 -2
  23. package/scripts/mcp_persistence_server.py +390 -76
  24. package/scripts/memory_mcp_server.py +370 -196
  25. package/scripts/postinstall.mjs +0 -7
  26. package/scripts/probe-context-rehydrate.mjs +28 -11
  27. package/scripts/prune.mjs +2 -2
  28. package/scripts/sync-tui.mjs +11 -5
  29. package/scripts/test-opencode-v2-sandbox.sh +1759 -0
  30. package/scripts/validate-routing.mjs +40 -0
  31. package/skills-lock.json +9 -10
  32. package/src/agents/mnemosyne.md +15 -16
  33. package/src/agents/zeus.md +1 -2
  34. package/src/mcp/code_mode_server.py +116 -24
  35. package/src/mcp/mcp_codemap_module.py +559 -129
  36. package/src/mcp/mcp_persistence_server.py +390 -76
  37. package/src/mcp/memory_mcp_server.py +371 -248
  38. package/src/mcp/pantheon_vision_server.py +136 -24
  39. package/src/mcp/requirements-mcp.txt +5 -3
  40. package/src/mcp/requirements-vision.txt +2 -0
  41. package/src/pantheon/model-command.ts +18 -7
  42. package/src/pantheon/todo-enforcer.ts +1 -1
  43. package/src/pantheon/vision.ts +1 -1
  44. package/src/plugin-v2.ts +134 -104
  45. package/src/plugins/tui/dist/tui.js +1 -1
  46. package/src/plugins/tui/package-lock.json +20 -20
  47. package/src/plugins/tui/package.json +12 -12
  48. package/src/routing.yml +0 -1
  49. package/src/skills/README.md +31 -36
  50. package/src/skills/auto-continue/SKILL.md +25 -75
  51. package/.pantheon/code-mode/eval-llm-judge.py +0 -255
  52. package/.pantheon/code-mode/eval-monte-carlo.py +0 -368
  53. package/.pantheon/code-mode/eval-run.py +0 -197
  54. package/.pantheon/code-mode/eval-static.py +0 -321
  55. package/.pantheon/code-mode/session-end-save.py +0 -186
  56. package/.pantheon/code-mode/session-end-save.sh +0 -18
  57. package/scripts/recover-zenodo-deposition.mjs +0 -146
  58. package/scripts/test-opencode-v1-v2-sandbox.sh +0 -862
  59. package/scripts/validate-zenodo-release.mjs +0 -154
  60. package/scripts/zenodo-artifact.mjs +0 -21
  61. package/scripts/zenodo-release-state.mjs +0 -53
  62. package/src/skills/orchestration-workflow/SKILL.md +0 -311
@@ -1,154 +0,0 @@
1
- #!/usr/bin/env node
2
- /** Validate the immutable inputs used by the GitHub Release → Zenodo workflow. */
3
-
4
- import { existsSync, readFileSync } from 'node:fs'
5
- import { join } from 'node:path'
6
- import { pathToFileURL } from 'node:url'
7
- import { compareVersions } from './version-check.mjs'
8
-
9
- const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/
10
-
11
- function validateHttpsUrl(value, name) {
12
- let url
13
- try {
14
- url = new URL(value)
15
- } catch {
16
- throw new Error(`${name} must be an absolute HTTPS URL.`)
17
- }
18
- if (
19
- url.protocol !== 'https:' ||
20
- !url.hostname ||
21
- url.username ||
22
- url.password ||
23
- /%(?![0-9A-Fa-f]{2})/.test(value) ||
24
- /[\s{}\\|^`]/.test(value)
25
- ) {
26
- throw new Error(`${name} must be an absolute HTTPS URL without credentials.`)
27
- }
28
- return url
29
- }
30
-
31
- function maskHost(hostname) {
32
- if (hostname.length <= 2) return '***'
33
- return `${hostname[0]}***${hostname.at(-1)}`
34
- }
35
-
36
- export function summarizeZenodoConfiguration({
37
- depositionsUrl,
38
- filesUrlTemplate,
39
- publishUrlTemplate,
40
- creatorName,
41
- }) {
42
- const values = [
43
- ['ZENODO_DEPOSITIONS_URL', depositionsUrl, true],
44
- ['ZENODO_FILES_URL_TEMPLATE', filesUrlTemplate, true],
45
- ['ZENODO_PUBLISH_URL_TEMPLATE', publishUrlTemplate, true],
46
- ['ZENODO_CREATOR_NAME', creatorName, false],
47
- ]
48
- return values.map(([name, value, isUrl]) => {
49
- if (typeof value !== 'string' || !value) return { name, present: false }
50
- if (!isUrl) return { name, present: true }
51
- try {
52
- const url = new URL(value.replaceAll('{id}', '1'))
53
- return {
54
- name,
55
- present: true,
56
- protocol: url.protocol,
57
- host: maskHost(url.hostname),
58
- hasWhitespace: /\s/.test(value),
59
- hasCredentials: Boolean(url.username || url.password),
60
- }
61
- } catch {
62
- return {
63
- name,
64
- present: true,
65
- protocol: 'invalid',
66
- host: '***',
67
- hasWhitespace: /\s/.test(value),
68
- }
69
- }
70
- })
71
- }
72
-
73
- export function zenodoTemplateUrl(template, id, name = 'Zenodo URL template') {
74
- if (!Number.isSafeInteger(id) || id <= 0) throw new Error('Zenodo deposition id is invalid.')
75
- if (typeof template !== 'string' || !template.includes('{id}'))
76
- throw new Error(`${name} must contain the {id} placeholder.`)
77
- return validateHttpsUrl(template.replaceAll('{id}', String(id)), name).href
78
- }
79
-
80
- export function zenodoDepositionUrl(depositionsUrl, id) {
81
- if (!Number.isSafeInteger(id) || id <= 0) throw new Error('Zenodo deposition id is invalid.')
82
- if (typeof depositionsUrl !== 'string')
83
- throw new Error('ZENODO_DEPOSITIONS_URL must be an absolute HTTPS URL.')
84
- const base = validateHttpsUrl(depositionsUrl, 'ZENODO_DEPOSITIONS_URL')
85
- if (base.search || base.hash)
86
- throw new Error('ZENODO_DEPOSITIONS_URL must not contain a query or fragment.')
87
- return new URL(`${base.pathname.replace(/\/$/, '')}/${id}`, base.origin).href
88
- }
89
-
90
- export function validateZenodoConfiguration({
91
- depositionsUrl,
92
- filesUrlTemplate,
93
- publishUrlTemplate,
94
- creatorName,
95
- }) {
96
- const base = validateHttpsUrl(depositionsUrl, 'ZENODO_DEPOSITIONS_URL')
97
- for (const [name, template] of [
98
- ['ZENODO_FILES_URL_TEMPLATE', filesUrlTemplate],
99
- ['ZENODO_PUBLISH_URL_TEMPLATE', publishUrlTemplate],
100
- ]) {
101
- if (
102
- typeof template !== 'string' ||
103
- !template.includes('{id}') ||
104
- template.replaceAll('{id}', '').match(/[{}]/) ||
105
- template.includes('{{') ||
106
- template.includes('}}')
107
- ) {
108
- throw new Error(`${name} must be an HTTPS URL template containing the {id} placeholder.`)
109
- }
110
- const url = new URL(zenodoTemplateUrl(template, 1, name))
111
- if (url.origin !== base.origin) throw new Error(`${name} must use the Zenodo depositions host.`)
112
- }
113
- if (typeof creatorName !== 'string' || !creatorName.trim())
114
- throw new Error('ZENODO_CREATOR_NAME must not be empty.')
115
- return true
116
- }
117
-
118
- export function validateZenodoRelease(root, tag) {
119
- if (!/^v/.test(tag)) throw new Error('Release tag must start with v.')
120
- const version = tag.slice(1)
121
- if (!SEMVER.test(version)) throw new Error('Release tag is not valid semver.')
122
- const packageJson = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
123
- if (packageJson.name !== 'pantheon-opencode' || packageJson.version !== version) {
124
- throw new Error('Release tag does not match package.json.')
125
- }
126
- const manifests = compareVersions(root)
127
- if (!manifests.ok) throw new Error('Release manifests are out of sync.')
128
- const citationPath = join(root, 'CITATION.cff')
129
- const citation = { present: existsSync(citationPath), version: null }
130
- if (citation.present) {
131
- const match = readFileSync(citationPath, 'utf8').match(/^version:\s*["']?([^"'\s]+)["']?\s*$/m)
132
- if (!match) throw new Error('CITATION.cff is missing its version field.')
133
- citation.version = match[1]
134
- if (citation.version !== version)
135
- throw new Error('CITATION.cff version differs from the release tag.')
136
- }
137
- return { tag, version, citation }
138
- }
139
-
140
- const isDirectRun = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href
141
- if (isDirectRun) {
142
- try {
143
- validateZenodoConfiguration({
144
- depositionsUrl: process.env.ZENODO_DEPOSITIONS_URL,
145
- filesUrlTemplate: process.env.ZENODO_FILES_URL_TEMPLATE,
146
- publishUrlTemplate: process.env.ZENODO_PUBLISH_URL_TEMPLATE,
147
- creatorName: process.env.ZENODO_CREATOR_NAME,
148
- })
149
- console.log(JSON.stringify(validateZenodoRelease(process.cwd(), process.env.RELEASE_TAG ?? '')))
150
- } catch (error) {
151
- console.error(`zenodo validation: ${error.message}`)
152
- process.exit(1)
153
- }
154
- }
@@ -1,21 +0,0 @@
1
- import { createHash } from 'node:crypto'
2
- import { readFileSync } from 'node:fs'
3
-
4
- export function sha256File(path) {
5
- return createHash('sha256').update(readFileSync(path)).digest('hex')
6
- }
7
-
8
- export function findZenodoFile(record, filename, checksum) {
9
- if (!record || typeof record !== 'object' || !Array.isArray(record.files)) {
10
- throw new Error('Zenodo record did not contain a files array.')
11
- }
12
- const matches = record.files.filter((file) => file?.filename === filename)
13
- if (matches.length > 1) throw new Error(`Zenodo record contains duplicate file: ${filename}.`)
14
- if (matches.length === 0) return null
15
- const file = matches[0]
16
- const expected = `sha256:${checksum}`
17
- if (file.checksum !== expected) {
18
- throw new Error(`Zenodo checksum mismatch for ${filename}.`)
19
- }
20
- return file
21
- }
@@ -1,53 +0,0 @@
1
- const DOI_PATTERN = /^10\.\d{4,9}\/\S+$/
2
- const MARKER_PATTERN =
3
- /<!-- zenodo-deposition:(?:id=(\d+);)?(?:doi=([^;\s]+);)?state=(pending|created|published)(?:;claim=([^\s]+))? -->/
4
-
5
- export function extractZenodoDoi(response) {
6
- if (!response || typeof response !== 'object') return null
7
- const candidates = [response.doi, response.metadata?.doi, response.links?.doi]
8
- for (const candidate of candidates) {
9
- if (typeof candidate === 'string' && DOI_PATTERN.test(candidate.trim())) return candidate.trim()
10
- }
11
- return null
12
- }
13
-
14
- export function validateZenodoResponse(response, { requireDoi = false } = {}) {
15
- if (!response || typeof response !== 'object' || Array.isArray(response)) {
16
- throw new Error('Zenodo response must be a JSON object.')
17
- }
18
- if (!Number.isSafeInteger(response.id) || response.id <= 0) {
19
- throw new Error('Zenodo response did not contain a valid deposition id.')
20
- }
21
- const doi = extractZenodoDoi(response)
22
- if (requireDoi && !doi) throw new Error('Zenodo response did not contain a valid DOI.')
23
- return { id: response.id, doi }
24
- }
25
-
26
- export function parseZenodoMarker(body) {
27
- const text = String(body ?? '')
28
- const match = text.match(MARKER_PATTERN)
29
- if (!match) {
30
- const legacy = text.match(/<!-- zenodo-deposition-id:(\d+) -->/)
31
- if (!legacy) return null
32
- const id = Number(legacy[1])
33
- if (!Number.isSafeInteger(id) || id <= 0)
34
- throw new Error('Zenodo marker has an invalid deposition id.')
35
- return { id, doi: null, state: 'created', claim: null }
36
- }
37
- const id = match[1] ? Number(match[1]) : null
38
- if (match[1] && (!Number.isSafeInteger(id) || id <= 0))
39
- throw new Error('Zenodo marker has an invalid deposition id.')
40
- if (match[2] && !DOI_PATTERN.test(match[2])) throw new Error('Zenodo marker has an invalid DOI.')
41
- return { id, doi: match[2] ?? null, state: match[3], claim: match[4] ?? null }
42
- }
43
-
44
- export function zenodoMarker({ id = null, doi = null, state, claim = null }) {
45
- if (!['pending', 'created', 'published'].includes(state))
46
- throw new Error('Zenodo marker state is invalid.')
47
- if (id !== null && (!Number.isSafeInteger(id) || id <= 0))
48
- throw new Error('Zenodo marker id is invalid.')
49
- if (doi !== null && !DOI_PATTERN.test(doi)) throw new Error('Zenodo marker DOI is invalid.')
50
- if (state !== 'pending' && id === null)
51
- throw new Error('Created or published Zenodo markers require an id.')
52
- return `<!-- zenodo-deposition:${id === null ? '' : `id=${id};`}${doi === null ? '' : `doi=${doi};`}state=${state}${claim === null ? '' : `;claim=${claim}`} -->`
53
- }
@@ -1,311 +0,0 @@
1
- ---
2
- name: orchestration-workflow
3
- description: "Practical step-by-step walkthrough for orchestrating features end-to-end using the multi-agent system, from planning through deployment"
4
- context: fork
5
- globs: ["**/AGENTS.md", "**/agents/*.agent.md"]
6
- alwaysApply: false
7
- ---
8
-
9
- # Orchestration Workflow: Step-by-Step Guide
10
-
11
- Practical walkthrough for using the multi-agent system end-to-end. This is your "how-to" guide for orchestrating features from planning through production deployment.
12
-
13
- ---
14
-
15
- ## Your First Feature (Real Example)
16
-
17
- **Scenario:** You want to add JWT authentication to your app.
18
- **Time:** ~6-8 hours total (spread across 1-2 days)
19
- **Team:** All agents working together
20
- **Result:** Complete feature with 95% coverage, security audit passed, ready to deploy
21
-
22
- ---
23
-
24
- ## Step 1: Plan the Feature (30 minutes)
25
-
26
- ### What You Do
27
-
28
- Open VS Code, start a chat with Copilot:
29
-
30
- ```
31
- @athena: Plan JWT authentication with refresh tokens
32
-
33
- Requirements:
34
- - User login with email + password
35
- - JWT access token (15 min expiry)
36
- - Refresh token (7 day expiry)
37
- - Secure token storage (httpOnly cookies)
38
- - Token verification on protected routes
39
- - Rate limiting (5 attempts/min)
40
- - OWASP Top 10 compliant
41
-
42
- Please create a detailed 3-4 phase implementation plan.
43
- ```
44
-
45
- ### What Athena Does
46
-
47
- Athena researches patterns, calls Apollo for existing auth code, and creates:
48
-
49
- ```
50
- 📋 Plan: JWT Authentication
51
- ├─ Phase 1: Database Schema (Demeter)
52
- │ ├─ Tasks: Create user + token tables
53
- │ ├─ Test requirements: 5 test cases
54
- │ └─ Risk: Zero-downtime migration
55
- ├─ Phase 2: Backend Services (Hermes)
56
- │ ├─ Tasks: JWT service + endpoints
57
- │ ├─ Test requirements: 8 test cases
58
- │ └─ Risk: Token expiry edge cases
59
- ├─ Phase 3: Frontend Integration (Aphrodite)
60
- │ ├─ Tasks: LoginForm + useAuth hook
61
- │ ├─ Test requirements: 6 test cases
62
- │ └─ Risk: Token refresh race condition
63
- └─ FAQ: Answers to common questions
64
- ```
65
-
66
- ### What You Do
67
-
68
- 1. Review the plan presented by Athena in chat
69
- 2. **Ask questions or approve**
70
- - If concerns: `@athena: Please adjust plan because...`
71
- - If approved: "Plan looks good, let's proceed"
72
-
73
- ### ⏸️ PAUSE POINT 1: Plan Approval
74
-
75
- ```
76
- Athena: ✅ Plan approved! Ready to orchestrate implementation
77
- Zeus: Starting Phase 1 - Database Schema
78
- ```
79
-
80
- ---
81
-
82
- ## Step 2: Orchestrate Implementation
83
-
84
- ### Phase 1: Database Schema
85
-
86
- **Zeus delegates to Demeter:**
87
- ```
88
- @demeter: Implement database schema for JWT auth
89
-
90
- Requirements:
91
- - User table: id, email, hashed_password
92
- - Token table: id, user_id, token, issued_at, expires_at, revoked_at
93
- - Indexes: user(email), token(user_id, token)
94
-
95
- TDD: RED → GREEN → REFACTOR
96
- Coverage target: >80%
97
- ```
98
-
99
- **Demeter does:**
100
- 1. Write FAILING migration test (RED)
101
- 2. Write minimal migration (GREEN)
102
- 3. Refactor (REFACTOR) — add types, indexes, constraints, timestamps
103
-
104
- **Demeter delivers:** Schema files + tests, >80% coverage
105
-
106
- **Themis reviews:** Coverage, security, performance, tests → APPROVED
107
-
108
- **Background dispatch for independent phases (OpenCode v1.16.2+):**
109
- If Phase 2 (backend) and Phase 3 (frontend) have no file dependencies, Zeus can dispatch both in **background** simultaneously and continue working while they execute. This eliminates the sequential wait.
110
-
111
- ### ⏸️ PAUSE POINT 2: Phase Review
112
-
113
- ```
114
- Zeus: "Phase 1 complete! Coverage: >80% ✅ Security: ✅ Tests: passing ✅
115
- Ready to continue to Phase 2?"
116
-
117
- User: "continue"
118
- ```
119
-
120
- ### Phase 2: Backend Services
121
-
122
- **Zeus delegates to Hermes:**
123
- ```
124
- @hermes: Implement backend services for JWT auth
125
-
126
- Create:
127
- 1. JWTService: generate, verify, refresh JWT
128
- 2. AuthService: handle login/logout
129
- 3. Auth endpoints: POST /auth/login, POST /auth/refresh, GET /auth/verify
130
-
131
- TDD: RED → GREEN → REFACTOR
132
- Coverage target: >80%
133
- ```
134
-
135
- **Hermes does (TDD):**
136
- 1. Write failing test for JWT generation (RED)
137
- 2. Write minimal JWT service (GREEN)
138
- 3. Refactor with proper types, error handling (REFACTOR)
139
- 4. Repeat for all endpoints
140
-
141
- **Hermes delivers:** Services + tests, >80% coverage
142
-
143
- **Themis reviews:** Coverage, security (OWASP), performance → APPROVED
144
-
145
- ### ⏸️ PAUSE POINT 2: Phase Review
146
-
147
- ```
148
- Zeus: "Phase 2 complete! Coverage: >80% ✅ Security: OWASP ✅ Tests: passing ✅
149
- Ready to continue to Phase 3?"
150
-
151
- User: "continue"
152
- ```
153
-
154
- ### Phase 3: Frontend Integration
155
-
156
- **Zeus delegates to Aphrodite:**
157
- ```
158
- @aphrodite: Implement frontend for JWT auth
159
-
160
- Create:
161
- 1. LoginForm component
162
- 2. useAuth hook for state management
163
- 3. Protected route wrapper
164
-
165
- TDD: RED → GREEN → REFACTOR
166
- Coverage target: >80%
167
- ```
168
-
169
- **Aphrodite does (TDD):**
170
- 1. Write failing component test (RED)
171
- 2. Write minimal component (GREEN)
172
- 3. Refactor with proper accessibility, error handling (REFACTOR)
173
-
174
- **Aphrodite delivers:** Components + tests, >80% coverage
175
-
176
- **Themis reviews:** Coverage, accessibility, security → APPROVED
177
-
178
- ### ⏸️ PAUSE POINT 2: Phase Review
179
-
180
- ```
181
- Zeus: "Phase 3 complete! Coverage: >80% ✅ Accessibility: ✅ Tests: passing ✅
182
- All phases approved!"
183
- ```
184
-
185
- ---
186
-
187
- ## Step 3: Final Summary
188
-
189
- ```
190
- ✅ JWT Authentication Complete
191
-
192
- 📊 Metrics:
193
- - 3 phases: Database, Backend, Frontend
194
- - >80% coverage across all layers
195
- - Security: OWASP compliant ✅
196
- - All tests passing ✅
197
-
198
- 🚀 Ready to commit
199
- ```
200
-
201
- ---
202
-
203
- ## Step 4: Git Commit
204
-
205
- ### ⏸️ PAUSE POINT 3: Git Commit
206
-
207
- ```
208
- Zeus: "All phases approved! Ready to commit."
209
-
210
- Suggested commit message:
211
- feat: Add JWT authentication with refresh tokens
212
-
213
- - Create User + Token database schema
214
- - Implement JWTService + AuthService
215
- - Add login, refresh, verify endpoints
216
- - Create LoginForm + useAuth hook
217
- - Full TDD: >80% coverage
218
- - Security: OWASP Top 10 compliant
219
-
220
- User: git add -A && git commit -m "..."
221
- ```
222
-
223
- ---
224
-
225
- ## Quick Reference: Workflow Commands
226
-
227
- ```bash
228
- # Step 1: Plan
229
- @athena: Plan [feature description]
230
-
231
- # Step 2: Orchestrate
232
- @zeus: Implement feature using plan
233
-
234
- # Step 3: At pause points
235
- # - Review phase results
236
- # - Approve before proceeding
237
-
238
- # Step 4: Commit
239
- git add -A
240
- git commit -m "feat: ..."
241
-
242
- # Step 5: Deploy
243
- git push origin [branch]
244
- ```
245
-
246
- ---
247
-
248
- ## Troubleshooting
249
-
250
- ### Problem: Phase coverage is <80%
251
- **Solution:** Implementer adds missing test cases, re-runs coverage, Themis re-reviews.
252
-
253
- ### Problem: Security audit found issue
254
- **Solution:** Relevant agent fixes (parameterized queries, input validation), re-audit, Themis approves.
255
-
256
- ### Problem: Frontend accessibility below target
257
- **Solution:** Aphrodite improves ARIA labels, keyboard navigation, re-checks, Themis approves.
258
-
259
- ---
260
-
261
- ## Common Patterns
262
-
263
- ### Pattern 1: Simple Bug Fix (Skip Athena)
264
- ```
265
- Discovery: @apollo: Find bug in authentication
266
- Fix: @hermes: Fix the validation error
267
- Review: @themis: Auto-invoked after fix
268
- Result: Minimal change, minimal risk (~30 min)
269
- ```
270
-
271
- ### Pattern 2: Complex Feature (Full System)
272
- ```
273
- Plan: @athena: Plan architecture
274
- Orchestrate: @zeus: Implement using plan
275
- Result: Complete feature, >80% coverage (1-2 days)
276
- ```
277
-
278
- ### Pattern 3: Database Optimization
279
- ```
280
- Discovery: @apollo: Find N+1 queries
281
- Optimize: @demeter: Add indexes + optimize
282
- Review: @themis: Auto-invoked
283
- Result: 10x faster queries (~2 hours)
284
- ```
285
-
286
- ---
287
-
288
- ## Pro Tips
289
-
290
- 🎯 **Plan First** — Saves 2-3x rework time
291
- 🎯 **Use Pause Points** — You control when to proceed
292
- 🎯 **Trust Themis** — Code review catches issues early
293
- 🎯 **Commit Atomically** — One phase = one commit
294
- 🎯 **Test First** — RED tests before code
295
- 🎯 **Coverage Matters** — <80% = blocked, no exceptions
296
- 🎯 **Security First** — Themis enforces OWASP compliance
297
- 🎯 **Background Dispatch** — Use OpenCode v1.16.2+ background agents to run independent phases in parallel without polling
298
-
299
- ---
300
-
301
- ## Next Steps
302
-
303
- 1. ✅ Read this guide
304
- 2. ✅ Review agent reference in `agent-coordination/SKILL.md`
305
- 3. ✅ Review TDD standards in `tdd-with-agents/SKILL.md`
306
- 4. 🚀 Start your first feature: `@athena: Plan [your idea]`
307
-
308
- ---
309
-
310
- **Philosophy:** Plan → Orchestrate → Review → Commit → Deploy
311
- Every phase has a pause point where YOU control the outcome.