a21466add232d59cdec1604e09d58ca05659a623
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6178be3aa7 |
feat(models): single-source model registry via models.yaml + sync_models.py
.opencode/models/models.yaml is now the ONE file humans edit to assign a model to an agent. tools/sync_models.py regenerates every derived surface — the .opencode/models/*.txt files, opencode.json's `agent` block, and each non-tier agent's .md `model:` frontmatter — so an assignment cannot drift across surfaces. `--check` verifies with no writes and is enforced in CI by test_model_registry_in_sync_with_manifest. Hardened after adversarial review: - Deletes orphan <agent>.txt files left behind when an override is dropped from the manifest. The dispatcher's resolver reads <agent>.txt before default.txt, so a stale file would silently pin the old model. Tier .txt files are left to sync_tier_models.py. - Rejects a manifest key that does not name a real agent (no matching .opencode/agents/<name>.md) instead of silently appending a bogus opencode.json entry and leaving the real agent on the default model. - Validates the regenerated opencode.json BEFORE writing it, so a bad render aborts cleanly instead of corrupting the file on disk. Tier-ladder agents (task-implementor-tier-*) remain governed separately by tiers.yaml + sync_tier_models.py and are passed through untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1eac4ea233 |
refactor(auto-agents): manifest-driven tier-model registry, slot-based naming
Replace the scattered per-agent .txt-file mapping (whose names embedded model-family identity like tier-qwen-med and tier-kimi and went stale the moment a model was swapped) with a single source-of-truth manifest at .opencode/models/tiers.yaml. The four tier slots get model-agnostic slot-based names (tier-min, tier-0, tier-1, tier-2); the model in each slot is configured ONLY in the manifest. Derived artifacts (per-agent .txt files and the mapping table block in tier-dispatcher.md) are now generated by tools/sync_tier_models.py. A drift-detection test in tests/auto_agents/test_tier_model_registry.py fails CI if any derived file diverges from the manifest, if an agent referenced by the manifest lacks an agent file, if the manifest cites a provider not declared in opencode.json, or if opencode.json carries a stale tier-* entry. To swap a model in a slot: edit tiers.yaml -> run python3 tools/sync_tier_models.py -> commit. The runtime dispatcher re-reads the .txt files per cycle (no restart); the static OpenCode config path needs a server restart. Tier rename mapping (escalation_tier integers UNCHANGED): tier-qwen-small -> tier-min (slot -1) tier-qwen-med -> tier-0 (slot 0, default first attempt) tier-qwen-large -> tier-1 (slot 1) tier-kimi -> tier-2 (slot 2) Vestigial tier-* agents removed (declared but never in the active mapping): tier-haiku, tier-sonnet, tier-opus, tier-codex, tier-gpt5-mini, tier-gpt5-nano, tier-o4-mini. estimator-implementation.md now reasons in capability descriptors (cheapest / default / advanced / complex) instead of model-family labels (qwen-small / qwen-med / qwen-large / kimi), so the estimator stays correct across model swaps. The stale "default tier = gpt-5-mini" docstring claim (already drifted to claude-haiku-4-5) is removed. Companion prose updates across every consumer of tier names: - Agent prompts: tier-dispatcher.md, implementation-worker.md, estimator-implementation.md - Skills: implementer-pr-context, implementer-workspace - Python: dispatch_implementer.py, _opencode_worker.py, _pr_context_sentinel.py, implementer_workspace.py, setup_auto_labels.py, _attempt_history.py - Tests: test_worker_permissions.py (parametrize list + byte-identity test now covers 4 slot files instead of 3 family-named files), test_opencode_worker_models.py (synthetic-fixture names updated) - Docs: .opencode/models/README.md, docs/development/models.md, docs/development/agent-system-specification.md, docs/development/auto-agents-tier-2-3-plan.md, docs/development/implementer-in-cycle-escalation-plan.md, docs/development/final-working-harvest-plan.md Validation: 1625 tests pass (+6 net new from the tier-registry test file), 3 skipped. python3 tools/sync_tier_models.py --check exits 0. local_ci_gate.sh --gate lint PASS. Files: 9 added, 22 deleted, 18 modified. The drift-detection test ran green on every step of the refactor, catching one out-of-sync .txt file before commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
132a5a2269 |
feat(auto-agents): centralise model registry under .opencode/models with session-create model stamp
Every agent's model assignment now lives in a single-line text file at
.opencode/models/<name>.txt; default.txt is the 27-agent catch-all.
opencode.json's agent.<name>.model uses
{file:./.opencode/models/<name>.txt} interpolation, and
tools/_opencode_worker.py reads the same files at session-create to
stamp the resolved model on the session record (observability + drift
sentinel; OpenCode does NOT propagate session-level model to
prompt_async — schema for that is undocumented and deferred to Stage
2). 39 .md frontmatter `model:` lines stripped; the two intentional
inheritors (task-implementor, agent-evolution-pool-supervisor) keep
their model-less frontmatter.
Operator workflow for swapping a model is now: edit
.opencode/models/<role>.txt, restart OpenCode so opencode.json's
{file:...} re-resolves, run the dispatcher. Live-swap without restart
was attempted (override on prompt_async); OpenCode 0.x silently
dropped those requests (200 OK, no assistant message) and the
prompt_async override was reverted. The session-create override
remains for observability + drift detection.
End-to-end validation (2026-05-10): dispatch_review.py on PR #25 with
default.txt=openai/gpt-5-mini produced a clean REQUEST_CHANGES review
in 26 s for ~$0.016; dispatch_implementer.py on PR #30 with
tier-qwen-* files remapped to openai/{gpt-5-nano, gpt-5-mini,
gpt-5-codex} ran the full implementation-worker → tier-dispatcher →
estimator-implementation → tier-qwen-med → task-implementor →
git-isolator-util chain in 16 min with model=gpt-5-mini end-to-end.
Also documents the printenv VAR form as the only allowed env-read in
implementation-worker.md and task-implementor.md (live testing
showed the worker burning 2–4 turns on permission-denied
trial-and-error trying printf and echo variants).
Tests: 21 in tests/auto_agents/test_opencode_worker_models.py
(resolver semantics with caplog assertions on every malformed-input
path; session-create body shape; prompt_async body never carries
model; three repo-level invariants — every {file:...} reference
resolves, every .md is wired or in the inheritor allowlist, no .md
has a model: frontmatter). 1027 auto_agents tests pass / 3 skipped.
Note: .opencode/models/default.txt and the three tier-qwen-*.txt
files are committed with their OpenAI swaps in place (gpt-5-mini,
gpt-5-nano, gpt-5-mini, gpt-5-codex respectively) because the
CleverThis HuggingFace endpoints are paused. Revert with `git diff
HEAD~1 -- .opencode/models/*.txt | git apply -R` if/when they come
back.
Co-authored-by: Cursor <cursoragent@cursor.com>
|