pantheon-opencode 1.2.0 → 1.2.2
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/AGENTS.md +9 -0
- package/README.md +112 -15
- package/bin/pantheon-init.mjs +93 -0
- package/commands/pantheon-vision.md +67 -0
- package/opencode.json +14 -10
- package/package.json +20 -4
- package/scripts/_pantheon_paths.py +0 -2
- package/scripts/changelog-extract.mjs +112 -0
- package/scripts/doctor.mjs +307 -15
- package/scripts/hooks/audit-imports.sh +43 -0
- package/scripts/hooks/format-multi-language.sh +96 -0
- package/scripts/hooks/log-session-start.sh +24 -0
- package/scripts/hooks/on-subagent-delegation-start.sh +91 -0
- package/scripts/hooks/on-subagent-delegation-stop.sh +37 -0
- package/scripts/hooks/run-type-check.sh +21 -0
- package/scripts/hooks/scan-secrets.sh +55 -0
- package/scripts/hooks/validate-post-conditions.sh +21 -0
- package/scripts/hooks/validate-talos-scope.sh +43 -0
- package/scripts/hooks/validate-tool-safety.sh +46 -0
- package/scripts/install/health-check.mjs +101 -1
- package/scripts/install/model-picker.mjs +118 -0
- package/scripts/install/opencode.mjs +155 -43
- package/scripts/install/plugin.mjs +4 -2
- package/scripts/install/venv.mjs +25 -2
- package/scripts/install-mcp.mjs +170 -37
- package/scripts/mcp_persistence_server.py +2 -1
- package/scripts/prune.mjs +359 -0
- package/scripts/secret-scan.mjs +88 -0
- package/scripts/uninstall.mjs +3 -3
- package/scripts/validate-routing.mjs +15 -0
- package/scripts/version-check.mjs +146 -0
- package/scripts/versioning.mjs +13 -14
- package/src/agents/hermes.md +2 -2
- package/src/agents/mnemosyne.md +1 -1
- package/src/agents/zeus.md +1 -1
- package/src/mcp/_pantheon_paths.py +0 -2
- package/src/mcp/install-mcp.mjs +6 -913
- package/src/mcp/mcp_persistence_server.py +2 -1
- package/src/mcp/pantheon_vision_server.py +495 -0
- package/src/mcp/requirements-mcp.txt +8 -5
- package/src/mcp/requirements-vision.txt +3 -0
- package/src/pantheon/auto-wake.ts +91 -0
- package/src/pantheon/background-job-board.ts +568 -0
- package/src/pantheon/file-persistence.ts +95 -0
- package/src/pantheon/presets.d.mts +108 -0
- package/src/pantheon/presets.mjs +554 -0
- package/src/pantheon/vision.ts +1437 -0
- package/src/plugin.ts +69 -25
- package/src/plugins/hook-runner.ts +186 -0
- package/src/plugins/pantheon-hooks.ts +153 -0
- package/src/plugins/tui/dist/tui.d.ts +1 -1
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +812 -223
- package/src/plugins/tui/dist/tui.js.map +1 -1
- package/src/plugins/tui/dist/tui.tsx +881 -121
- package/src/plugins/tui/package.json +3 -3
- package/src/plugins/tui/src/index.tsx +881 -121
- package/src/routing.yml +148 -0
- package/src/skills/context-compression/SKILL.md +1 -1
- package/src/skills/loop-engineering/SKILL.md +1 -1
- package/src/skills/orchestration-workflow/SKILL.md +11 -11
- package/scripts/scrub_secrets.py +0 -281
- package/src/mcp/requirements-mcp-core.txt +0 -5
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/** Scan versionable files without printing secret values. */
|
|
4
|
+
|
|
5
|
+
import { execFileSync } from 'node:child_process'
|
|
6
|
+
import { readFileSync } from 'node:fs'
|
|
7
|
+
import { resolve } from 'node:path'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
|
|
10
|
+
const bifrostHeader = ['x', '-bf-', 'vk'].join('')
|
|
11
|
+
const bifrostTokenPrefix = ['sk', '-bf-'].join('')
|
|
12
|
+
const apiKeyName = ['api', 'Key'].join('')
|
|
13
|
+
const authorizationName = ['Author', 'ization'].join('')
|
|
14
|
+
|
|
15
|
+
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
16
|
+
|
|
17
|
+
// Files that may reference credential PATTERN NAMES (not values): gitleaks
|
|
18
|
+
// config, security policy, scan tooling and its fixtures. Keep in sync with
|
|
19
|
+
// the [allowlist] paths in .gitleaks.toml.
|
|
20
|
+
export const allowlistedFiles = new Set([
|
|
21
|
+
'.gitleaks.toml',
|
|
22
|
+
'.gitleaksignore',
|
|
23
|
+
'SECURITY.md',
|
|
24
|
+
'scripts/secret-scan.mjs',
|
|
25
|
+
'tests/test_secret_scan.mjs',
|
|
26
|
+
])
|
|
27
|
+
|
|
28
|
+
const patterns = [
|
|
29
|
+
{ label: 'Bifrost credential header', regex: new RegExp(escapeRegExp(bifrostHeader), 'i') },
|
|
30
|
+
{
|
|
31
|
+
label: 'Bifrost credential value',
|
|
32
|
+
regex: new RegExp(`${escapeRegExp(bifrostTokenPrefix)}[A-Za-z0-9_-]{8,}`, 'i'),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'literal API key value',
|
|
36
|
+
regex: new RegExp(
|
|
37
|
+
`["']${escapeRegExp(apiKeyName)}["']\\s*[:=]\\s*["'](?!\\$\\{|process\\.env|os\\.getenv|env:)[^"']{12,}["']`,
|
|
38
|
+
'i',
|
|
39
|
+
),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
label: 'literal Authorization bearer value',
|
|
43
|
+
regex: new RegExp(
|
|
44
|
+
`["']${escapeRegExp(authorizationName)}["']\\s*[:=]\\s*["']Bearer\\s+[A-Za-z0-9._-]{12,}["']`,
|
|
45
|
+
'i',
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
export function scanText(text, file = '<text>') {
|
|
51
|
+
return patterns.filter(({ regex }) => regex.test(text)).map(({ label }) => ({ file, label }))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function versionableFiles() {
|
|
55
|
+
return execFileSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard'], {
|
|
56
|
+
encoding: 'buffer',
|
|
57
|
+
})
|
|
58
|
+
.toString()
|
|
59
|
+
.split('\0')
|
|
60
|
+
.filter(Boolean)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function scanVersionableFiles() {
|
|
64
|
+
const findings = []
|
|
65
|
+
for (const file of versionableFiles()) {
|
|
66
|
+
if (allowlistedFiles.has(file)) continue
|
|
67
|
+
let text
|
|
68
|
+
try {
|
|
69
|
+
const content = readFileSync(file)
|
|
70
|
+
if (content.includes(0)) continue
|
|
71
|
+
text = content.toString('utf8')
|
|
72
|
+
} catch {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
findings.push(...scanText(text, file))
|
|
76
|
+
}
|
|
77
|
+
return findings
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
|
|
81
|
+
const findings = scanVersionableFiles()
|
|
82
|
+
if (findings.length > 0) {
|
|
83
|
+
for (const finding of findings) console.error(`[SECRET SCAN] ${finding.file}: ${finding.label}`)
|
|
84
|
+
process.exitCode = 1
|
|
85
|
+
} else {
|
|
86
|
+
console.log('Secret scan passed: no versionable Bifrost/API credentials detected.')
|
|
87
|
+
}
|
|
88
|
+
}
|
package/scripts/uninstall.mjs
CHANGED
|
@@ -18,6 +18,7 @@ import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
|
|
18
18
|
import { dirname, join } from 'node:path'
|
|
19
19
|
import { fileURLToPath } from 'node:url'
|
|
20
20
|
import yaml from 'js-yaml'
|
|
21
|
+
import { validatePresetDefs } from '../src/pantheon/presets.mjs'
|
|
21
22
|
|
|
22
23
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
23
24
|
const ROOT = join(__dirname, '..')
|
|
@@ -150,6 +151,20 @@ for (const [name, info] of Object.entries(routing.agents || {})) {
|
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
|
|
154
|
+
// F. Model preset validation
|
|
155
|
+
const presetDefs = routing.presets || {}
|
|
156
|
+
console.log(`\n Model presets: ${Object.keys(presetDefs).length} defined`)
|
|
157
|
+
|
|
158
|
+
const presetKnownAgents = routingAgents.filter((a) => a !== 'zen' && a !== 'zeus_copilot')
|
|
159
|
+
const presetValidation = validatePresetDefs(presetDefs, { agents: presetKnownAgents })
|
|
160
|
+
for (const err of presetValidation.errors) {
|
|
161
|
+
check(false, `Preset ${err}`)
|
|
162
|
+
}
|
|
163
|
+
for (const w of presetValidation.warnings) {
|
|
164
|
+
warn(`Preset ${w}`)
|
|
165
|
+
}
|
|
166
|
+
console.log(` Presets defined: ${Object.keys(presetDefs).length}`)
|
|
167
|
+
|
|
153
168
|
// Summary
|
|
154
169
|
console.log(`\n${'='.repeat(50)}`)
|
|
155
170
|
const status = failures === 0 ? '✅ PASSED' : `❌ FAILED (${failures}/${checks} checks failed)`
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* version-check.mjs — Single source of truth enforcement
|
|
4
|
+
*
|
|
5
|
+
* package.json is the SOURCE OF TRUTH for the Pantheon version.
|
|
6
|
+
* Every other manifest (pyproject.toml, plugin.json, src/plugins/tui/package.json)
|
|
7
|
+
* MUST carry the same version. This script:
|
|
8
|
+
*
|
|
9
|
+
* - compares every manifest against package.json and prints a divergence
|
|
10
|
+
* table when they differ (exit code 1),
|
|
11
|
+
* - with --fix, rewrites each divergent manifest to the package.json version.
|
|
12
|
+
*
|
|
13
|
+
* Mirrors the MANIFEST_FILES list in scripts/versioning.mjs so `apply`
|
|
14
|
+
* and `check` can never drift apart.
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* node scripts/version-check.mjs # verify (exit 0 = in sync)
|
|
18
|
+
* node scripts/version-check.mjs --fix # sync all manifests
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
22
|
+
import { join } from 'node:path'
|
|
23
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
24
|
+
|
|
25
|
+
/** Same set of manifests as versioning.mjs (minus package.json itself). */
|
|
26
|
+
export const MANIFESTS = [
|
|
27
|
+
{ name: 'pyproject.toml', file: 'pyproject.toml', kind: 'toml' },
|
|
28
|
+
{ name: 'plugin.json', file: 'plugin.json', kind: 'json' },
|
|
29
|
+
{ name: 'src/plugins/tui/package.json', file: join('src', 'plugins', 'tui', 'package.json'), kind: 'json' },
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
function readTomlVersion(filePath) {
|
|
33
|
+
const text = readFileSync(filePath, 'utf-8')
|
|
34
|
+
const match = text.match(/^version\s*=\s*"([^"]+)"/m)
|
|
35
|
+
if (!match) throw new Error(`no version field in ${filePath}`)
|
|
36
|
+
return match[1]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readJsonVersion(filePath) {
|
|
40
|
+
return JSON.parse(readFileSync(filePath, 'utf-8')).version
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function readManifestVersion(filePath, kind) {
|
|
44
|
+
try {
|
|
45
|
+
return kind === 'toml' ? readTomlVersion(filePath) : readJsonVersion(filePath)
|
|
46
|
+
} catch {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function writeManifestVersion(filePath, kind, version) {
|
|
52
|
+
if (kind === 'toml') {
|
|
53
|
+
const text = readFileSync(filePath, 'utf-8')
|
|
54
|
+
const updated = text.replace(/^(version\s*=\s*")[^"]+(")/m, `$1${version}$2`)
|
|
55
|
+
writeFileSync(filePath, updated)
|
|
56
|
+
} else {
|
|
57
|
+
const content = JSON.parse(readFileSync(filePath, 'utf-8'))
|
|
58
|
+
content.version = version
|
|
59
|
+
writeFileSync(filePath, `${JSON.stringify(content, null, 2)}\n`)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Compare every manifest version against package.json (source of truth).
|
|
65
|
+
*
|
|
66
|
+
* @param {string} root - repository root containing package.json + manifests
|
|
67
|
+
* @returns {{source: string, manifests: Array<{name: string, version: string|null, ok: boolean}>, ok: boolean}}
|
|
68
|
+
* - source: version read from package.json
|
|
69
|
+
* - manifests: per-manifest {name, version (null when unreadable), ok}
|
|
70
|
+
* - ok: true when every manifest matches the source version
|
|
71
|
+
*/
|
|
72
|
+
export function compareVersions(root) {
|
|
73
|
+
const source = JSON.parse(readFileSync(join(root, 'package.json'), 'utf-8')).version
|
|
74
|
+
const manifests = MANIFESTS.map(({ name, file, kind }) => {
|
|
75
|
+
const version = readManifestVersion(join(root, file), kind)
|
|
76
|
+
return { name, version, ok: version === source }
|
|
77
|
+
})
|
|
78
|
+
return { source, manifests, ok: manifests.every((m) => m.ok) }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Rewrite every divergent manifest to the package.json version.
|
|
83
|
+
*
|
|
84
|
+
* @param {string} root - repository root
|
|
85
|
+
* @returns {number} count of manifests rewritten
|
|
86
|
+
*/
|
|
87
|
+
export function syncToSource(root) {
|
|
88
|
+
const { source, manifests } = compareVersions(root)
|
|
89
|
+
let changed = 0
|
|
90
|
+
for (const manifest of manifests) {
|
|
91
|
+
if (manifest.ok) continue
|
|
92
|
+
const def = MANIFESTS.find((m) => m.name === manifest.name)
|
|
93
|
+
writeManifestVersion(join(root, def.file), def.kind, source)
|
|
94
|
+
changed += 1
|
|
95
|
+
}
|
|
96
|
+
return changed
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function printDivergenceTable(result) {
|
|
100
|
+
const rows = [
|
|
101
|
+
['manifest', 'version', 'status'],
|
|
102
|
+
...result.manifests.map((m) => [m.name, m.version ?? 'MISSING', m.ok ? 'ok' : 'DIVERGENT']),
|
|
103
|
+
]
|
|
104
|
+
const widths = rows[0].map((_, i) => Math.max(...rows.map((row) => row[i].length)))
|
|
105
|
+
console.log(`Source of truth: package.json → v${result.source}\n`)
|
|
106
|
+
for (const row of rows) {
|
|
107
|
+
console.log(row.map((cell, i) => cell.padEnd(widths[i])).join(' '))
|
|
108
|
+
}
|
|
109
|
+
console.log('')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const isDirectRun =
|
|
113
|
+
process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href
|
|
114
|
+
|
|
115
|
+
if (isDirectRun) {
|
|
116
|
+
// npm scripts run from the package root, so the working directory is the
|
|
117
|
+
// repository root to check. Explicit cwd keeps the CLI testable.
|
|
118
|
+
const root = process.cwd()
|
|
119
|
+
const fix = process.argv.includes('--fix')
|
|
120
|
+
let result
|
|
121
|
+
try {
|
|
122
|
+
result = compareVersions(root)
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error(`version-check: cannot read package.json — ${error.message}`)
|
|
125
|
+
process.exit(1)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (result.ok) {
|
|
129
|
+
console.log(`✓ All manifests match package.json v${result.source}`)
|
|
130
|
+
process.exit(0)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
printDivergenceTable(result)
|
|
134
|
+
if (fix) {
|
|
135
|
+
const changed = syncToSource(root)
|
|
136
|
+
const after = compareVersions(root)
|
|
137
|
+
if (after.ok) {
|
|
138
|
+
console.log(`✓ Synced ${changed} manifest(s) to v${after.source}`)
|
|
139
|
+
process.exit(0)
|
|
140
|
+
}
|
|
141
|
+
console.error(`version-check: sync incomplete — ${after.manifests.filter((m) => !m.ok).length} manifest(s) still divergent`)
|
|
142
|
+
process.exit(1)
|
|
143
|
+
}
|
|
144
|
+
console.error('version-check: manifests out of sync (run with --fix to sync)')
|
|
145
|
+
process.exit(1)
|
|
146
|
+
}
|
package/scripts/versioning.mjs
CHANGED
|
@@ -29,7 +29,7 @@ const MANIFEST_FILES = [
|
|
|
29
29
|
'pyproject.toml',
|
|
30
30
|
'package.json',
|
|
31
31
|
'plugin.json',
|
|
32
|
-
'
|
|
32
|
+
'src/plugins/tui/package.json',
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
const CHANGELOG_PATH = join(ROOT, 'CHANGELOG.md')
|
|
@@ -47,8 +47,11 @@ function run(cmd) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function getLatestTag() {
|
|
50
|
-
//
|
|
51
|
-
|
|
50
|
+
// Stable tags only: strict vX.Y.Z with NO pre-release suffix.
|
|
51
|
+
// The loose glob `v[0-9]*.[0-9]*.[0-9]*` ALSO matches v1.2.0-beta.9.*
|
|
52
|
+
// (the trailing `*` swallows the -beta suffix), which would poison the
|
|
53
|
+
// version gate — so filter strictly before sorting.
|
|
54
|
+
const tag = run("git tag -l 'v*' | grep -E '^v[0-9]+\\.[0-9]+\\.[0-9]+$' | sort -V | tail -1")
|
|
52
55
|
return tag || 'v0.0.0'
|
|
53
56
|
}
|
|
54
57
|
|
|
@@ -207,13 +210,15 @@ switch (command) {
|
|
|
207
210
|
const latestVer = latestTag.replace(/^v/, '')
|
|
208
211
|
|
|
209
212
|
// If package.json is already ahead of the latest tag, someone bumped
|
|
210
|
-
// without tagging — warn and use the current version as-is.
|
|
213
|
+
// without tagging — warn and use the current version as-is. Tags are
|
|
214
|
+
// workflow-owned, so there is nothing to create here.
|
|
211
215
|
if (current !== latestVer) {
|
|
212
216
|
console.log(`⚠ package.json (${current}) already ahead of latest tag (${latestTag}).`)
|
|
213
217
|
console.log(` Syncing all manifests to ${current} and promoting CHANGELOG.`)
|
|
214
218
|
updateManifests(current)
|
|
215
219
|
const date = new Date().toISOString().slice(0, 10)
|
|
216
220
|
promoteUnreleased(current, date)
|
|
221
|
+
console.log(`Tag v${current} will be created by the release workflow after merge to main.`)
|
|
217
222
|
break
|
|
218
223
|
}
|
|
219
224
|
|
|
@@ -226,16 +231,10 @@ switch (command) {
|
|
|
226
231
|
promoteUnreleased(newVersion, date)
|
|
227
232
|
console.log(`\nDone. Commit with: git add -A && git commit -m "chore(release): v${newVersion}"`)
|
|
228
233
|
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
console.log(`Tag ${tag} created locally. Push: git push origin ${tag}`)
|
|
234
|
-
console.log(`Auto-release will trigger on main after merge.`)
|
|
235
|
-
} catch (e) {
|
|
236
|
-
console.warn(`Tag creation failed: ${e.message}`)
|
|
237
|
-
console.log('Create manually: git tag -a v' + newVersion + ' -m "chore(release): v' + newVersion + '"')
|
|
238
|
-
}
|
|
234
|
+
// Tags are owned by the release workflow — never create them locally.
|
|
235
|
+
// A local tag on a pre-merge commit drifts from the merged main state
|
|
236
|
+
// (the untagged-v1.2.1 root cause) and would desync the version gate.
|
|
237
|
+
console.log(`Tag v${newVersion} will be created by the release workflow after merge to main.`)
|
|
239
238
|
break
|
|
240
239
|
}
|
|
241
240
|
|
package/src/agents/hermes.md
CHANGED
|
@@ -50,7 +50,7 @@ permission:
|
|
|
50
50
|
|
|
51
51
|
You are the **BACKEND TASK IMPLEMENTER** (Hermes) called by Zeus to implement FastAPI endpoints, services, and routers. Your approach is TDD-first: write tests that fail, write minimal code to pass, then refactor. You focus purely on implementation following provided plans.
|
|
52
52
|
|
|
53
|
-
## Core Capabilities
|
|
53
|
+
## Core Capabilities
|
|
54
54
|
|
|
55
55
|
### 1. **Test-Driven Development**
|
|
56
56
|
See `skill: tdd-with-agents` for the full TDD cycle.
|
|
@@ -67,7 +67,7 @@ See `skill: tdd-with-agents` for the full TDD cycle.
|
|
|
67
67
|
- Return clear, structured results
|
|
68
68
|
- Report readiness for next phase
|
|
69
69
|
|
|
70
|
-
### 4. **Parallel Execution Mode**
|
|
70
|
+
### 4. **Parallel Execution Mode**
|
|
71
71
|
- **You can run simultaneously with @aphrodite and @demeter** when scopes don't overlap
|
|
72
72
|
- Your scope: backend files only (routers, services, tests)
|
|
73
73
|
- Signal clearly when your phase is done so Themis can review
|
package/src/agents/mnemosyne.md
CHANGED
|
@@ -98,7 +98,7 @@ Mnemosyne executes the expanded compression pipeline. When Zeus delegates compre
|
|
|
98
98
|
|
|
99
99
|
5. **Archive IMPL/REVIEW**: Append to `02-progress-log.md` (same as Level 1)
|
|
100
100
|
|
|
101
|
-
6. **Update Cross-References**:
|
|
101
|
+
6. **Update Cross-References**:
|
|
102
102
|
- Append new entries to `_xref/index.md`
|
|
103
103
|
- Increment `_xref/_next_id.json`
|
|
104
104
|
|
package/src/agents/zeus.md
CHANGED
|
@@ -81,7 +81,7 @@ Antes de usar a arvore de roteamento, consulte o memory:
|
|
|
81
81
|
|
|
82
82
|
```
|
|
83
83
|
memory_search(task_prompt, top_k=2)
|
|
84
|
-
→ score > 0.85?
|
|
84
|
+
→ score > 0.85?
|
|
85
85
|
SIM → usa resultado cacheado (agent, background, pattern)
|
|
86
86
|
NAO → aplica arvore de roteamento + memory_store() pra proxima vez
|
|
87
87
|
```
|