okstra 0.65.0 → 0.66.0

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/docs/kr/cli.md CHANGED
@@ -296,7 +296,7 @@ scripts/okstra.sh --task-type implementation-planning --workers claude,codex --p
296
296
  ```
297
297
 
298
298
  > 모든 `--*-model` 플래그는 `scripts/okstra_ctl/models.py` 의 provider 별 mapping 에 등록된 alias 만 허용합니다. 등록되지 않은 값은 `UnknownModelError` 로 즉시 거부됩니다 (manifest 의 `modelExecutionValue` 와 실제 실행값 불일치로 인한 contract-violation 을 사전에 차단). 허용값:
299
- > - Claude (`--lead-model` / `--claude-model` / `--report-writer-model`): `opus`, `opus-4-7`, `claude-opus-4-7`, `opus-4-6`, `claude-opus-4-6`, `sonnet`, `sonnet-4-6`, `claude-sonnet-4-6`, `haiku`, `haiku-4-5`, `claude-haiku-4-5`, `claude-haiku-4-5-20251001`
299
+ > - Claude (`--lead-model` / `--claude-model` / `--report-writer-model`): `fable`, `fable-5`, `claude-fable-5`, `opus`, `opus-4-8`, `claude-opus-4-8`, `opus-4-7`, `claude-opus-4-7`, `opus-4-6`, `claude-opus-4-6`, `sonnet`, `sonnet-4-6`, `claude-sonnet-4-6`, `haiku`, `haiku-4-5`, `claude-haiku-4-5`, `claude-haiku-4-5-20251001`
300
300
  > - Codex (`--codex-model`): `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.2`, `codex-auto-review`
301
301
  > - Gemini (`--gemini-model`): `auto`, `pro`, `gemini-3-flash-preview`, `gemini-3-pro-preview` (그리고 `gemini auto` / `gemini pro` 별칭)
302
302
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okstra",
3
- "version": "0.65.0",
3
+ "version": "0.66.0",
4
4
  "description": "Multi-agent cross-verification orchestrator runtime + Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "author": "devonshin",
@@ -1,5 +1,5 @@
1
1
  {
2
- "package": "0.65.0",
3
- "builtAt": "2026-06-10T08:26:08.228Z",
2
+ "package": "0.66.0",
3
+ "builtAt": "2026-06-10T09:21:55.603Z",
4
4
  "repoRoot": "/home/runner/work/okstra/okstra"
5
5
  }
@@ -225,7 +225,7 @@ Spawn **analysis workers only** in the same turn (Phase 4 in Teams mode; Phase 5
225
225
 
226
226
  **Agent `name` on dispatch (BLOCKING — token-usage attribution depends on it).** Every analysis-worker `Agent(...)` call MUST set `name: "<workerId>-worker"` — `name: "claude-worker"` / `name: "codex-worker"` / `name: "gemini-worker"` — exactly as the report-writer dispatch sets `name: "report-writer"` ([okstra-report-writer](./skills/okstra-report-writer/SKILL.md)). The Agent harness records this `name` as `agentName` in the subagent session jsonl, and the Phase 7 token collector matches each worker's session by that `agentName` (`okstra_token_usage/collect.py`). A worker dispatched **without** `name` produces a session with no `agentName`; the collector cannot attribute it and records the worker as `source: "unavailable"` even though the session exists and is team-tagged (observed in `dev-9692` error-analysis: `claude`/`codex` workers dispatched without `name` → both `unavailable`, while the named `report-writer` collected normally). Convergence reverify dispatches keep the prefix (`<workerId>-worker-reverify-r<N>`); implementation executor/verifier variants keep `<workerId>-worker` / `<workerId>-executor`.
227
227
 
228
- **Agent `model:` on dispatch (BLOCKING — assignment is otherwise ignored).** The `Claude worker` `Agent(...)` call MUST set `model: "<family token of that role's modelExecutionValue>"` (`opus` / `sonnet` / `haiku`), per [okstra-team-contract](./skills/okstra-team-contract/SKILL.md) "Model Assignment Rules" #3–#4. The claude-worker definition is `model: inherit`, so omitting this parameter makes the worker silently run on the lead's model instead of its manifest assignment — the assigned-vs-actual deviation. `Codex worker` / `Gemini worker` are exempt: their CLI model is applied via the wrapper's own `--model` argument, so leave their Agent `model:` at `inherit` (rule #5).
228
+ **Agent `model:` on dispatch (BLOCKING — assignment is otherwise ignored).** The `Claude worker` `Agent(...)` call MUST set `model: "<family token of that role's modelExecutionValue>"` (`fable` / `opus` / `sonnet` / `haiku`), per [okstra-team-contract](./skills/okstra-team-contract/SKILL.md) "Model Assignment Rules" #3–#4. The claude-worker definition is `model: inherit`, so omitting this parameter makes the worker silently run on the lead's model instead of its manifest assignment — the assigned-vs-actual deviation. `Codex worker` / `Gemini worker` are exempt: their CLI model is applied via the wrapper's own `--model` argument, so leave their Agent `model:` at `inherit` (rule #5).
229
229
 
230
230
  The no-`team_name` fallback (Phase 5) is only legal when team-state's `teamCreate.status` is `"error"` for this run. If `teamCreate` is missing or `attempted: false`, the correct action when an Agent dispatch is rejected for a missing team is to GO BACK to Phase 3 and call `TeamCreate` — never to strip `team_name` and continue.
231
231
 
@@ -8,7 +8,12 @@ from __future__ import annotations
8
8
  from dataclasses import dataclass
9
9
 
10
10
  CLAUDE_MAPPING = {
11
+ "fable": ("fable", "fable"),
12
+ "fable-5": ("fable-5", "claude-fable-5"),
13
+ "claude-fable-5": ("fable-5", "claude-fable-5"),
11
14
  "opus": ("opus", "opus"),
15
+ "opus-4-8": ("opus-4-8", "claude-opus-4-8"),
16
+ "claude-opus-4-8": ("opus-4-8", "claude-opus-4-8"),
12
17
  "opus-4-7": ("opus-4-7", "claude-opus-4-7"),
13
18
  "claude-opus-4-7": ("opus-4-7", "claude-opus-4-7"),
14
19
  "opus-4-6": ("opus-4-6", "claude-opus-4-6"),
@@ -358,7 +358,8 @@ def _enforce_schema(data: dict) -> None:
358
358
  # 구체버전 계열로 돌았는지" 가독성만 준다. CLI 가 실제 고른 버전과 다를 수
359
359
  # 있으나 표시이므로 실행에는 무해하다. 새 버전이 나오면 여기만 갱신한다.
360
360
  _DISPLAY_CONCRETE_CLAUDE = {
361
- "opus": "claude-opus-4-7",
361
+ "fable": "claude-fable-5",
362
+ "opus": "claude-opus-4-8",
362
363
  "sonnet": "claude-sonnet-4-6",
363
364
  "haiku": "claude-haiku-4-5",
364
365
  }
@@ -90,7 +90,7 @@ _STAGE_SCOPED_TASK_TYPES = ("implementation", "final-verification")
90
90
  CANONICAL_BASE_REFS = ["main", "dev", "staging", "preprod", "prod"]
91
91
  BASE_REF_FREE_INPUT_TOKEN = "__free_input__"
92
92
 
93
- CLAUDE_MODEL_OPTIONS = ["default", "opus", "sonnet", "haiku"]
93
+ CLAUDE_MODEL_OPTIONS = ["default", "fable", "opus", "sonnet", "haiku"]
94
94
  CODEX_MODEL_OPTIONS = ["default", "gpt-5.5", "gpt-5.4", "gpt-5.4-mini"]
95
95
  GEMINI_MODEL_OPTIONS = ["default", "gemini-3-pro-preview", "gemini-3-flash-preview", "auto"]
96
96
 
@@ -4,9 +4,9 @@ Pricing is matched by substring against the model id recorded in the session
4
4
  transcript, so keys must reflect the *actual* model id form emitted by each
5
5
  provider:
6
6
 
7
- * Anthropic — `claude-opus-4-*`, `claude-sonnet-4-*`, `claude-haiku-4-5-*`,
8
- `claude-3-5-sonnet-*`, `claude-3-5-haiku-*`, `claude-3-opus-*`,
9
- `claude-3-haiku-*`.
7
+ * Anthropic — `claude-fable-5*`, `claude-opus-4-*`, `claude-sonnet-4-*`,
8
+ `claude-haiku-4-5-*`, `claude-3-5-sonnet-*`, `claude-3-5-haiku-*`,
9
+ `claude-3-opus-*`, `claude-3-haiku-*`.
10
10
  * OpenAI / Codex — `gpt-5*`, `gpt-4o*`, `gpt-4*`.
11
11
  * Google / Gemini — `gemini-2.5-pro*`, `gemini-2.5-flash*`, `gemini-2.0-flash*`.
12
12
 
@@ -45,7 +45,11 @@ CLAUDE_PRICING = {
45
45
  "3-sonnet": (3.0, 3.75, 0.30, 15.0), # legacy 3 Sonnet
46
46
  "3-haiku": (0.25, 0.30, 0.03, 1.25), # Haiku 3
47
47
 
48
+ # Claude Fable 5 (tier above Opus).
49
+ "fable-5": (10.0, 12.5, 1.0, 50.0), # Fable 5 (cache prices derived from ratios)
50
+
48
51
  # Claude 4 point releases (explicit so future divergence is easy to see).
52
+ "opus-4-8": (5.0, 6.25, 0.50, 25.0), # Opus 4.8 (cache prices derived from ratios)
49
53
  "opus-4-7": (5.0, 6.25, 0.50, 25.0), # Opus 4.7 (cache prices derived from ratios)
50
54
  "opus-4-6": (5.0, 6.25, 0.50, 25.0), # Opus 4.6 (legacy; pricing matches 4.7 per Anthropic)
51
55
  "sonnet-4-6": (3.0, 3.75, 0.30, 15.0), # Sonnet 4.6 (cache prices derived from ratios)
@@ -56,15 +56,15 @@ Subsequent `okstra <subcmd>` calls self-bootstrap their Python path, so this ski
56
56
 
57
57
  This skill performs cross-task synthesis (multi-task classification, dependency reasoning, phase placement, Gantt/timeline assembly) which benefits substantially from Opus-class reasoning. The frontmatter `model: opus` field above instructs supporting Claude Code harness versions to switch automatically; if the harness ignores it, this gate catches the case explicitly.
58
58
 
59
- 1. Inspect the active session model. The model is shown in the status line, accessible via `/model`, and embedded in the runtime context as the model name (e.g. `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5-*`).
60
- 2. If the active model is **Opus-class** (`claude-opus-*`): proceed to Step 1.
59
+ 1. Inspect the active session model. The model is shown in the status line, accessible via `/model`, and embedded in the runtime context as the model name (e.g. `claude-fable-5`, `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5-*`).
60
+ 2. If the active model is **Opus-class or above** (`claude-opus-*`, `claude-fable-*`): proceed to Step 1.
61
61
  3. If the active model is **Sonnet or Haiku-class**: STOP and output the following message verbatim, then wait for user response:
62
62
  ```
63
63
  okstra-schedule는 Opus-class 모델에서 실행하는 것을 권장합니다 (현재: <active-model>).
64
64
  /model opus 로 전환 후 다시 호출하시거나, 'sonnet으로 진행' 이라고 명시하시면 그대로 실행합니다.
65
65
  ```
66
66
  4. If the user explicitly insists on the lower model ("sonnet으로 진행", "그대로 진행", "force", or similar): proceed to Step 1, but prepend a single-line warning at the top of the generated schedule file: `> ⚠️ Generated with <model> (not Opus). Cross-task synthesis quality may be reduced.`
67
- 5. Skip this gate ONLY when the harness has clearly enforced `model: opus` from the frontmatter — verifiable by the active model already being Opus-class without manual switching.
67
+ 5. Skip this gate ONLY when the harness has clearly enforced `model: opus` from the frontmatter — verifiable by the active model already being Opus-class or above without manual switching.
68
68
 
69
69
  ### Step 1: Resolve task-group and collect tasks
70
70
 
@@ -38,7 +38,7 @@ okstra tasks are always operated using the `Claude lead` + required worker team
38
38
  1. `resultContract.requiredWorkerRoles` in `task-manifest.json` (and the lead model metadata) is the canonical source. There is no role-level fallback — a missing assignment is a manifest defect, not a license to invent one.
39
39
  2. If `modelExecutionValue` differs from `model`, use `modelExecutionValue` during execution.
40
40
  3. **Spawn-time enforcement for in-process Claude subagents (BLOCKING).** `Claude worker` and `Report writer worker` are in-process Claude subagents whose agent definitions declare `model: inherit` (`agents/workers/claude-worker.md`, `agents/workers/report-writer-worker.md`). `inherit` follows the **lead's** runtime model, NOT the role's assignment — so an opus assignment silently runs on a sonnet lead. To make the assignment binding (not merely declared), lead MUST pass an explicit `model:` parameter on every `Agent(...)` dispatch for these two roles, derived from that role's `modelExecutionValue`. The dispatch `model:` parameter overrides the `inherit` frontmatter; the frontmatter remains only as the fallback when no parameter is supplied. Omitting `model:` on a Claude-side dispatch is a contract violation that reproduces the assigned-vs-actual model deviation.
41
- 4. **`modelExecutionValue` → Agent `model:` family token.** The Agent tool's `model` parameter accepts family tokens only — `opus` / `sonnet` / `haiku` (an exact version such as `claude-opus-4-7` is NOT a valid value). Map by prefix: a `modelExecutionValue` of `opus*` / `claude-opus*` → `"opus"`, `sonnet*` / `claude-sonnet*` → `"sonnet"`, `haiku*` / `claude-haiku*` → `"haiku"`. This enforces the assignment at **family granularity** (opus vs sonnet vs haiku); the exact version within a family is still inherited from the lead session and cannot be pinned via this parameter.
41
+ 4. **`modelExecutionValue` → Agent `model:` family token.** The Agent tool's `model` parameter accepts family tokens only — `fable` / `opus` / `sonnet` / `haiku` (an exact version such as `claude-opus-4-7` is NOT a valid value). Map by prefix: a `modelExecutionValue` of `fable*` / `claude-fable*` → `"fable"`, `opus*` / `claude-opus*` → `"opus"`, `sonnet*` / `claude-sonnet*` → `"sonnet"`, `haiku*` / `claude-haiku*` → `"haiku"`. This enforces the assignment at **family granularity** (fable vs opus vs sonnet vs haiku); the exact version within a family is still inherited from the lead session and cannot be pinned via this parameter.
42
42
  5. **Codex / Gemini wrappers are out of scope for the Agent `model:` rule.** `Codex worker` / `Gemini worker` subagents are Claude wrappers that shell out to an external CLI; the role's `modelExecutionValue` is already applied via the CLI's own `--model <modelExecutionValue>` argument (see `agents/workers/_cli-wrapper-template.md`). The Agent `model:` parameter for these wrappers would only set the wrapper's own orchestration model, not the external CLI's model — leave it at `inherit` and do NOT map it from `modelExecutionValue`.
43
43
 
44
44
  ### Dynamic Worker Role Determination