its-magic 0.1.3-0 → 0.1.3-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/package.json +1 -1
- package/scripts/check_intake_template_parity.py +62 -0
- package/template/.cursor/agents/curator.mdc +1 -0
- package/template/.cursor/agents/po.mdc +1 -0
- package/template/.cursor/agents/release.mdc +1 -0
- package/template/.cursor/model-catalog.local.example.cursor-only.json +9 -0
- package/template/.cursor/model-catalog.local.example.json +9 -0
- package/template/.cursor/model-catalog.local.example.level-1-easy.json +9 -0
- package/template/.cursor/model-catalog.local.example.level-2-complex.json +9 -0
- package/template/.cursor/model-catalog.local.example.level-3-mega.json +9 -0
- package/template/.cursor/model-catalog.local.example.level-4-super.json +9 -0
- package/template/.cursor/model-catalog.local.example.role-based-balanced.json +18 -0
- package/template/.cursor/model-catalog.local.example.role-based-highend.json +18 -0
- package/template/.cursor/scratchpad.local.example.md +55 -0
- package/template/.cursor/scratchpad.md +62 -0
- package/template/docs/engineering/runbook.md +197 -0
- package/template/scripts/check_intake_template_parity.py +62 -0
- package/template/scripts/model_tier_lib.py +680 -0
- package/template/scripts/model_tier_validate.py +368 -0
package/package.json
CHANGED
|
@@ -228,6 +228,64 @@ RELEASE_CHANGELOG_PAIRS: tuple[tuple[str, str], ...] = (
|
|
|
228
228
|
),
|
|
229
229
|
)
|
|
230
230
|
|
|
231
|
+
MODEL_TIER_PAIRS: tuple[tuple[str, str], ...] = (
|
|
232
|
+
(
|
|
233
|
+
"scripts/model_tier_lib.py",
|
|
234
|
+
"template/scripts/model_tier_lib.py",
|
|
235
|
+
),
|
|
236
|
+
(
|
|
237
|
+
"scripts/model_tier_validate.py",
|
|
238
|
+
"template/scripts/model_tier_validate.py",
|
|
239
|
+
),
|
|
240
|
+
(
|
|
241
|
+
"docs/engineering/runbook.md",
|
|
242
|
+
"template/docs/engineering/runbook.md",
|
|
243
|
+
),
|
|
244
|
+
(
|
|
245
|
+
".cursor/scratchpad.md",
|
|
246
|
+
"template/.cursor/scratchpad.md",
|
|
247
|
+
),
|
|
248
|
+
(
|
|
249
|
+
".cursor/scratchpad.local.example.md",
|
|
250
|
+
"template/.cursor/scratchpad.local.example.md",
|
|
251
|
+
),
|
|
252
|
+
(
|
|
253
|
+
"scripts/check_intake_template_parity.py",
|
|
254
|
+
"template/scripts/check_intake_template_parity.py",
|
|
255
|
+
),
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
MODEL_TIER_OVERRIDES_PAIRS: tuple[tuple[str, str], ...] = (
|
|
259
|
+
(
|
|
260
|
+
".cursor/scratchpad.md",
|
|
261
|
+
"template/.cursor/scratchpad.md",
|
|
262
|
+
),
|
|
263
|
+
(
|
|
264
|
+
".cursor/scratchpad.local.example.md",
|
|
265
|
+
"template/.cursor/scratchpad.local.example.md",
|
|
266
|
+
),
|
|
267
|
+
(
|
|
268
|
+
".cursor/model-catalog.local.example.role-based-balanced.json",
|
|
269
|
+
"template/.cursor/model-catalog.local.example.role-based-balanced.json",
|
|
270
|
+
),
|
|
271
|
+
(
|
|
272
|
+
".cursor/model-catalog.local.example.role-based-highend.json",
|
|
273
|
+
"template/.cursor/model-catalog.local.example.role-based-highend.json",
|
|
274
|
+
),
|
|
275
|
+
(
|
|
276
|
+
"scripts/model_tier_lib.py",
|
|
277
|
+
"template/scripts/model_tier_lib.py",
|
|
278
|
+
),
|
|
279
|
+
(
|
|
280
|
+
"scripts/model_tier_validate.py",
|
|
281
|
+
"template/scripts/model_tier_validate.py",
|
|
282
|
+
),
|
|
283
|
+
(
|
|
284
|
+
"docs/engineering/runbook.md",
|
|
285
|
+
"template/docs/engineering/runbook.md",
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
|
|
231
289
|
DOWNSTREAM_CI_GUARD_PAIRS: tuple[tuple[str, str], ...] = (
|
|
232
290
|
(
|
|
233
291
|
"scripts/check_downstream_ci_guard.py",
|
|
@@ -252,6 +310,8 @@ SCOPES: dict[str, tuple[tuple[str, str], ...]] = {
|
|
|
252
310
|
"project-readme": PROJECT_README_PAIRS,
|
|
253
311
|
"dev-environment": DEV_ENVIRONMENT_PAIRS,
|
|
254
312
|
"release-changelog": RELEASE_CHANGELOG_PAIRS,
|
|
313
|
+
"model-tier": MODEL_TIER_PAIRS,
|
|
314
|
+
"model-tier-overrides": MODEL_TIER_OVERRIDES_PAIRS,
|
|
255
315
|
"all": (
|
|
256
316
|
INTAKE_TEMPLATE_PAIRS
|
|
257
317
|
+ CAVEMAN_COMPRESS_PAIRS
|
|
@@ -265,6 +325,8 @@ SCOPES: dict[str, tuple[tuple[str, str], ...]] = {
|
|
|
265
325
|
+ PROJECT_README_PAIRS
|
|
266
326
|
+ DEV_ENVIRONMENT_PAIRS
|
|
267
327
|
+ RELEASE_CHANGELOG_PAIRS
|
|
328
|
+
+ MODEL_TIER_PAIRS
|
|
329
|
+
+ MODEL_TIER_OVERRIDES_PAIRS
|
|
268
330
|
),
|
|
269
331
|
}
|
|
270
332
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "composer-2.5-fast",
|
|
5
|
+
"balanced": "composer-2.5-standard",
|
|
6
|
+
"strong": "composer-2.5"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Cursor-integrated models only. Uses Cursor's own Composer 2.5 family via stable Cursor model IDs. No external API key is required; everything routes through Cursor-managed infrastructure. Strong maps to the strongest available Composer 2.5 variant (often the default parent model when model: is omitted)."
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "<your-cheap-model-slug>",
|
|
5
|
+
"balanced": "<your-balanced-model-slug>",
|
|
6
|
+
"strong": "<your-strong-model-slug>"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Copy this file to .cursor/model-catalog.local.json and replace placeholder slugs with vendor-specific model IDs. Enable with MODEL_RESOLVE=local_catalog in .cursor/scratchpad.local.md. All three tier keys are required."
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "qwen-3.7-plus",
|
|
5
|
+
"balanced": "composer-2.5-standard",
|
|
6
|
+
"strong": "glm-4.7"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Level 1 — small/simple apps (CRUD, dashboard, bot, single-service). Cost-focused: Qwen3.7 Plus handles routine volume, Composer 2.5 Standard is the Cursor default, GLM-4.7 covers occasional architecture/release gates. Based on ai_modell_auslegung_cursor_highend.md 'Kleine unkomplizierte Apps'. Enable with MODEL_RESOLVE=local_catalog."
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "qwen-3.7-plus",
|
|
5
|
+
"balanced": "composer-2.5-standard",
|
|
6
|
+
"strong": "glm-5.2"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Level 2 — complex apps (multi-service, auth, DB, FE+BE, Docker, API, worker/queue). Balanced: cheap Qwen for mass DEV, Composer 2.5 Standard as Cursor default, strong GLM-5.2 for architecture/QA/release gates. Based on ai_modell_auslegung_cursor_highend.md 'Komplexere Apps'. Enable with MODEL_RESOLVE=local_catalog."
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "qwen-3.7-plus",
|
|
5
|
+
"balanced": "glm-5.2",
|
|
6
|
+
"strong": "gpt-5.5"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Level 3 — mega-complex software / modular monoliths (trading/finance platforms, multi-team systems, long-lived infrastructure). Strong GPT-5.5 for chief-architect/final-gate work, GLM-5.2 for SA/QA/RELEASE, Qwen for volume DEV. Based on ai_modell_auslegung_cursor_highend.md 'Mega-komplexe Software'. Enable with MODEL_RESOLVE=local_catalog."
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "qwen-3.7-plus",
|
|
5
|
+
"balanced": "kimi-k2.7-code",
|
|
6
|
+
"strong": "claude-opus-4.8"
|
|
7
|
+
},
|
|
8
|
+
"notes": "Level 4 — super-high-sophisticated / mission-critical (AI operating systems, critical infrastructure, long-horizon agent systems, high-risk security/privacy/finance). Chief-architect quality: Claude Opus 4.8 for critical gates, Kimi K2.7 Code for difficult long-horizon DEV, Qwen for cheap mass work. Based on ai_modell_auslegung_cursor_highend.md 'Super-High-Sophisticated Projects'. Enable with MODEL_RESOLVE=local_catalog."
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 2,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "<your-cheap-model-slug>",
|
|
5
|
+
"balanced": "<your-balanced-model-slug>",
|
|
6
|
+
"strong": "<your-strong-model-slug>"
|
|
7
|
+
},
|
|
8
|
+
"roles": {
|
|
9
|
+
"po": "<your-po-model-slug>",
|
|
10
|
+
"sa": "<your-sa-model-slug>",
|
|
11
|
+
"dev": "<your-dev-model-slug>",
|
|
12
|
+
"dev_difficult": "<your-dev-difficult-model-slug>",
|
|
13
|
+
"qa": "<your-qa-model-slug>",
|
|
14
|
+
"security": "<your-security-model-slug>",
|
|
15
|
+
"release": "<your-release-model-slug>"
|
|
16
|
+
},
|
|
17
|
+
"notes": "Role-based balanced preset (US-0102 / DEC-0087). Copy to .cursor/model-catalog.local.json and set MODEL_RESOLVE=role_catalog in .cursor/scratchpad.local.md. All tier and role keys required when roles section present."
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 2,
|
|
3
|
+
"tiers": {
|
|
4
|
+
"cheap": "<your-cheap-highend-slug>",
|
|
5
|
+
"balanced": "<your-balanced-highend-slug>",
|
|
6
|
+
"strong": "<your-strong-highend-slug>"
|
|
7
|
+
},
|
|
8
|
+
"roles": {
|
|
9
|
+
"po": "<your-po-highend-slug>",
|
|
10
|
+
"sa": "<your-sa-highend-slug>",
|
|
11
|
+
"dev": "<your-dev-highend-slug>",
|
|
12
|
+
"dev_difficult": "<your-dev-difficult-highend-slug>",
|
|
13
|
+
"qa": "<your-qa-highend-slug>",
|
|
14
|
+
"security": "<your-security-highend-slug>",
|
|
15
|
+
"release": "<your-release-highend-slug>"
|
|
16
|
+
},
|
|
17
|
+
"notes": "Role-based high-end preset (US-0102 / DEC-0087). See ai_modell_auslegung_cursor_highend.md for non-normative role recommendations. Enable with MODEL_RESOLVE=role_catalog."
|
|
18
|
+
}
|
|
@@ -321,3 +321,58 @@ CAVEMAN_MODE=0
|
|
|
321
321
|
CAVEMAN_LEVEL=
|
|
322
322
|
CAVEMAN_COMPRESS_INPUT=0
|
|
323
323
|
CAVEMAN_FILE_SCOPE=
|
|
324
|
+
|
|
325
|
+
#
|
|
326
|
+
# ## Per-phase model tier selection (US-0101 / DEC-0086)
|
|
327
|
+
# MODEL_TIER selects LLM model strength (which model runs).
|
|
328
|
+
# MODEL_TIER ≠ TOKEN_PROFILE ≠ DELIVERY_MODE — these are independent axes;
|
|
329
|
+
# none substitutes for the other (DEC-0062 / US-0080 / US-0096).
|
|
330
|
+
# - MODEL_TIER_DEFAULT: cheap|balanced|strong (default balanced)
|
|
331
|
+
# - MODEL_TIER_<PHASE>: cheap|balanced|strong (per-phase override; PHASE = canonical phase id)
|
|
332
|
+
# Default matrix (architecture-locked):
|
|
333
|
+
# cheap — ask, refresh-context, memory-audit, status-reconcile, pause
|
|
334
|
+
# balanced — intake, discovery, research, release, plan-verify
|
|
335
|
+
# strong — architecture, execute, quick, qa, verify-work, security-review
|
|
336
|
+
# (inherit parent) — auto (orchestrator always inherits parent model)
|
|
337
|
+
# - MODEL_CATALOG: path to local slug catalog (default .cursor/model-catalog.local.json)
|
|
338
|
+
# - MODEL_RESOLVE: alias_only|local_catalog|role_catalog (default alias_only)
|
|
339
|
+
# - MODEL_FALLBACK: fallback when catalog lookup fails (default inherit)
|
|
340
|
+
# - MODEL_PROVIDER_MODE: cursor|api (default cursor)
|
|
341
|
+
# cursor = all subagents route through Cursor-managed infrastructure
|
|
342
|
+
# api = operator uses BYOK via Cursor Settings → Models → API Key
|
|
343
|
+
# Known limitation: subagents do NOT inherit custom API keys/base URLs.
|
|
344
|
+
#
|
|
345
|
+
# ## Direct per-phase model slug override (US-0102 / DEC-0087) — set in this local file only
|
|
346
|
+
# Precedence: MODEL_<PHASE> > MODEL_TIER_<PHASE> > MODEL_TIER_DEFAULT > Cursor alias
|
|
347
|
+
# - MODEL_<PHASE>: direct vendor slug (e.g. MODEL_EXECUTE=<your-vendor-slug>, MODEL_ASK=<your-vendor-slug>)
|
|
348
|
+
# - MODEL_RESOLVE=role_catalog enables phase→role→catalog slug lookup (requires v2 catalog with roles section)
|
|
349
|
+
MODEL_TIER_DEFAULT=balanced
|
|
350
|
+
MODEL_CATALOG=.cursor/model-catalog.local.json
|
|
351
|
+
MODEL_RESOLVE=alias_only
|
|
352
|
+
MODEL_FALLBACK=inherit
|
|
353
|
+
MODEL_PROVIDER_MODE=cursor
|
|
354
|
+
|
|
355
|
+
# Per-phase tier overrides for this project (uncomment and adjust as needed):
|
|
356
|
+
#MODEL_TIER_INTAKE=balanced
|
|
357
|
+
#MODEL_TIER_DISCOVERY=cheap
|
|
358
|
+
#MODEL_TIER_RESEARCH=balanced
|
|
359
|
+
#MODEL_TIER_ARCHITECTURE=strong
|
|
360
|
+
#MODEL_TIER_SPRINT-PLAN=strong
|
|
361
|
+
#MODEL_TIER_PLAN-VERIFY=balanced
|
|
362
|
+
#MODEL_TIER_EXECUTE=cheap
|
|
363
|
+
#MODEL_TIER_QA=strong
|
|
364
|
+
#MODEL_TIER_VERIFY-WORK=strong
|
|
365
|
+
#MODEL_TIER_RELEASE=balanced
|
|
366
|
+
#MODEL_TIER_REFRESH-CONTEXT=cheap
|
|
367
|
+
|
|
368
|
+
# Direct per-phase slug overrides (US-0102 — uncomment and set vendor slugs):
|
|
369
|
+
#MODEL_ASK=<your-vendor-slug>
|
|
370
|
+
#MODEL_EXECUTE=<your-vendor-slug>
|
|
371
|
+
#MODEL_QA=<your-vendor-slug>
|
|
372
|
+
|
|
373
|
+
# Use a vendor catalog instead of Cursor aliases:
|
|
374
|
+
# cp .cursor/model-catalog.local.example.level-2-complex.json .cursor/model-catalog.local.json
|
|
375
|
+
#MODEL_RESOLVE=local_catalog
|
|
376
|
+
# Role-based catalog preset (US-0102):
|
|
377
|
+
# cp .cursor/model-catalog.local.example.role-based-balanced.json .cursor/model-catalog.local.json
|
|
378
|
+
#MODEL_RESOLVE=role_catalog
|
|
@@ -322,3 +322,65 @@ CAVEMAN_MODE=1
|
|
|
322
322
|
CAVEMAN_LEVEL=full
|
|
323
323
|
CAVEMAN_COMPRESS_INPUT=0
|
|
324
324
|
CAVEMAN_FILE_SCOPE=
|
|
325
|
+
|
|
326
|
+
#
|
|
327
|
+
# ## Per-phase model tier selection (US-0101 / DEC-0086)
|
|
328
|
+
# MODEL_TIER selects LLM model strength (which model runs).
|
|
329
|
+
# MODEL_TIER ≠ TOKEN_PROFILE ≠ DELIVERY_MODE — these are independent axes;
|
|
330
|
+
# none substitutes for the other (DEC-0062 / US-0080 / US-0096).
|
|
331
|
+
# - MODEL_TIER_DEFAULT: cheap|balanced|strong (default balanced)
|
|
332
|
+
# - MODEL_TIER_<PHASE>: cheap|balanced|strong (per-phase override; PHASE = canonical phase id)
|
|
333
|
+
# Examples: MODEL_TIER_EXECUTE=cheap, MODEL_TIER_QA=strong, MODEL_TIER_RESEARCH=balanced
|
|
334
|
+
# Set in .cursor/scratchpad.local.md to override per phase without touching committed defaults.
|
|
335
|
+
# Default matrix (architecture-locked):
|
|
336
|
+
# cheap — ask, refresh-context, memory-audit, status-reconcile, pause
|
|
337
|
+
# balanced — intake, discovery, research, release, plan-verify
|
|
338
|
+
# strong — architecture, execute, quick, qa, verify-work, security-review
|
|
339
|
+
# (inherit parent) — auto (orchestrator always inherits parent model)
|
|
340
|
+
# - MODEL_CATALOG: path to local slug catalog (default .cursor/model-catalog.local.json)
|
|
341
|
+
# - MODEL_RESOLVE: alias_only|local_catalog|role_catalog (default alias_only)
|
|
342
|
+
# alias_only = use Cursor-stable aliases (cheap->fast, balanced->inherit, strong->omit model:)
|
|
343
|
+
# local_catalog = look up vendor model slugs from MODEL_CATALOG; requires valid JSON catalog
|
|
344
|
+
# role_catalog = opt-in phase→role→catalog slug lookup (US-0102 / DEC-0087); falls through on miss
|
|
345
|
+
# - MODEL_FALLBACK: fallback when catalog lookup fails (default inherit)
|
|
346
|
+
# - MODEL_PROVIDER_MODE: cursor|api (default cursor)
|
|
347
|
+
# cursor = all subagents route through Cursor-managed infrastructure
|
|
348
|
+
# api = operator uses BYOK via Cursor Settings → Models → API Key
|
|
349
|
+
# Known limitation: subagents do NOT inherit custom API keys/base URLs.
|
|
350
|
+
#
|
|
351
|
+
# Example catalogs for 4 software-complexity levels + a Cursor-only variant:
|
|
352
|
+
# .cursor/model-catalog.local.example.json — minimal placeholder template
|
|
353
|
+
# .cursor/model-catalog.local.example.cursor-only.json — only Cursor-integrated Composer models
|
|
354
|
+
# .cursor/model-catalog.local.example.level-1-easy.json — small/simple apps
|
|
355
|
+
# .cursor/model-catalog.local.example.level-2-complex.json — complex multi-service apps
|
|
356
|
+
# .cursor/model-catalog.local.example.level-3-mega.json — mega-complex / modular monoliths
|
|
357
|
+
# .cursor/model-catalog.local.example.level-4-super.json — super-high-sophisticated / mission-critical
|
|
358
|
+
# .cursor/model-catalog.local.example.role-based-balanced.json — v2 role preset (balanced)
|
|
359
|
+
# .cursor/model-catalog.local.example.role-based-highend.json — v2 role preset (high-end)
|
|
360
|
+
# Copy one to .cursor/model-catalog.local.json and set MODEL_RESOLVE=local_catalog or role_catalog to activate.
|
|
361
|
+
MODEL_TIER_DEFAULT=balanced
|
|
362
|
+
MODEL_CATALOG=.cursor/model-catalog.local.json
|
|
363
|
+
MODEL_RESOLVE=alias_only
|
|
364
|
+
MODEL_FALLBACK=inherit
|
|
365
|
+
MODEL_PROVIDER_MODE=cursor
|
|
366
|
+
#
|
|
367
|
+
# ## Direct per-phase model slug override + role catalog (US-0102 / DEC-0087)
|
|
368
|
+
# Composes on US-0101 / DEC-0086 — tier baseline unchanged; overlays are optional.
|
|
369
|
+
# Precedence chain (deterministic, per canonical phase_id):
|
|
370
|
+
# 1. MODEL_<PHASE> — direct vendor slug override (highest priority)
|
|
371
|
+
# 2. MODEL_TIER_<PHASE> — DEC-0086 tier→alias / local_catalog chain
|
|
372
|
+
# 3. role_catalog lookup — only when MODEL_RESOLVE=role_catalog; miss falls through
|
|
373
|
+
# 4. MODEL_TIER_DEFAULT — DEC-0086 tier chain
|
|
374
|
+
# 5. Cursor stable alias — DEC-0086 built-in mapping (fast / inherit / omit)
|
|
375
|
+
# Scratchpad merge precedence for all MODEL_* keys: MODEL_<PHASE> > MODEL_TIER_<PHASE> > MODEL_TIER_DEFAULT
|
|
376
|
+
# - MODEL_<PHASE>: direct vendor slug; <PHASE> = canonical phase id (same list as MODEL_TIER_<PHASE>)
|
|
377
|
+
# Set in .cursor/scratchpad.local.md only — use <your-vendor-slug> placeholders in committed files.
|
|
378
|
+
# Canonical phase ids: ask, refresh-context, memory-audit, status-reconcile, pause,
|
|
379
|
+
# intake, discovery, research, release, plan-verify, architecture, execute, quick,
|
|
380
|
+
# qa, verify-work, security-review, auto
|
|
381
|
+
# Examples (placeholders — replace in scratchpad.local.md):
|
|
382
|
+
# MODEL_ASK=<your-vendor-slug>
|
|
383
|
+
# MODEL_EXECUTE=<your-vendor-slug>
|
|
384
|
+
# MODEL_QA=<your-vendor-slug>
|
|
385
|
+
# MODEL_REFRESH-CONTEXT=<your-vendor-slug>
|
|
386
|
+
# MODEL_ASK participates in step 1 like any other phase (no special-case bypass).
|
|
@@ -650,6 +650,203 @@ When **`AUTO_DELIVERY_ROUTING=backlog_then_scratchpad`**, story row may declare
|
|
|
650
650
|
|
|
651
651
|
**Release status (S0086 / US-0096)**: **`released`** (`2026-06-13T16:00:00Z`); **`US-0096`** **DONE** in canonical backlog. Operator verify: **`handoffs/releases/S0086-release-notes.md`** **## Verify**; publish skipped while **`RELEASE_PUBLISH_MODE=confirm`**.
|
|
652
652
|
|
|
653
|
+
## Per-phase model tier selection (US-0101 / DEC-0086)
|
|
654
|
+
|
|
655
|
+
`MODEL_TIER` selects LLM model strength (which model runs per lifecycle phase).
|
|
656
|
+
Three operator-facing tiers map to stable Cursor aliases — no vendor slugs in
|
|
657
|
+
template files.
|
|
658
|
+
|
|
659
|
+
| Key | Values | Default | Role |
|
|
660
|
+
|-----|--------|---------|------|
|
|
661
|
+
| **`MODEL_TIER_DEFAULT`** | `cheap` \| `balanced` \| `strong` | `balanced` | Fallback when phase-specific key absent |
|
|
662
|
+
| **`MODEL_TIER_<PHASE>`** | `cheap` \| `balanced` \| `strong` | *(per matrix)* | Per-phase tier override |
|
|
663
|
+
| **`MODEL_CATALOG`** | path | `.cursor/model-catalog.local.json` | Path to local slug catalog |
|
|
664
|
+
| **`MODEL_RESOLVE`** | `alias_only` \| `local_catalog` | `alias_only` | Resolution strategy |
|
|
665
|
+
| **`MODEL_FALLBACK`** | `inherit` | `inherit` | Fallback when catalog lookup fails |
|
|
666
|
+
| **`MODEL_PROVIDER_MODE`** | `cursor` \| `api` | `cursor` | Provider routing |
|
|
667
|
+
|
|
668
|
+
### Default phase→tier matrix (architecture-locked)
|
|
669
|
+
|
|
670
|
+
| Tier | Cursor alias | `model:` field | Phases |
|
|
671
|
+
|------|-------------|----------------|--------|
|
|
672
|
+
| **`cheap`** | `fast` | `model: fast` | `ask`, `refresh-context`, `memory-audit`, `status-reconcile`, `pause` |
|
|
673
|
+
| **`balanced`** | `inherit` | `model: inherit` | `intake`, `discovery`, `research`, `release`, `plan-verify` |
|
|
674
|
+
| **`strong`** | *(omit)* | no `model:` field | `architecture`, `execute`, `quick`, `qa`, `verify-work`, `security-review` |
|
|
675
|
+
| *(inherit parent)* | — | — | `auto` (orchestrator always inherits parent model) |
|
|
676
|
+
|
|
677
|
+
### Provider mode (MODEL_PROVIDER_MODE)
|
|
678
|
+
|
|
679
|
+
| Mode | Description |
|
|
680
|
+
|------|-------------|
|
|
681
|
+
| **`cursor`** (default) | All subagents route through Cursor-managed infrastructure; tier aliases work as designed |
|
|
682
|
+
| **`api`** | Operator uses BYOK via Cursor Settings → Models → API Key |
|
|
683
|
+
|
|
684
|
+
**Known limitation (confirmed 2026-06)**: Cursor subagents do **NOT** inherit
|
|
685
|
+
custom API keys or base URLs — they always bill against the Cursor plan. When
|
|
686
|
+
`MODEL_PROVIDER_MODE=api`, the local catalog is the only operator-controlled
|
|
687
|
+
surface; subagent `model:` aliases still resolve through Cursor infrastructure.
|
|
688
|
+
|
|
689
|
+
**Workaround recipes**:
|
|
690
|
+
|
|
691
|
+
1. **Parent model + `inherit`** — set the parent chat model to the desired BYOK
|
|
692
|
+
model; subagents using `model: inherit` (balanced tier) pick it up.
|
|
693
|
+
2. **Manual phase runs** — run each phase in a separate chat with the desired
|
|
694
|
+
model selected at the chat level (no subagent spawn).
|
|
695
|
+
3. **Local catalog override** — set `MODEL_RESOLVE=local_catalog` and populate
|
|
696
|
+
`.cursor/model-catalog.local.json` with vendor slugs; materializer applies
|
|
697
|
+
slugs at template materialization time (not at subagent runtime).
|
|
698
|
+
|
|
699
|
+
### Non-substitution paragraph
|
|
700
|
+
|
|
701
|
+
MODEL_TIER ≠ TOKEN_PROFILE ≠ DELIVERY_MODE
|
|
702
|
+
|
|
703
|
+
> **`MODEL_TIER`** selects LLM model strength (which model runs).
|
|
704
|
+
> **`TOKEN_PROFILE`** selects context breadth / token cost (how much context the model sees).
|
|
705
|
+
> **`DELIVERY_MODE`** selects lifecycle shape (standard / ultra_lean / mega_quick).
|
|
706
|
+
> These are **independent axes** — none substitutes for another. A `strong` tier
|
|
707
|
+
> with `lean` profile is valid; a `cheap` tier with `full` profile is valid.
|
|
708
|
+
> Setting one does not change the others. Combine freely.
|
|
709
|
+
|
|
710
|
+
### Reason codes — `MODEL_TIER_*` / `MODEL_CATALOG_*` / `MODEL_RESOLVE_*` / `MODEL_SLUG_*`
|
|
711
|
+
|
|
712
|
+
| Code | Trigger |
|
|
713
|
+
|------|---------|
|
|
714
|
+
| **`MODEL_TIER_INVALID`** | Unknown tier value (not `cheap`/`balanced`/`strong`) |
|
|
715
|
+
| **`MODEL_CATALOG_INVALID`** | Malformed catalog JSON (parse error, missing `schema_version`) |
|
|
716
|
+
| **`MODEL_SLUG_UNKNOWN`** | Tier key missing from catalog when `MODEL_RESOLVE=local_catalog` |
|
|
717
|
+
| **`MODEL_RESOLVE_FALLBACK`** | Catalog lookup failed but `MODEL_FALLBACK=inherit` → reason + fallback |
|
|
718
|
+
|
|
719
|
+
### Template agent defaults
|
|
720
|
+
|
|
721
|
+
| Agent role | Tier | `model:` field |
|
|
722
|
+
|-----------|------|----------------|
|
|
723
|
+
| `curator` | cheap | `model: fast` |
|
|
724
|
+
| `po` | balanced | `model: inherit` |
|
|
725
|
+
| `release` | balanced | `model: inherit` |
|
|
726
|
+
| `tech-lead` | strong | *(omit)* |
|
|
727
|
+
| `dev` | strong | *(omit)* |
|
|
728
|
+
| `qa` | strong | *(omit)* |
|
|
729
|
+
| `security` | strong | *(omit)* |
|
|
730
|
+
|
|
731
|
+
**Forbidden in `template/.cursor/agents/`**: hardcoded vendor slugs
|
|
732
|
+
(`composer-*`, `claude-*`, `gpt-*`, `opus-*`). Template files use aliases only.
|
|
733
|
+
|
|
734
|
+
### Local catalog schema (v1)
|
|
735
|
+
|
|
736
|
+
```json
|
|
737
|
+
{
|
|
738
|
+
"schema_version": 1,
|
|
739
|
+
"tiers": {
|
|
740
|
+
"cheap": "<slug>",
|
|
741
|
+
"balanced": "<slug>",
|
|
742
|
+
"strong": "<slug>"
|
|
743
|
+
},
|
|
744
|
+
"notes": "optional free-text"
|
|
745
|
+
}
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
- Path: `.cursor/model-catalog.local.json` (gitignored)
|
|
749
|
+
- Example: `.cursor/model-catalog.local.example.json` (committed, placeholder values)
|
|
750
|
+
- All three tier keys required; values are opaque vendor slug strings
|
|
751
|
+
|
|
752
|
+
### Resolver algorithm
|
|
753
|
+
|
|
754
|
+
1. Read `MODEL_TIER_<PHASE>` from merged scratchpad → tier value
|
|
755
|
+
2. If `MODEL_RESOLVE=alias_only` (default): use built-in mapping (table above)
|
|
756
|
+
3. If `MODEL_RESOLVE=local_catalog`: load catalog JSON → lookup tier key → slug
|
|
757
|
+
4. If key missing → `MODEL_SLUG_UNKNOWN` fail-closed
|
|
758
|
+
5. If `MODEL_FALLBACK=inherit` and lookup fails → emit `MODEL_RESOLVE_FALLBACK` + use `inherit`
|
|
759
|
+
6. Unknown tier value → `MODEL_TIER_INVALID` fail-closed
|
|
760
|
+
7. Malformed catalog JSON → `MODEL_CATALOG_INVALID` fail-closed
|
|
761
|
+
|
|
762
|
+
### Validation commands
|
|
763
|
+
|
|
764
|
+
- `python scripts/model_tier_validate.py --repo .`
|
|
765
|
+
- `pytest -k us0101 tests/auto_command_contract_test.py`
|
|
766
|
+
- `python scripts/check_intake_template_parity.py --scope=model-tier`
|
|
767
|
+
- `tests/run-tests.ps1` / `tests/run-tests.sh` §26Z
|
|
768
|
+
|
|
769
|
+
Normative architecture: `docs/engineering/architecture.md` (**# US-0101**).
|
|
770
|
+
|
|
771
|
+
## Direct per-phase model slug override + role catalog (US-0102 / DEC-0087)
|
|
772
|
+
|
|
773
|
+
Composes on **US-0101** / **DEC-0086** — tier-only operators need no migration.
|
|
774
|
+
|
|
775
|
+
### 5-step precedence chain
|
|
776
|
+
|
|
777
|
+
| Step | Source | Outcome |
|
|
778
|
+
|------|--------|---------|
|
|
779
|
+
| **1** | `MODEL_<PHASE>` | Non-empty slug → return (validate per mode) or `MODEL_OVERRIDE_SLUG_UNKNOWN` |
|
|
780
|
+
| **2** | `MODEL_TIER_<PHASE>` | **DEC-0086** tier→alias / `local_catalog` chain |
|
|
781
|
+
| **3** | `MODEL_RESOLVE=role_catalog` | Phase→logical role → catalog `roles[<key>]`; miss → `MODEL_ROLE_SLUG_UNKNOWN` → fall through |
|
|
782
|
+
| **4** | `MODEL_TIER_DEFAULT` | **DEC-0086** tier chain |
|
|
783
|
+
| **5** | Cursor alias | **DEC-0086** built-in mapping |
|
|
784
|
+
|
|
785
|
+
When `MODEL_RESOLVE` is `alias_only` or `local_catalog`, step **3** is skipped.
|
|
786
|
+
|
|
787
|
+
### Scratchpad keys (new)
|
|
788
|
+
|
|
789
|
+
| Key | Default | Role |
|
|
790
|
+
|-----|---------|------|
|
|
791
|
+
| **`MODEL_<PHASE>`** | *(absent)* | Direct vendor slug; includes `MODEL_ASK` |
|
|
792
|
+
| **`MODEL_RESOLVE`** | `alias_only` | Extended: `alias_only` \| `local_catalog` \| **`role_catalog`** |
|
|
793
|
+
|
|
794
|
+
Operator slugs live in `.cursor/scratchpad.local.md` and `.cursor/model-catalog.local.json` only (gitignored).
|
|
795
|
+
|
|
796
|
+
### Role catalog enablement recipe
|
|
797
|
+
|
|
798
|
+
1. Copy a v2 example catalog:
|
|
799
|
+
- `.cursor/model-catalog.local.example.role-based-balanced.json`, or
|
|
800
|
+
- `.cursor/model-catalog.local.example.role-based-highend.json`
|
|
801
|
+
2. Save as `.cursor/model-catalog.local.json` with real vendor slugs.
|
|
802
|
+
3. Set `MODEL_RESOLVE=role_catalog` in `.cursor/scratchpad.local.md`.
|
|
803
|
+
4. Optional: set `MODEL_<PHASE>=<slug>` for direct overrides (step 1 wins over role lookup).
|
|
804
|
+
5. Run `python scripts/model_tier_validate.py --repo .` to validate.
|
|
805
|
+
|
|
806
|
+
On role lookup miss → `MODEL_ROLE_SLUG_UNKNOWN` emitted; resolver falls through to `MODEL_TIER_DEFAULT` then Cursor alias.
|
|
807
|
+
|
|
808
|
+
**`dev_difficult`**: no automatic phase routing — use `MODEL_EXECUTE=<slug>` direct override or tier `strong` + catalog tier slug.
|
|
809
|
+
|
|
810
|
+
Non-normative role recommendations: `ai_modell_auslegung_cursor_highend.md`.
|
|
811
|
+
|
|
812
|
+
### Catalog schema v2 (opt-in)
|
|
813
|
+
|
|
814
|
+
```json
|
|
815
|
+
{
|
|
816
|
+
"schema_version": 2,
|
|
817
|
+
"tiers": { "cheap": "<slug>", "balanced": "<slug>", "strong": "<slug>" },
|
|
818
|
+
"roles": {
|
|
819
|
+
"po": "<slug>", "sa": "<slug>", "dev": "<slug>", "dev_difficult": "<slug>",
|
|
820
|
+
"qa": "<slug>", "security": "<slug>", "release": "<slug>"
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
v1 catalogs (tiers only) unchanged. Malformed v2 → `MODEL_CATALOG_SCHEMA_V2_INVALID`.
|
|
826
|
+
|
|
827
|
+
### New reason codes
|
|
828
|
+
|
|
829
|
+
| Code | Trigger |
|
|
830
|
+
|------|---------|
|
|
831
|
+
| **`MODEL_OVERRIDE_SLUG_UNKNOWN`** | Direct slug validation failure |
|
|
832
|
+
| **`MODEL_ROLE_SLUG_UNKNOWN`** | Role catalog lookup miss |
|
|
833
|
+
| **`MODEL_CATALOG_SCHEMA_V2_INVALID`** | v2 schema validation failure |
|
|
834
|
+
|
|
835
|
+
### Non-substitution paragraph
|
|
836
|
+
|
|
837
|
+
MODEL_TIER ≠ TOKEN_PROFILE ≠ DELIVERY_MODE — unchanged from **US-0101**; model selection is orthogonal to context breadth.
|
|
838
|
+
|
|
839
|
+
### Validation commands
|
|
840
|
+
|
|
841
|
+
- `python scripts/model_tier_validate.py --repo .`
|
|
842
|
+
- `pytest -k us0102 tests/auto_command_contract_test.py`
|
|
843
|
+
- `python scripts/check_intake_template_parity.py --scope=model-tier-overrides`
|
|
844
|
+
- `tests/run-tests.ps1` / `tests/run-tests.sh` §26AA
|
|
845
|
+
|
|
846
|
+
Normative architecture: `docs/engineering/architecture.md` (**# US-0102**); decision: **`DEC-0087`**.
|
|
847
|
+
|
|
848
|
+
Binding decision: `decisions/DEC-0086.md`.
|
|
849
|
+
|
|
653
850
|
Context compaction policy:
|
|
654
851
|
|
|
655
852
|
- `docs/engineering/state.md` is a compact hot surface for current execution
|
|
@@ -228,6 +228,64 @@ RELEASE_CHANGELOG_PAIRS: tuple[tuple[str, str], ...] = (
|
|
|
228
228
|
),
|
|
229
229
|
)
|
|
230
230
|
|
|
231
|
+
MODEL_TIER_PAIRS: tuple[tuple[str, str], ...] = (
|
|
232
|
+
(
|
|
233
|
+
"scripts/model_tier_lib.py",
|
|
234
|
+
"template/scripts/model_tier_lib.py",
|
|
235
|
+
),
|
|
236
|
+
(
|
|
237
|
+
"scripts/model_tier_validate.py",
|
|
238
|
+
"template/scripts/model_tier_validate.py",
|
|
239
|
+
),
|
|
240
|
+
(
|
|
241
|
+
"docs/engineering/runbook.md",
|
|
242
|
+
"template/docs/engineering/runbook.md",
|
|
243
|
+
),
|
|
244
|
+
(
|
|
245
|
+
".cursor/scratchpad.md",
|
|
246
|
+
"template/.cursor/scratchpad.md",
|
|
247
|
+
),
|
|
248
|
+
(
|
|
249
|
+
".cursor/scratchpad.local.example.md",
|
|
250
|
+
"template/.cursor/scratchpad.local.example.md",
|
|
251
|
+
),
|
|
252
|
+
(
|
|
253
|
+
"scripts/check_intake_template_parity.py",
|
|
254
|
+
"template/scripts/check_intake_template_parity.py",
|
|
255
|
+
),
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
MODEL_TIER_OVERRIDES_PAIRS: tuple[tuple[str, str], ...] = (
|
|
259
|
+
(
|
|
260
|
+
".cursor/scratchpad.md",
|
|
261
|
+
"template/.cursor/scratchpad.md",
|
|
262
|
+
),
|
|
263
|
+
(
|
|
264
|
+
".cursor/scratchpad.local.example.md",
|
|
265
|
+
"template/.cursor/scratchpad.local.example.md",
|
|
266
|
+
),
|
|
267
|
+
(
|
|
268
|
+
".cursor/model-catalog.local.example.role-based-balanced.json",
|
|
269
|
+
"template/.cursor/model-catalog.local.example.role-based-balanced.json",
|
|
270
|
+
),
|
|
271
|
+
(
|
|
272
|
+
".cursor/model-catalog.local.example.role-based-highend.json",
|
|
273
|
+
"template/.cursor/model-catalog.local.example.role-based-highend.json",
|
|
274
|
+
),
|
|
275
|
+
(
|
|
276
|
+
"scripts/model_tier_lib.py",
|
|
277
|
+
"template/scripts/model_tier_lib.py",
|
|
278
|
+
),
|
|
279
|
+
(
|
|
280
|
+
"scripts/model_tier_validate.py",
|
|
281
|
+
"template/scripts/model_tier_validate.py",
|
|
282
|
+
),
|
|
283
|
+
(
|
|
284
|
+
"docs/engineering/runbook.md",
|
|
285
|
+
"template/docs/engineering/runbook.md",
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
|
|
231
289
|
DOWNSTREAM_CI_GUARD_PAIRS: tuple[tuple[str, str], ...] = (
|
|
232
290
|
(
|
|
233
291
|
"scripts/check_downstream_ci_guard.py",
|
|
@@ -252,6 +310,8 @@ SCOPES: dict[str, tuple[tuple[str, str], ...]] = {
|
|
|
252
310
|
"project-readme": PROJECT_README_PAIRS,
|
|
253
311
|
"dev-environment": DEV_ENVIRONMENT_PAIRS,
|
|
254
312
|
"release-changelog": RELEASE_CHANGELOG_PAIRS,
|
|
313
|
+
"model-tier": MODEL_TIER_PAIRS,
|
|
314
|
+
"model-tier-overrides": MODEL_TIER_OVERRIDES_PAIRS,
|
|
255
315
|
"all": (
|
|
256
316
|
INTAKE_TEMPLATE_PAIRS
|
|
257
317
|
+ CAVEMAN_COMPRESS_PAIRS
|
|
@@ -265,6 +325,8 @@ SCOPES: dict[str, tuple[tuple[str, str], ...]] = {
|
|
|
265
325
|
+ PROJECT_README_PAIRS
|
|
266
326
|
+ DEV_ENVIRONMENT_PAIRS
|
|
267
327
|
+ RELEASE_CHANGELOG_PAIRS
|
|
328
|
+
+ MODEL_TIER_PAIRS
|
|
329
|
+
+ MODEL_TIER_OVERRIDES_PAIRS
|
|
268
330
|
),
|
|
269
331
|
}
|
|
270
332
|
|