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.
- package/.pantheon/code-mode/README.md +4 -2
- package/.pantheon/code-mode/checkpoint_session.py +138 -102
- package/.pantheon/code-mode/compress-inline.py +102 -57
- package/.pantheon/code-mode/manifest.json +2 -8
- package/CHANGELOG.md +22 -0
- package/README.md +86 -52
- package/README.pt-BR.md +63 -43
- package/commands/pantheon-optimize.md +2 -2
- package/package.json +13 -1
- package/plugin.json +1 -1
- package/pyproject.toml +8 -15
- package/scripts/build-agents-md.mjs +2 -2
- package/scripts/check-plugin-v2-coverage.mjs +213 -0
- package/scripts/ci-validate-yaml.py +7 -5
- package/scripts/code_mode_server.py +116 -24
- package/scripts/doctor.mjs +85 -28
- package/scripts/install/cli-ui.mjs +1 -1
- package/scripts/install/config-migration.mjs +2 -2
- package/scripts/install/health-check.mjs +6 -19
- package/scripts/install/interactive.mjs +6 -6
- package/scripts/install/migrate.mjs +1 -1
- package/scripts/install/state.mjs +27 -2
- package/scripts/mcp_persistence_server.py +390 -76
- package/scripts/memory_mcp_server.py +370 -196
- package/scripts/postinstall.mjs +0 -7
- package/scripts/probe-context-rehydrate.mjs +28 -11
- package/scripts/prune.mjs +2 -2
- package/scripts/sync-tui.mjs +11 -5
- package/scripts/test-opencode-v2-sandbox.sh +1759 -0
- package/scripts/validate-routing.mjs +40 -0
- package/skills-lock.json +9 -10
- package/src/agents/mnemosyne.md +15 -16
- package/src/agents/zeus.md +1 -2
- package/src/mcp/code_mode_server.py +116 -24
- package/src/mcp/mcp_codemap_module.py +559 -129
- package/src/mcp/mcp_persistence_server.py +390 -76
- package/src/mcp/memory_mcp_server.py +371 -248
- package/src/mcp/pantheon_vision_server.py +136 -24
- package/src/mcp/requirements-mcp.txt +5 -3
- package/src/mcp/requirements-vision.txt +2 -0
- package/src/pantheon/model-command.ts +18 -7
- package/src/pantheon/todo-enforcer.ts +1 -1
- package/src/pantheon/vision.ts +1 -1
- package/src/plugin-v2.ts +134 -104
- package/src/plugins/tui/dist/tui.js +1 -1
- package/src/plugins/tui/package-lock.json +20 -20
- package/src/plugins/tui/package.json +12 -12
- package/src/routing.yml +0 -1
- package/src/skills/README.md +31 -36
- package/src/skills/auto-continue/SKILL.md +25 -75
- package/.pantheon/code-mode/eval-llm-judge.py +0 -255
- package/.pantheon/code-mode/eval-monte-carlo.py +0 -368
- package/.pantheon/code-mode/eval-run.py +0 -197
- package/.pantheon/code-mode/eval-static.py +0 -321
- package/.pantheon/code-mode/session-end-save.py +0 -186
- package/.pantheon/code-mode/session-end-save.sh +0 -18
- package/scripts/recover-zenodo-deposition.mjs +0 -146
- package/scripts/test-opencode-v1-v2-sandbox.sh +0 -862
- package/scripts/validate-zenodo-release.mjs +0 -154
- package/scripts/zenodo-artifact.mjs +0 -21
- package/scripts/zenodo-release-state.mjs +0 -53
- 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.
|