claude-dev-env 2.10.0 → 2.12.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.
Files changed (39) hide show
  1. package/CLAUDE.md +1 -1
  2. package/_shared/advisor/CLAUDE.md +3 -2
  3. package/_shared/advisor/advisor-protocol.md +74 -108
  4. package/_shared/advisor/reference/advisor-block.md +37 -0
  5. package/_shared/advisor/reference/cli-chain.md +45 -0
  6. package/_shared/advisor/reference/consult-format.md +41 -0
  7. package/_shared/advisor/reference/lifecycle.md +21 -0
  8. package/_shared/advisor/reference/sol-rung.md +34 -0
  9. package/_shared/advisor/reference/spawn-walk-log.md +31 -0
  10. package/_shared/advisor/reference/third-party-bind.md +30 -0
  11. package/_shared/advisor/reference/warm-up.md +34 -0
  12. package/_shared/advisor/scripts/codex_sol_advisor.py +514 -0
  13. package/_shared/advisor/scripts/config/advisor_scripts_constants/advisor_route_constants.py +21 -0
  14. package/_shared/advisor/scripts/config/advisor_scripts_constants/model_tier_run_validator_constants.py +19 -17
  15. package/_shared/advisor/scripts/config/advisor_scripts_constants/sol_advisor_constants.py +33 -0
  16. package/_shared/advisor/scripts/model_tier_run_validator.py +32 -9
  17. package/_shared/advisor/scripts/tests/test_codex_sol_advisor.py +636 -0
  18. package/_shared/advisor/scripts/tests/test_model_tier_run_validator.py +79 -0
  19. package/_shared/advisor/scripts/tests/test_tier_model_ids.py +39 -17
  20. package/_shared/advisor/scripts/tier_model_ids.py +24 -0
  21. package/commands/CLAUDE.md +1 -0
  22. package/commands/sr-loop.md +48 -0
  23. package/docs/references/CLAUDE.md +2 -1
  24. package/docs/references/advisor-tool.md +26 -8
  25. package/docs/references/team-advisor-skill.md +3 -3
  26. package/docs/references/weak-executor-advisor.md +91 -0
  27. package/hooks/blocking/test_fable_spawn_gate.py +18 -11
  28. package/package.json +1 -1
  29. package/skills/_shared/advisor/CLAUDE.md +1 -1
  30. package/skills/_shared/advisor/scripts/README.md +2 -0
  31. package/skills/grokify/SKILL.md +1 -1
  32. package/skills/grokify/templates/handoff-template.md +2 -2
  33. package/skills/orchestrator/SKILL.md +5 -4
  34. package/skills/team-advisor/SKILL.md +7 -4
  35. package/skills/team-advisor/reference/advisor-docs-review.md +207 -0
  36. package/skills/usage-pause/SKILL.md +1 -1
  37. package/skills/usage-pause/scripts/resolve_usage_window.py +32 -4
  38. package/skills/usage-pause/scripts/test_resolve_usage_window.py +26 -0
  39. package/skills/usage-pause/scripts/usage_pause_constants/resolve_usage_window_constants.py +3 -1
@@ -33,6 +33,8 @@ main = model_tier_run_validator.main
33
33
  load_model_tier_run_from_json_path = (
34
34
  model_tier_run_validator.load_model_tier_run_from_json_path
35
35
  )
36
+ ADVISOR_MODEL_TIER = model_tier_run_validator.ADVISOR_MODEL_TIER
37
+ CODEX_BIND_SUCCESS_TOKEN = model_tier_run_validator.CODEX_BIND_SUCCESS_TOKEN
36
38
 
37
39
 
38
40
  def test_clean_single_spawn_at_top_of_slice_passes() -> None:
@@ -45,6 +47,66 @@ def test_clean_single_spawn_at_top_of_slice_passes() -> None:
45
47
  assert validate_model_tier_run(run) is None
46
48
 
47
49
 
50
+ def test_sol_codex_bind_is_first_success_when_enabled() -> None:
51
+ run = ModelTierRun(
52
+ own_tier="Opus",
53
+ candidate_tiers=[ADVISOR_MODEL_TIER, "Fable", "Opus"],
54
+ attempts=[{"tier": ADVISOR_MODEL_TIER, "result": CODEX_BIND_SUCCESS_TOKEN}],
55
+ selected_tier=ADVISOR_MODEL_TIER,
56
+ is_sol_enabled=True,
57
+ )
58
+ assert validate_model_tier_run(run) is None
59
+
60
+
61
+ def test_sol_failure_falls_through_to_fable_when_enabled() -> None:
62
+ run = ModelTierRun(
63
+ own_tier="Opus",
64
+ candidate_tiers=[ADVISOR_MODEL_TIER, "Fable", "Opus"],
65
+ attempts=[
66
+ {"tier": ADVISOR_MODEL_TIER, "result": "unavailable"},
67
+ {"tier": "Fable", "result": "spawned"},
68
+ ],
69
+ selected_tier="Fable",
70
+ is_sol_enabled=True,
71
+ )
72
+ assert validate_model_tier_run(run) is None
73
+
74
+
75
+ def test_sol_rung_precedes_third_party_cli_floor_when_enabled() -> None:
76
+ run = ModelTierRun(
77
+ own_tier="ThirdParty",
78
+ candidate_tiers=[ADVISOR_MODEL_TIER, "Fable", "Opus"],
79
+ attempts=[{"tier": ADVISOR_MODEL_TIER, "result": CODEX_BIND_SUCCESS_TOKEN}],
80
+ selected_tier=ADVISOR_MODEL_TIER,
81
+ is_sol_enabled=True,
82
+ )
83
+
84
+ assert validate_model_tier_run(run) is None
85
+
86
+
87
+ def test_sol_codex_result_requires_sol_candidate() -> None:
88
+ run = ModelTierRun(
89
+ own_tier="Opus",
90
+ candidate_tiers=["Fable", "Opus"],
91
+ attempts=[{"tier": "Fable", "result": CODEX_BIND_SUCCESS_TOKEN}],
92
+ selected_tier="Fable",
93
+ )
94
+ with pytest.raises(ModelTierRunError):
95
+ validate_model_tier_run(run)
96
+
97
+
98
+ def test_sol_spawned_result_does_not_count_as_codex_success() -> None:
99
+ run = ModelTierRun(
100
+ own_tier="Opus",
101
+ candidate_tiers=[ADVISOR_MODEL_TIER, "Fable", "Opus"],
102
+ attempts=[{"tier": ADVISOR_MODEL_TIER, "result": "spawned"}],
103
+ selected_tier=ADVISOR_MODEL_TIER,
104
+ is_sol_enabled=True,
105
+ )
106
+ with pytest.raises(ModelTierRunError):
107
+ validate_model_tier_run(run)
108
+
109
+
48
110
  def test_fallthrough_to_floor_tier_passes() -> None:
49
111
  run = ModelTierRun(
50
112
  own_tier="Opus",
@@ -223,6 +285,23 @@ def test_cli_validates_json_log_file(tmp_path: Path) -> None:
223
285
  assert loaded_run.selected_tier == "Fable"
224
286
 
225
287
 
288
+ def test_cli_rejects_non_boolean_sol_enabled(tmp_path: Path) -> None:
289
+ log_path = tmp_path / "invalid-sol-enabled.json"
290
+ log_path.write_text(
291
+ json.dumps(
292
+ {
293
+ "own_tier": "Opus",
294
+ "candidate_tiers": ["Fable", "Opus"],
295
+ "attempts": [{"tier": "Fable", "result": "spawned"}],
296
+ "selected_tier": "Fable",
297
+ "sol_enabled": "false",
298
+ }
299
+ ),
300
+ encoding="utf-8",
301
+ )
302
+ assert main([str(log_path)]) == 2
303
+
304
+
226
305
  def test_cli_rejects_incomplete_fallback_log(tmp_path: Path) -> None:
227
306
  log_path = tmp_path / "incomplete-walk.json"
228
307
  log_path.write_text(
@@ -10,6 +10,26 @@ from types import ModuleType
10
10
  import pytest
11
11
 
12
12
 
13
+ constants_root = Path(__file__).parent.parent / "config"
14
+ if str(constants_root) not in sys.path:
15
+ sys.path.insert(0, str(constants_root))
16
+
17
+ from advisor_scripts_constants.model_tier_run_validator_constants import ( # noqa: E402
18
+ ADVISOR_SENDMESSAGE_REPLY_WAIT_SECONDS,
19
+ ALL_CLI_MODEL_ID_BY_TIER,
20
+ ALL_KNOWN_TIER_NAMES,
21
+ ALL_MODEL_TIERS,
22
+ HOST_PROFILE_CLAUDE,
23
+ HOST_PROFILE_THIRD_PARTY,
24
+ THIRD_PARTY_MODEL_TIER,
25
+ )
26
+ from advisor_scripts_constants.advisor_route_constants import ( # noqa: E402
27
+ ADVISOR_CODEX_MODEL_ID,
28
+ ADVISOR_MODEL_TIER,
29
+ ALL_CODEX_MODEL_ID_BY_TIER,
30
+ )
31
+
32
+
13
33
  def _load_tier_model_ids_module() -> ModuleType:
14
34
  scripts_root = Path(__file__).parent.parent
15
35
  module_path = scripts_root / "tier_model_ids.py"
@@ -26,21 +46,9 @@ def _load_tier_model_ids_module() -> ModuleType:
26
46
 
27
47
  tier_model_ids = _load_tier_model_ids_module()
28
48
  resolve_cli_model_id = tier_model_ids.resolve_cli_model_id
49
+ resolve_codex_model_id = tier_model_ids.resolve_codex_model_id
29
50
  canonical_tier_name = tier_model_ids.canonical_tier_name
30
51
  detect_host_profile = tier_model_ids.detect_host_profile
31
- constants_root = Path(__file__).parent.parent / "config"
32
- if str(constants_root) not in sys.path:
33
- sys.path.insert(0, str(constants_root))
34
-
35
- from advisor_scripts_constants.model_tier_run_validator_constants import ( # noqa: E402
36
- ADVISOR_SENDMESSAGE_REPLY_WAIT_SECONDS,
37
- ALL_CLI_MODEL_ID_BY_TIER,
38
- ALL_KNOWN_TIER_NAMES,
39
- ALL_MODEL_TIERS,
40
- HOST_PROFILE_CLAUDE,
41
- HOST_PROFILE_THIRD_PARTY,
42
- THIRD_PARTY_MODEL_TIER,
43
- )
44
52
 
45
53
  SCRIPTS_ROOT = Path(__file__).parent.parent
46
54
  DOCUMENTED_RESOLVE_ONE_LINER = (
@@ -94,14 +102,28 @@ def test_sendmessage_reply_wait_is_positive_bound() -> None:
94
102
  assert ADVISOR_SENDMESSAGE_REPLY_WAIT_SECONDS == 120
95
103
 
96
104
 
105
+ def test_resolve_codex_model_id_maps_sol() -> None:
106
+ assert resolve_codex_model_id(f" {ADVISOR_MODEL_TIER.lower()} ") == (
107
+ ADVISOR_CODEX_MODEL_ID
108
+ )
109
+
110
+
111
+ def test_resolve_codex_model_id_rejects_claude_tier() -> None:
112
+ with pytest.raises(ValueError, match="not a known model tier"):
113
+ resolve_codex_model_id("Opus")
114
+
115
+
97
116
  def test_cli_model_alias_map_keys_match_known_tiers() -> None:
98
- assert set(ALL_CLI_MODEL_ID_BY_TIER) == set(ALL_KNOWN_TIER_NAMES)
117
+ all_cli_tiers = (*ALL_MODEL_TIERS, THIRD_PARTY_MODEL_TIER)
118
+ assert set(ALL_CLI_MODEL_ID_BY_TIER) == set(all_cli_tiers)
99
119
  assert set(ALL_MODEL_TIERS).issubset(set(ALL_KNOWN_TIER_NAMES))
120
+ assert ADVISOR_MODEL_TIER in ALL_KNOWN_TIER_NAMES
100
121
  assert THIRD_PARTY_MODEL_TIER in ALL_KNOWN_TIER_NAMES
101
122
  assert THIRD_PARTY_MODEL_TIER not in ALL_MODEL_TIERS
102
- assert all(
103
- ALL_CLI_MODEL_ID_BY_TIER[each_tier] for each_tier in ALL_KNOWN_TIER_NAMES
104
- )
123
+ assert all(ALL_CLI_MODEL_ID_BY_TIER[each_tier] for each_tier in all_cli_tiers)
124
+ assert ALL_CODEX_MODEL_ID_BY_TIER == {
125
+ ADVISOR_MODEL_TIER: ADVISOR_CODEX_MODEL_ID,
126
+ }
105
127
 
106
128
 
107
129
  def test_canonical_tier_name_strips_and_normalizes() -> None:
@@ -45,6 +45,9 @@ from advisor_scripts_constants.model_tier_run_validator_constants import ( # no
45
45
  UNKNOWN_HOST_PROFILE_ERROR,
46
46
  UNKNOWN_LADDER_NAME_ERROR,
47
47
  )
48
+ from advisor_scripts_constants.advisor_route_constants import ( # noqa: E402
49
+ ALL_CODEX_MODEL_ID_BY_TIER,
50
+ )
48
51
 
49
52
 
50
53
  def canonical_tier_name(tier_name: str) -> str | None:
@@ -111,6 +114,27 @@ def resolve_cli_model_id(tier: str) -> str:
111
114
  return maybe_model_alias
112
115
 
113
116
 
117
+ def resolve_codex_model_id(tier: str) -> str:
118
+ """Return the dated Codex model id for a Codex-backed advisor tier.
119
+
120
+ Args:
121
+ tier: Ladder tier name whose Codex model id should be resolved.
122
+
123
+ Returns:
124
+ The configured Codex model id.
125
+
126
+ Raises:
127
+ ValueError: When ``tier`` is not a known Codex-backed tier.
128
+ """
129
+ maybe_canonical_tier = canonical_tier_name(tier)
130
+ if maybe_canonical_tier is None:
131
+ raise ValueError(UNKNOWN_LADDER_NAME_ERROR.format(tier))
132
+ maybe_model_id = ALL_CODEX_MODEL_ID_BY_TIER.get(maybe_canonical_tier)
133
+ if maybe_model_id is None:
134
+ raise ValueError(UNKNOWN_LADDER_NAME_ERROR.format(tier))
135
+ return maybe_model_id
136
+
137
+
114
138
  def detect_host_profile(
115
139
  setting_by_name: Mapping[str, str] | None = None,
116
140
  ) -> str:
@@ -15,6 +15,7 @@ Slash-command definitions installed into `~/.claude/commands/` by `bin/install.m
15
15
  | `pr-comments.md` | `/pr-comments` | Fetches and formats PR review comments for response |
16
16
  | `review-plan.md` | `/review-plan` | Reviews the current plan packet against code standards |
17
17
  | `right-size.md` | `/right-size` | Checks an implementation against the Right-Sized Engineering rules |
18
+ | `sr-loop.md` | `/sr-loop` | Runs the converging cleanup loop: /simplify passes until clean, then a code-review fix pass |
18
19
  | `sum.md` | `/sum` | Generates a formatted session summary for quick pickup in a new session |
19
20
 
20
21
  ## Format
@@ -0,0 +1,48 @@
1
+ ---
2
+ description: Converging cleanup loop - repeat /simplify until clean, then repeat /code-review --fix until clean
3
+ argument-hint: [PR URL, branch, or blank for the current diff]
4
+ ---
5
+
6
+ Run the converging cleanup loop on the target: `$ARGUMENTS` (blank means the
7
+ current branch's diff). Each phase invokes an existing skill with the Skill
8
+ tool and repeats it until a pass returns zero new findings.
9
+
10
+ ## Phase A — loop /simplify
11
+
12
+ 1. Invoke the `simplify` skill on the target (the same review the user gets
13
+ from `/simplify <target>`). Let it run its 4-lens fan-out and apply its
14
+ fixes.
15
+ 2. After each pass: run the scoped test suite (test files beside the touched
16
+ code, not the full repo suite), commit once (`git commit -F <file>`, body
17
+ written with the Write tool, Co-Authored-By line, 10-minute timeout — the
18
+ pre-commit gate runs its own tests), and push to the PR head branch. The PR
19
+ stays draft.
20
+ 3. Repeat the invocation. **Skips are sticky:** carry every adjudicated skip
21
+ forward into the next pass as "already adjudicated — do not re-report: ..."
22
+ context, or the loop never converges.
23
+ 4. Phase A converges when a full pass returns zero new findings. When the
24
+ previous pass changed only a line or two, a single combined-lens
25
+ confirmation agent may serve as the final pass.
26
+
27
+ ## Phase B — loop /code-review low --fix
28
+
29
+ 1. Invoke the `code-review` skill with arguments `low --fix` on the same
30
+ target. Let it report findings and apply its fixes.
31
+ 2. After any pass that changed files: test, commit, push as in Phase A.
32
+ 3. Repeat until a pass reports zero findings. Phase B usually converges in one
33
+ pass when Phase A ran first.
34
+
35
+ ## Finish
36
+
37
+ Report: passes run per phase, commits pushed with hashes, fixes applied, and
38
+ the standing skip list with reasons.
39
+
40
+ ## Constraints (observed under headless runs)
41
+
42
+ - Run this loop in the main session. A wrapper subagent cannot see the
43
+ `code-review` skill, and a nested agent's own subagent reports route to the
44
+ main session instead of back to it.
45
+ - Scope test runs to the touched files; a full-suite run can outlive one
46
+ foreground tool call.
47
+ - A hung or newly slow test suite is a finding to investigate, not an
48
+ inconvenience.
@@ -10,7 +10,8 @@ Pointer documents to external sources, standard terminology, and internal tool o
10
10
  | `code-review-enforcement.md` | How the code-review gates work: the two required efforts (push at low, PR creation at xhigh), the stamp bound to the branch-surface hash, the single sanctioned minter, the two-layer stamp-directory guard, and the bypass surfaces the gates leave open |
11
11
  | `prose-style-enforcement.md` | How `CLAUDE_PROSE_STYLE_ENFORCEMENT` arms opinionated prose gates (default off) while AskUserQuestion lean-block stays always on |
12
12
  | `advisor-tool.md` | Canonical consult bones for any stronger reviewer: when to call, hard rule before first write, how to treat advice; maps to the Anthropic advisor tool |
13
- | `team-advisor-skill.md` | `/team-advisor` map: sole-consumer warm bind, ref index, and how it pairs with `advisor()` |
13
+ | `team-advisor-skill.md` | `/team-advisor` map: sole-consumer warm bind, ref index, and advisor selection |
14
+ | `weak-executor-advisor.md` | Consult profile a below-advisor-tier executor (Sonnet, Haiku) follows on top of `advisor-tool.md`: spawn-prompt steering, context packaging, two-timing rule, consult budget, failure branches |
14
15
 
15
16
  ## Role
16
17
 
@@ -1,14 +1,14 @@
1
1
  # Advisor Tool
2
2
 
3
- Canonical consult timing and weight for any stronger-reviewer path: the native `advisor()` tool, `/team-advisor`, and the shared warm advisor.
3
+ Canonical consult timing and weight for the repository advisor path: `/team-advisor` and the shared warm advisor. Anthropic's advisor documentation supplies the source guidance for packet shape and review timing.
4
4
 
5
5
  Source bones: [Anthropic Advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool) (Suggested system prompt for coding tasks). API shape, model pairs, cost, and caching live there. This file carries only the call rules a session needs every time.
6
6
 
7
7
  ## What it is
8
8
 
9
- `advisor()` is a no-parameter review call. The platform forwards the full conversation (task, tool calls, results) to a stronger model. The executor continues with that guidance.
9
+ `/team-advisor` is the repository's advisor implementation. It carries the full first packet explicitly, sends later deltas, and owns the warm Agent/SendMessage or read-only Sol CLI lifecycle.
10
10
 
11
- When `advisor()` is absent, use `/team-advisor` (see `team-advisor-skill.md`).
11
+ See `team-advisor-skill.md` for the bind and lifecycle map.
12
12
 
13
13
  ## When to call
14
14
 
@@ -18,11 +18,11 @@ If the task needs orientation first (find files, fetch a source, see what exists
18
18
 
19
19
  Also call:
20
20
 
21
- - **When you believe the task is complete.** Before this call, make the deliverable durable: write the file, save the result, commit the change. The call takes time; if the session ends during it, a durable result survives and an unwritten one does not.
21
+ - **When you believe the task is complete.** Before this call, make the deliverable durable: write the file, save the result, commit the change. The call takes time; if the session ends during it, a durable result survives and an unwritten one does not. Ask the advisor to hunt for missing requirements, untested behavior, wrong assumptions, unhandled edge cases, evidence gaps, and early completion claims.
22
22
  - **When stuck** — errors recur, approach does not converge, results do not fit.
23
23
  - **When considering a change of approach.**
24
24
 
25
- On tasks longer than a few steps, call at least once before committing to an approach and once before declaring done. On short reactive tasks where the next action is dictated by tool output you just read, you do not need repeated calls most value is on the first call, before the approach hardens.
25
+ On tasks longer than a few steps, aim for an early approach consult and a completion review. Reserve a third consult for recovery or reconciliation, and add consults when material new evidence or forks arise. This cadence guides planning and leaves the task free to follow its evidence. Short reactive tasks may use the single consult that best fits the live decision.
26
26
 
27
27
  Call for design, architecture, and risk questions where you will not touch a file. If the response would be analysis or a recommendation with no other tool calls, call first. That judgment is where a second opinion is highest value. Simple factual lookups and arithmetic do not need a call.
28
28
 
@@ -34,7 +34,22 @@ Your first write, edit, or state-changing shell call on a task must be preceded
34
34
 
35
35
  Give the advice serious weight. If a step fails empirically, or primary-source evidence contradicts a claim (the file says X, the paper states Y), adapt. A passing self-test is not evidence the advice is wrong — it is evidence the test does not check what the advice is checking.
36
36
 
37
- If your data points one way and the advisor points another: do not silently switch. Surface the conflict in one more call — "I found X, you suggest Y, which constraint breaks the tie?" The advisor saw the evidence but may have underweighted it; a reconcile call is cheaper than the wrong branch.
37
+ If your data points one way and the advisor points another: do not silently switch. Surface the conflict in one more call — "I found X, you suggest Y, which constraint breaks the tie?" A reconcile call is cheaper than the wrong branch.
38
+
39
+ Work a disagreement in this order: keep the observed evidence in the record, name the conflict plainly, ask the advisor which constraint breaks the tie, then act on the reconciled plan.
40
+
41
+ ## Escalation shapes
42
+
43
+ Four shapes cover how a harder task gets more strength behind it. Route to the one that matches the work, not by default to the advisor.
44
+
45
+ | Shape | Fits when |
46
+ |---|---|
47
+ | Advisor | The task needs intermittent strategy and review, and one executor keeps the task from start to finish. |
48
+ | Subagent | A piece of the task is a bounded subtask that benefits from its own context and its own loop. |
49
+ | Stronger-model planning phase | The plan needs the strong model's judgment; the fast model can carry it out once written. |
50
+ | Full model switch | Every step of the task needs the stronger tier, not just the hard decisions. |
51
+
52
+ Spawn a subagent when the work is a delegable bounded subtask. Switch the whole task to the stronger model when every turn needs that tier.
38
53
 
39
54
  ## Brevity cue
40
55
 
@@ -42,10 +57,13 @@ When the consult path supports a free-text brief, append:
42
57
 
43
58
  `(Advisor: please keep your guidance under 80 words — I need a focused starting point, not a comprehensive plan.)`
44
59
 
60
+ Size the ask at roughly 80 percent of the true ceiling; direct address to the advisor lands more reliably than a third-person description.
61
+
45
62
  ## Related
46
63
 
47
64
  | Doc | Holds |
48
65
  |---|---|
49
66
  | [Anthropic Advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool) | API shape, model pairs, cost, caching, full best practices |
50
- | `team-advisor-skill.md` | Standing warm advisor when `advisor()` is missing |
51
- | `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, floor walk, lifecycle, executor paste blocks |
67
+ | `team-advisor-skill.md` | Standing warm advisor for this repository |
68
+ | `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, floor walk, lifecycle a read map routes each bind or consult moment to its `reference/` detail file |
69
+ | `weak-executor-advisor.md` | Consult deltas for an executor spawned below the advisor's own tier |
@@ -1,6 +1,6 @@
1
1
  # Team-Advisor Skill
2
2
 
3
- `/team-advisor` binds one standing warm advisor for this session at the strongest reachable tier. Use it when `advisor()` is absent, or when you want a standing four-signal reviewer across many decision points.
3
+ `/team-advisor` binds one standing warm advisor for this session at the strongest reachable tier. This skill is the selected custom reproduction path for advisor behavior: it forwards explicit packets to a warm Agent/SendMessage advisor or the read-only `codex_sol_advisor.py` path across many decision points.
4
4
 
5
5
  ## Refs
6
6
 
@@ -15,6 +15,6 @@
15
15
 
16
16
  Follow the call rules in `advisor-tool.md` (orientation first, then consult before substantive work; durable deliverable before the completion consult; stuck or reapproach; long tasks twice).
17
17
 
18
- ## Relation to `advisor()`
18
+ ## Selected path
19
19
 
20
- `/team-advisor` works with no `advisor()` tool. When both exist: `advisor()` for a fast history-forwarded check; `/team-advisor` for a standing named reviewer consulted at the same cadence.
20
+ `/team-advisor` is the repository's advisor implementation. It provides explicit first-consult packets, delta consults, a standing warm reviewer, and a read-only Sol CLI option.
@@ -0,0 +1,91 @@
1
+ # Weak-Executor Advisor Profile
2
+
3
+ Consult profile for an executor spawned below the advisor's own tier — a
4
+ Sonnet or Haiku model carrying an advisor bind. `advisor-tool.md` sets the
5
+ canonical cadence for every consumer; this file adds the deltas a below-tier
6
+ executor needs on top of it.
7
+
8
+ Source: [Anthropic Advisor tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/advisor-tool)
9
+ (Suggested system prompt for coding tasks). The distilled facts behind each
10
+ section live in
11
+ `skills/team-advisor/reference/advisor-docs-review.md`.
12
+
13
+ ## Scope
14
+
15
+ Applies to any executor running below the advisor's tier. A same-tier or
16
+ stronger executor follows `advisor-tool.md` alone. The paste-ready form of
17
+ this profile is the **Weak-executor add-on** block in
18
+ `~/.claude/_shared/advisor/reference/advisor-block.md`.
19
+
20
+ ## Steering lives in the spawn prompt
21
+
22
+ The advisor rules sit at the top of the spawn prompt, ahead of every other
23
+ sentence that mentions the advisor — the spawn prompt is the one steering
24
+ surface with measured effect on Sonnet.
25
+
26
+ ## Context packaging
27
+
28
+ Everything the advisor learns arrives inside the consult. Each consult
29
+ carries its own packet:
30
+
31
+ - **First consult** — use the complete packet in
32
+ `~/.claude/_shared/advisor/reference/consult-format.md`: assignment,
33
+ desired outcome, constraints and exclusions, actions taken in order, real
34
+ output and current state, decision or blocker, validation evidence,
35
+ unresolved risks, and load-bearing paths or excerpts.
36
+ - **Later consults** — the delta since the last consult.
37
+ - **Ordering** — stable role and charter text first, volatile detail last.
38
+
39
+ ## Two-timing rule
40
+
41
+ Two consult moments carry the measured gain:
42
+
43
+ 1. **Early** — after a few exploratory reads land in the transcript, before
44
+ the first write. This is the hard rule `advisor-tool.md` §Hard rule
45
+ states for every consumer.
46
+ 2. **Final** — after file writes and test output exist to forward. Make the
47
+ deliverable durable first (write the file, save the result, commit the
48
+ change), then consult.
49
+
50
+ ## Planner funnel
51
+
52
+ Consult the advisor before any task-list or planner tool. The advisor's plan
53
+ becomes the task list.
54
+
55
+ ## Consult budget
56
+
57
+ Aim for two consults per task: early orientation and completion review. Reserve a third for advisory recovery or reconciliation guidance, and add a consult when a material fork produces new evidence. This is a planning target that leaves the task free to follow its evidence.
58
+
59
+ ## Advice weight
60
+
61
+ Advice is binding absent empirical contradiction. A conflict between the
62
+ executor's own evidence and the advisor's guidance goes back to the advisor
63
+ as a reconcile consult. See `advisor-tool.md` §How to treat advice for the
64
+ full weighing rule.
65
+
66
+ ## Long-run reminder
67
+
68
+ On a run past roughly 20 advisor-free turns, the executor re-reads its
69
+ advisor rules before the next substantive step — the re-read keeps the
70
+ advisor visible across a long horizon.
71
+
72
+ ## Failure branches
73
+
74
+ - **Transient advisor failure** — retry once, then carry on with the
75
+ evidence in hand and record the gap in the result.
76
+ - **Advisor unreachable** — report upward and hold the decision for the
77
+ owning session; re-binding belongs to that session alone.
78
+
79
+ ## Pairing invariant
80
+
81
+ The advisor binds at or above the strongest consumer's tier. The floor
82
+ holds at that tier whichever executor joins the pairing.
83
+
84
+ ## Related
85
+
86
+ | Doc | Holds |
87
+ |---|---|
88
+ | `advisor-tool.md` | Canonical consult cadence, hard rule, brevity cue |
89
+ | `~/.claude/_shared/advisor/advisor-protocol.md` | Host bind, model floor, and the Advisor-block assembly rule |
90
+ | `~/.claude/_shared/advisor/reference/advisor-block.md` | The paste parts — transport preambles, shared core, weak-executor add-on |
91
+ | `skills/team-advisor/reference/advisor-docs-review.md` | Distilled source facts behind each section above |
@@ -11,8 +11,9 @@ field, pass whether or not the marker is present. One test reads
11
11
  spawn tool names.
12
12
 
13
13
  Token pins read the warm-up section and each consuming skill. Two doc-gate
14
- agreement tests assemble a spawn prompt out of the advisor-protocol wording a
15
- warm-up bind and a drift re-spawn follow, and run each through the gate, so
14
+ agreement tests assemble a spawn prompt out of the advisor reference wording a
15
+ warm-up bind (``reference/warm-up.md``) and a drift re-spawn
16
+ (``reference/lifecycle.md``) follow, and run each through the gate, so
16
17
  wording that stops naming the marker fails here. Two deny-path tests read the
17
18
  preview the gate hands the block logger and hold it bounded and scoped to the
18
19
  model field.
@@ -64,6 +65,13 @@ _FULL_SONNET_MODEL_ID = "claude-sonnet-4-5"
64
65
  _PACKAGE_ROOT = _HOOKS_TREE.parent
65
66
  _ADVISOR_PROTOCOL_PATH = _PACKAGE_ROOT / "_shared" / "advisor" / "advisor-protocol.md"
66
67
  _ADVISOR_PROTOCOL_TEXT = _ADVISOR_PROTOCOL_PATH.read_text(encoding="utf-8")
68
+ _ADVISOR_REFERENCE_DIR = _PACKAGE_ROOT / "_shared" / "advisor" / "reference"
69
+ _ADVISOR_LIFECYCLE_TEXT = (_ADVISOR_REFERENCE_DIR / "lifecycle.md").read_text(
70
+ encoding="utf-8"
71
+ )
72
+ _ADVISOR_WARM_UP_TEXT = (_ADVISOR_REFERENCE_DIR / "warm-up.md").read_text(
73
+ encoding="utf-8"
74
+ )
67
75
  _ALL_CONSUMING_SKILL_NAMES = ("team-advisor", "orchestrator", "orchestrator-refresh")
68
76
  _ALL_CONSUMING_SKILL_PATHS = tuple(
69
77
  _PACKAGE_ROOT / "skills" / each_skill_name / "SKILL.md"
@@ -321,19 +329,18 @@ def test_consuming_skill_names_the_marker_token(skill_path: pathlib.Path) -> Non
321
329
  assert FABLE_SPAWN_AUTHORIZATION_MARKER in skill_path.read_text(encoding="utf-8")
322
330
 
323
331
 
324
- def _paragraph_starting_at(paragraph_marker: str) -> str:
325
- """Return the advisor-protocol paragraph that opens with a marker.
332
+ def _paragraph_starting_at(source_text: str, paragraph_marker: str) -> str:
333
+ """Return the advisor-doc paragraph that opens with a marker.
326
334
 
327
335
  Args:
336
+ source_text: The advisor document text holding the paragraph.
328
337
  paragraph_marker: The literal text opening the paragraph.
329
338
 
330
339
  Returns:
331
340
  The paragraph text, running from that marker to the blank line that
332
341
  closes it.
333
342
  """
334
- paragraph_body = _ADVISOR_PROTOCOL_TEXT[
335
- _ADVISOR_PROTOCOL_TEXT.index(paragraph_marker) :
336
- ]
343
+ paragraph_body = source_text[source_text.index(paragraph_marker) :]
337
344
  paragraph_end = paragraph_body.find(_PARAGRAPH_SEPARATOR)
338
345
  if paragraph_end < 0:
339
346
  return paragraph_body
@@ -341,7 +348,7 @@ def _paragraph_starting_at(paragraph_marker: str) -> str:
341
348
 
342
349
 
343
350
  def _respawn_spawn_prompt() -> str:
344
- """Assemble the spawn prompt a drift re-spawn writes from the protocol.
351
+ """Assemble the spawn prompt a drift re-spawn writes from the lifecycle doc.
345
352
 
346
353
  The prompt comes from the re-spawn paragraph alone, so the gate reads
347
354
  what that one paragraph tells a session to send.
@@ -349,7 +356,7 @@ def _respawn_spawn_prompt() -> str:
349
356
  Returns:
350
357
  The spawn prompt text a session following that paragraph sends.
351
358
  """
352
- return _paragraph_starting_at(_RESPAWN_PARAGRAPH_MARKER)
359
+ return _paragraph_starting_at(_ADVISOR_LIFECYCLE_TEXT, _RESPAWN_PARAGRAPH_MARKER)
353
360
 
354
361
 
355
362
  def test_respawn_paragraph_prompt_passes_the_gate_at_the_fable_tier() -> None:
@@ -358,7 +365,7 @@ def test_respawn_paragraph_prompt_passes_the_gate_at_the_fable_tier() -> None:
358
365
 
359
366
 
360
367
  def _warm_up_spawn_prompt() -> str:
361
- """Assemble the spawn prompt a warm-up bind writes from the protocol.
368
+ """Assemble the spawn prompt a warm-up bind writes from the warm-up doc.
362
369
 
363
370
  The prompt comes from the spawn-field prompt bullet alone, so the gate
364
371
  reads what that one bullet tells a session to send.
@@ -366,7 +373,7 @@ def _warm_up_spawn_prompt() -> str:
366
373
  Returns:
367
374
  The spawn prompt text a session following that bullet sends.
368
375
  """
369
- return _paragraph_starting_at(_WARM_UP_PROMPT_BULLET_MARKER)
376
+ return _paragraph_starting_at(_ADVISOR_WARM_UP_TEXT, _WARM_UP_PROMPT_BULLET_MARKER)
370
377
 
371
378
 
372
379
  def test_warm_up_prompt_bullet_passes_the_gate_at_the_fable_tier() -> None:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,4 +6,4 @@
6
6
 
7
7
  @~/.claude/_shared/advisor/advisor-protocol.md
8
8
 
9
- Scripts: `~/.claude/_shared/advisor/scripts/` (`model_tier_run_validator.py`, `tier_model_ids.py`, constants under `scripts/config/`).
9
+ Scripts: `~/.claude/_shared/advisor/scripts/` (`model_tier_run_validator.py`, `codex_sol_advisor.py`, `tier_model_ids.py`, constants under `scripts/config/`).
@@ -4,6 +4,8 @@
4
4
 
5
5
  @~/.claude/_shared/advisor/scripts/model_tier_run_validator.py
6
6
 
7
+ @~/.claude/_shared/advisor/scripts/codex_sol_advisor.py
8
+
7
9
  @~/.claude/_shared/advisor/scripts/tier_model_ids.py
8
10
 
9
11
  Full tree: `~/.claude/_shared/advisor/scripts/`.
@@ -43,7 +43,7 @@ The user types `/grokify`, alone or with guidance.
43
43
 
44
44
  - **Bind once, first:** charter + findings + constraints + plan piped from a temp file into `claude -p --model fable --effort high --output-format json`; parse and save `session_id` from the JSON reply.
45
45
  - **Consult:** brief piped into `claude -p --resume <session_id> --model fable --effort high --output-format json`.
46
- - **ConsultB** If fable is unavailable, use opus with max effort: `claude -p --resume <session_id> --model opus --effort max --output-format json`.
46
+ - **ConsultB** If fable is unavailable, use opus with xhigh effort: `claude -p --resume <session_id> --model opus --effort xhigh --output-format json`.
47
47
  - **Signals:** every advisor reply opens with exactly one of ENDORSE, CORRECTION, PLAN, or STOP. CORRECTION and PLAN are actions to take, with a report-back in the next consult on that topic. STOP halts that line of work and surfaces it to the user. When the CLI is unreachable, Grok stops and says so — it never self-endorses in the advisor's place.
48
48
  - **Cadence, mandatory:** after planning and before any edit; per phase before implementation (TDD red + approach) and after (diff, tests, acceptance evidence); before every `git commit` and `git push`; on every user-facing fork before asking; on any twice-repeated failure or stall.
49
49
 
@@ -43,7 +43,7 @@ CONFIRM THESE WITH THE USER FIRST, VIA ASKUSERQUESTION, BEFORE EMBEDDING]
43
43
  append the full Established findings, Hard constraints, and Plan sections of this
44
44
  document to the same file.
45
45
  2. Bind: `claude -p --model fable --effort high --output-format json < <charter-file>`
46
- 2a. If 2 fails, replace fable with opus, effort high to max.
46
+ 2a. If 2 fails, replace fable with opus, effort high to xhigh.
47
47
  3. The JSON output is an array of events, not one object. Take `session_id` from any
48
48
  event; the reply text is the `type == "result"` event's `.result` field. Persist
49
49
  `session_id`, the repo root, and the cwd to a state file at once.
@@ -56,7 +56,7 @@ CONFIRM THESE WITH THE USER FIRST, VIA ASKUSERQUESTION, BEFORE EMBEDDING]
56
56
  session, not a model failure.
57
57
 
58
58
  **Consult (every time):** write the brief to a temp file, then
59
- `claude -p --resume <session_id> --model fable (or opus) --effort high (max for opus) --output-format json < <brief-file>`.
59
+ `claude -p --resume <session_id> --model fable (or opus) --effort high (xhigh for opus) --output-format json < <brief-file>`.
60
60
  Act on the reply's opening signal: ENDORSE — proceed. CORRECTION — apply it first;
61
61
  your next consult on that topic opens with what happened. PLAN — adopt it; same
62
62
  report-back rule. STOP — halt that line of work and surface it to the user. Never
@@ -193,7 +193,7 @@ Touch only: <files or globs>
193
193
  Done when: <one mechanical check — a command, a test, a diff scope>
194
194
  Return: status, artifact paths, blockers — nothing else.
195
195
 
196
- <host-matched Advisor block from advisor-protocol.md, advisor name filled in>
196
+ <Advisor block assembled per _shared/advisor/reference/advisor-block.md advisor name filled in>
197
197
  ```
198
198
 
199
199
  - **Size the task by its done-check.** The right task is the largest
@@ -218,9 +218,10 @@ Return: status, artifact paths, blockers — nothing else.
218
218
  table picks the definition, and `clean-coder` already holds the code
219
219
  discipline. The ticket adds the task, the pointers, and the Advisor
220
220
  block only.
221
- - **The Advisor block is the one pasted paragraph.** It is host-matched
222
- at bind time and written to be self-contained (the protocol's Advisor
223
- block section) — paste it; do not point at it.
221
+ - **The Advisor block is pasted, assembled text.** Assemble it at bind
222
+ time from the parts in
223
+ [`_shared/advisor/reference/advisor-block.md`](../../_shared/advisor/reference/advisor-block.md)
224
+ and paste the assembled text itself into the ticket.
224
225
 
225
226
  ## Workflow Agent Routing
226
227