Skip to content

fix(tests): fix version assertion and ask-user TS type error - #65

Closed
ldangelo wants to merge 8 commits into
mainfrom
fix/ci-test-failures
Closed

fix(tests): fix version assertion and ask-user TS type error#65
ldangelo wants to merge 8 commits into
mainfrom
fix/ci-test-failures

Conversation

@ldangelo

Copy link
Copy Markdown
Contributor

Summary

  • Update version assertion in packages/development/tests/auto-team-trd-parser.test.js from 2.12.0 to 2.13.0 to match the current implement-trd-beads.yaml metadata version
  • Fix TS2322 type error in packages/pi/extensions/ask-user.ts line 30 by replacing the JSON Schema wrapper object ({ type: 'object', properties: {...}, required: [...] }) with the flat Record<string, { type: string; description: string }> shape required by the ExtensionAPI.parameters interface

Root Cause

Failure 1: implement-trd-beads.yaml was bumped to 2.13.0 without updating the version assertion in the corresponding test.

Failure 2: ask-user.ts used a JSON Schema-style parameters object with a type: 'object' wrapper. The ExtensionAPI interface and the test both expect a flat map of parameter names to { type, description } descriptors.

Test plan

  • Verify auto-team-trd-parser.test.js passes with the updated 2.13.0 assertion
  • Verify ask-user.test.ts passes with capturedConfig.parameters.question.type === 'string' resolving correctly
  • Confirm no other tests regress

🤖 Generated with Claude Code

ldangelo and others added 8 commits May 27, 2026 14:06
…ases

Adds PRD and TRD for replacing opus/sonnet/haiku aliases with high/medium/low
tier aliases backed by a project-level .claude/ensemble-model-config.json file.
Includes /ensemble:map-model wizard and /ensemble:migrate-model-config commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… schema, config-loader, model-resolver

- Add packages/core/lib/known-model-ids.js: frozen KNOWN_MODEL_IDS array (single source of truth)
- Add schemas/ensemble-model-config-schema.json: JSON Schema draft-07 for .claude/ensemble-model-config.json
- Rewrite packages/core/lib/config-loader.js: findProjectRoot, getProjectConfigPath, getDefaultConfig (tiers: high/medium/low), validateConfig (rejects legacy opus/sonnet/haiku keys), loadConfig (project-local file), checkLegacyXdgFile (one-time migration warning), emitFirstRunHint (first-run sentinel)
- Rewrite packages/core/lib/model-resolver.js: PreflightError, preflightValidate, resolveModel, selectModel (ENSEMBLE_MODEL_OVERRIDE must be tier alias; legacy aliases and raw model IDs rejected)
- Update packages/core/lib/index.js: export new tier-based APIs alongside existing exports
- Add/update all tests: known-model-ids, schema, config-loader (incl. TRD-006 first-run hint), model-resolver, usage-logger (self-contained config), integration suite
- Close beads: cow2, aecg, wkad, 22ic, 7xe6, 0ez5, 6bd2, onms, 0cez, ropv, u4ir, s2z9

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…migration, YAML migration, agent tier assignments

- Update command-yaml-schema.json model enum: opus/sonnet/haiku → high/medium/low
- Add optional model field to agent-yaml-schema.json metadata properties
- Migrate 7 command YAMLs: opus → high (configure-team, create-trd-foreman, create-trd, refine-trd, refine-prd, feature, create-prd)
- Migrate 11 command YAMLs: sonnet → medium (discover-standards, inject-standards, analyze-requirements, beads-build, beads-plan, fix-issue, implement-bead, implement-trd, requirement-status, implement-trd-beads, validate-requirements)
- Migrate inline model refs in fix-issue.yaml: haiku → low, sonnet → medium
- Add model: high to 9 high-tier agent YAMLs (ensemble-orchestrator, tech-lead-orchestrator, product-management-orchestrator, qa-orchestrator, infrastructure-orchestrator, code-reviewer, deep-debugger, agent-meta-engineer, release-agent)
- Add model: medium to 15 medium-tier agent YAMLs (backend-developer, frontend-developer, infrastructure-developer, documentation-specialist, api-documentation-specialist, postgresql-specialist, helm-chart-specialist, build-orchestrator, deployment-orchestrator, playwright-tester, test-runner, github-specialist, git-workflow, manager-dashboard-agent, general-purpose)
- Add model: low to 3 low-tier agent YAMLs (file-creator, context-fetcher, directory-monitor)
- Update 18 generated .md frontmatter files to match YAML sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…igrator, command definitions

- Add map-model-wizard.js with runWizard (TTY interactive), runOneShotUpdate (non-interactive), and writeConfigAtomic helper
- Add legacy-config-migrator.js with findLegacyConfig, migrateLegacyConfig (opus→high, sonnet→medium, haiku→low mapping, commandOverrides/costTracking warnings)
- Add map-model.yaml and migrate-model-config.yaml command definitions with generated .md files
- Add 22 tests covering writeConfigAtomic, runOneShotUpdate, runWizard TTY detection, findLegacyConfig, and migrateLegacyConfig edge cases
- BYPASS_COMMANDS in config-loader.js already included both map-model and migrate-model-config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ELOG, README, usage-logger cleanup

- TRD-019: Add scripts/lint-model-ids.js — scans all command/agent YAMLs, validates model: values against KNOWN_MODEL_IDS + tier aliases, exits 0/1
- TRD-019-TEST: Add scripts/tests/lint-model-ids.test.js — unit tests for extractModelValue and integration test for exit codes
- TRD-020: Add lint:model-ids script to root package.json; integrate into validate chain
- TRD-020-TEST: Smoke test confirmed — 58 files scanned, exit 0 on clean codebase
- TRD-021: Add [5.0.0] breaking-change entry to packages/core/CHANGELOG.md
- TRD-022: Add "Model Tier Configuration" section to root README.md
- TRD-023: Update usage-logger.js — hardcoded XDG log path, remove costTracking guard, MODEL_PRICING updated to current model IDs
- TRD-023-TEST: Rewrite usage-logger.test.js for new API (always-log, new model IDs, new tier aliases)
- All TRD-001 through TRD-023-TEST checkboxes marked complete in TRD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…loper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update version assertion in auto-team-trd-parser.test.js from 2.12.0 to 2.13.0 to
match the current implement-trd-beads.yaml metadata version. Fix TS2322 type error in
ask-user.ts by replacing the JSON Schema object structure with the flat Record<string,
{ type; description }> shape required by ExtensionAPI.parameters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude

claude Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Code Review

Overview

The PR title says "fix version assertion and ask-user TS type error" and the description lists only two small bug fixes, but the actual diff is 99 files, +4 308 / -766 lines — it implements an entirely new Tiered Model Aliases feature (PRD/TRD-2026-021). The two stated fixes are included, but they are minor relative to the bulk of this PR. Reviewers should be aware of the true scope before approving.


🔴 Critical

1. Runtime state files committed to git (.beads/)

.beads/dolt-server.pid and .beads/dolt-server.port are machine-specific runtime state that change every time the Beads server restarts. These will create noisy, meaningless diffs on every developer's machine. .gitignore currently lists .beads.bd/ but not .beads/ itself. Add to .gitignore:

.beads/dolt-server.pid
.beads/dolt-server.port

.beads/issues.jsonl and .beads/.local_version changes may be intentional, but the PID/port files definitely should not be tracked.

2. BYPASS_COMMANDS namespace mismatch — map-model self-blocks

In packages/core/lib/config-loader.js:

const BYPASS_COMMANDS = ['map-model', 'migrate-model-config'];

In packages/core/lib/model-resolver.js:

function preflightValidate(config, commandName) {
  if (BYPASS_COMMANDS.includes(commandName)) { return; }
  ...
}

But the command YAML declares name: ensemble:map-model. If selectModel is called with the full namespaced name (as it should be from metadata), the bypass never fires. A user with an invalid config (e.g., a model ID not in KNOWN_MODEL_IDS) who runs /ensemble:map-model to fix it will get a PreflightError blocking the very command they need to repair their config. The fix is either to include the namespaced forms in BYPASS_COMMANDS or to strip the prefix before checking:

const BYPASS_COMMANDS = ['map-model', 'migrate-model-config', 'ensemble:map-model', 'ensemble:migrate-model-config'];

🟡 High

3. selectModel() is a breaking API change with no mention in PR description

model-resolver.js completely rewrites selectModel(command, config, options) to selectModel(commandName, explicitTier, startDir). The functions extractModelPreference, getModelAlias, and resolveModelAlias are also removed from exports. Any callers (internal or external plugins) depending on the old signature will silently break at runtime. This deserves explicit mention in the PR description and a search for callers.

4. Test duplicates the function it's testing

scripts/tests/lint-model-ids.test.js re-implements extractModelValue directly because lint-model-ids.js calls main() on load and can't be require()'d cleanly:

// --- Replicated helpers (must stay in sync with lint-model-ids.js) ---
function extractModelValue(yamlContent) { ... }

The comment "must stay in sync" is a maintenance smell. The fix is to export helpers from the script using a guard:

// in lint-model-ids.js
if (require.main === module) { main(); }
module.exports = { extractModelValue, findYamlFiles, collectYamlFiles };

This lets tests import the real functions instead of duplicating them.


🟠 Medium

5. ensemble-model-config-schema.json inconsistent strictness

"tiers": { "additionalProperties": false },  // strict
...
"additionalProperties": true  // root: permissive

A typo like "extarKnownModelIds" at the root level would be silently accepted. Consider "additionalProperties": false at the root, or at minimum list extraKnownModelIds as an "unevaluatedProperties": false guard.

6. legacy-config-migrator.js imports writeConfigAtomic from map-model-wizard.js

The migrator conceptually has no dependency on the interactive wizard; it imports writeConfigAtomic which is a generic file-write utility. This creates an unintuitive coupling. writeConfigAtomic should be moved to a shared utility module (e.g., lib/fs-utils.js) so both the wizard and migrator can import it independently.

7. map-model.yaml has model: medium but is a bypass command

The map-model command sets model: medium in its own YAML. If selectModel is called with the command's metadata tier before the bypass check resolves (depending on call order), this is a chicken-and-egg risk. It's low severity given the bypass should run first, but the self-referential model: medium on a config-repair command is confusing. Consider documenting why it's safe, or setting no model: field on bypass commands.


🟢 Low / Suggestions

8. emitFirstRunHint accumulates stale path keys

seen-hints.json uses the absolute project root path as a key. These paths are machine-specific, accumulate indefinitely, and are never pruned. A project moved to a different directory gets a duplicate hint. A hash of the project root, or a relative path from $HOME, would be more portable.

9. Mass YAML regeneration obscures the meaningful diff

~60 agent/command YAML files were bulk-updated solely to rename opus/sonnet/haikuhigh/medium/low. These generated changes should ideally be a separate commit from the core logic changes to make the diff easier to review.


✅ What's Good

  • The new config architecture (project-scoped .claude/ensemble-model-config.json vs old global XDG path) is a cleaner design.
  • writeConfigAtomic using tmp + rename is the correct pattern for safe config writes.
  • preflightValidate against KNOWN_MODEL_IDS is good defensive programming.
  • The DEFAULT_CONFIG with Object.freeze and proper fallback chain in loadConfig is solid.
  • The one-time warning/hint sentinel pattern in checkLegacyXdgFile / emitFirstRunHint is a thoughtful UX detail.
  • The two stated bug fixes (ask-user.ts TS2322, version assertion 2.12.0→2.13.0) are correct.
  • schemas/ensemble-model-config-schema.json is a welcome addition.

Summary

The implementation quality of the tiered model aliases feature is generally solid, but items #1 (.beads/ runtime files) and #2 (BYPASS_COMMANDS namespace mismatch) should be fixed before merge — the second one will cause a broken user experience when the feature is most needed. Items #3 and #4 are high priority for maintainability. The PR description needs to accurately reflect that this is a feature PR, not just a bug-fix.

@ldangelo

Copy link
Copy Markdown
Contributor Author

Closing — branch was accidentally created from feature/trd-2026-021-tiered-model-aliases instead of main. Recreating with only the two targeted fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant