@ai-dev-methodologies/rlp-desk 0.14.4 → 0.14.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-dev-methodologies/rlp-desk",
3
- "version": "0.14.4",
3
+ "version": "0.14.6",
4
4
  "description": "Fresh-context iterative loops for Claude Code — autonomous task completion with independent verification",
5
5
  "scripts": {
6
6
  "postinstall": "node scripts/postinstall.js",
@@ -89,6 +89,14 @@ Ask about these items one by one (or in small groups):
89
89
  - **gpt-5.5:medium** — default recommendation (full context window, progressive upgrade handles harder US)
90
90
  - **spark:high** — only when US is small enough for spark's 100k context (single-file, AC count <= 4, simple logic). Do NOT use as primary recommendation — spark context window is too small for most tasks
91
91
 
92
+ **Context window behavior (claude models — v0.14.6+)**:
93
+ - All claude models default to **200K**. `sonnet` and `opus` aliases both run at the standard window.
94
+ - To request 1M, append the explicit `[1m]` suffix on the full model id:
95
+ - `claude-opus-4-7[1m]` — 1M attempted via `ANTHROPIC_BETA=context-1m-2025-08-07`. Works on most Claude Max accounts.
96
+ - `claude-sonnet-4-6[1m]` — 1M attempted, **but** requires the Anthropic "Extra usage" toggle at https://claude.ai/settings/usage. Without that toggle the worker fails at the first API call with `Extra usage is required for 1M context`.
97
+ - rlp-desk does NOT pre-check entitlement — the explicit `[1m]` is honored as-is. If the API rejects it, you will see the error immediately and can re-run with the standard alias or the opus 1M form.
98
+ - **Default recommendation when 1M is genuinely needed:** prefer `claude-opus-4-7[1m]` over `claude-sonnet-4-6[1m]` because opus 1M does not require a separate entitlement toggle.
99
+
92
100
  Present complexity score with evidence to the user, e.g.: "I rate this MEDIUM because: US count=4 (MEDIUM), file scope=2 (MEDIUM), logic=conditionals (MEDIUM), deps=none (LOW), impact=modify (MEDIUM). Highest=MEDIUM."
93
101
 
94
102
  **If codex IS installed** — say: "Codex is installed. I recommend cross-engine Worker for cost savings (Pro token pool separation) and cross-engine blind-spot coverage (claude Verifier catches issues codex Worker misses)."
@@ -1,5 +1,5 @@
1
1
  import { shellQuote } from '../util/shell-quote.mjs';
2
- import { OPUS_1M_BETA, isOpusModel } from '../constants.mjs';
2
+ import { ONE_MILLION_BETA, wantsOneMillionContext } from '../constants.mjs';
3
3
 
4
4
  const CLAUDE_BIN = 'claude';
5
5
  const CODEX_BIN = 'codex';
@@ -32,12 +32,14 @@ function assertTuiMode(mode, builderName) {
32
32
  export function buildClaudeCmd(mode, model, options = {}) {
33
33
  assertTuiMode(mode, 'buildClaudeCmd');
34
34
 
35
- // v5.7 §4.9: auto-enable 1M-token context for Opus models. Long campaigns
36
- // no longer silently truncate at 200K. Header is benign for non-Opus calls
37
- // but we omit it there to keep the cmdline tidy.
35
+ // v0.14.6: 1M context is opt-in only via the explicit '[1m]' suffix.
36
+ // opus / sonnet / claude-opus-4-7 (no suffix) all run at the standard
37
+ // 200K context. Adding '[1m]' on either opus or sonnet model id injects
38
+ // the ANTHROPIC_BETA header and attempts the 1M window — sonnet[1m] still
39
+ // requires Anthropic "Extra usage" entitlement at the API layer.
38
40
  const parts = ['DISABLE_OMC=1'];
39
- if (isOpusModel(model)) {
40
- parts.push(`ANTHROPIC_BETA=${shellQuote(OPUS_1M_BETA)}`);
41
+ if (wantsOneMillionContext(model)) {
42
+ parts.push(`ANTHROPIC_BETA=${shellQuote(ONE_MILLION_BETA)}`);
41
43
  }
42
44
  parts.push(
43
45
  CLAUDE_BIN,
@@ -1,19 +1,21 @@
1
1
  // Shared runtime constants. Single-source for cross-module values.
2
2
 
3
- // Anthropic Claude API beta header that activates the 1M-token context window
4
- // for Opus models. Auto-prepended to every claude CLI invocation that uses
5
- // --model opus so long campaigns no longer silently truncate at 200K.
3
+ // Anthropic Claude API beta header for the 1M-token context window. Injected
4
+ // only when the user explicitly opts in via the '[1m]' suffix on the model
5
+ // id see wantsOneMillionContext() below.
6
6
  //
7
7
  // Docs: https://docs.anthropic.com/en/docs/build-with-claude/context-windows
8
8
  // (search "1M context") — header rotates with each beta phase.
9
- export const OPUS_1M_BETA = 'context-1m-2025-08-07';
9
+ export const ONE_MILLION_BETA = 'context-1m-2025-08-07';
10
10
 
11
- // Model id that triggers Opus 1M auto-enable. Plain string match against the
12
- // --model value (post-shellQuote stripping). Bracketed form
13
- // 'claude-opus-4-7[1m]' is also Opus and benefits from this; pattern match
14
- // covers both.
15
- export function isOpusModel(model) {
11
+ // v0.14.6: 1M context is opt-in only via the explicit '[1m]' suffix on the
12
+ // model id. Previously rlp-desk auto-injected ANTHROPIC_BETA for any opus
13
+ // model; in practice that produced surprising results (opus alias still
14
+ // reported a 200K window in real CLI calls, and sonnet[1m] requires a
15
+ // separate "Extra usage" entitlement). New rule: user is the source of
16
+ // truth. Type the suffix to opt in; otherwise both opus and sonnet run at
17
+ // the standard 200K context.
18
+ export function wantsOneMillionContext(model) {
16
19
  if (!model) return false;
17
- const m = String(model).toLowerCase();
18
- return m === 'opus' || m.startsWith('claude-opus-');
20
+ return String(model).toLowerCase().endsWith('[1m]');
19
21
  }
@@ -7,7 +7,7 @@ import { promisify } from 'node:util';
7
7
 
8
8
  import { buildClaudeCmd, buildCodexCmd, parseModelFlag } from '../cli/command-builder.mjs';
9
9
  import { shellQuote } from '../util/shell-quote.mjs';
10
- import { OPUS_1M_BETA, isOpusModel } from '../constants.mjs';
10
+ import { ONE_MILLION_BETA, wantsOneMillionContext } from '../constants.mjs';
11
11
  import { initCampaign } from '../init/campaign-initializer.mjs';
12
12
  import { LEGACY_DESK_REL, resolveDeskRoot } from '../util/desk-root.mjs';
13
13
  import { writeSentinelExclusive } from '../shared/fs.mjs';
@@ -933,9 +933,11 @@ async function runFinalSequentialVerify({
933
933
  const HOME_DESK_DIR = path.join(os.homedir(), '.claude', 'ralph-desk');
934
934
 
935
935
  function buildAutonomousClaudeCmd({ promptFile, model, rootDir, homeDeskDir = HOME_DESK_DIR }) {
936
- // §4.9: ANTHROPIC_BETA prefix for Opus 1M context.
937
- const betaPrefix = isOpusModel(model)
938
- ? `ANTHROPIC_BETA=${shellQuote(OPUS_1M_BETA)} `
936
+ // v0.14.6: ANTHROPIC_BETA prefix injected only when the model id ends
937
+ // with explicit '[1m]' suffix. opus / sonnet / claude-opus-4-7 (no
938
+ // suffix) all run at the standard 200K context.
939
+ const betaPrefix = wantsOneMillionContext(model)
940
+ ? `ANTHROPIC_BETA=${shellQuote(ONE_MILLION_BETA)} `
939
941
  : '';
940
942
  // §4.11.a: --add-dir whitelist (home rlp-desk + campaign cwd) for true autonomy.
941
943
  const addDirParts = [];
@@ -46,17 +46,19 @@ build_claude_cmd() {
46
46
  # Defends against bracketed model ids like 'claude-opus-4-7[1m]' (zsh char-class glob),
47
47
  # spaces, embedded quotes, etc. Plain "$model" would let zsh expand brackets as glob.
48
48
  #
49
- # v5.7 §4.9: auto-enable Opus 1M context window via ANTHROPIC_BETA env. Mirror
50
- # of src/node/constants.mjs OPUS_1M_BETA. Update both on header rotation.
51
- local _opus_beta=""
49
+ # v0.14.6: ANTHROPIC_BETA injected only when the model id ends with the
50
+ # explicit '[1m]' suffix. opus / sonnet / claude-opus-4-7 (no suffix) all
51
+ # run at the standard 200K context. Mirror of src/node/constants.mjs
52
+ # ONE_MILLION_BETA + wantsOneMillionContext(). Update both on rotation.
53
+ local _onem_beta=""
52
54
  case "$model" in
53
- opus|claude-opus-*) _opus_beta="ANTHROPIC_BETA='context-1m-2025-08-07' " ;;
55
+ *\[1m\]) _onem_beta="ANTHROPIC_BETA='context-1m-2025-08-07' " ;;
54
56
  esac
55
57
  # v5.7 §4.11.a: --add-dir whitelist for autonomous mode. ROOT (campaign cwd)
56
58
  # plus home rlp-desk tree authorized for read/write without TUI prompts.
57
59
  local _home_desk="$HOME/.claude/ralph-desk"
58
60
  local _add_dirs="--add-dir ${(qq)_home_desk} --add-dir ${(qq)ROOT}"
59
- local base="DISABLE_OMC=1 ${_opus_beta}$CLAUDE_BIN --model ${(qq)model} --mcp-config '{\"mcpServers\":{}}' --strict-mcp-config --dangerously-skip-permissions ${_add_dirs}"
61
+ local base="DISABLE_OMC=1 ${_onem_beta}$CLAUDE_BIN --model ${(qq)model} --mcp-config '{\"mcpServers\":{}}' --strict-mcp-config --dangerously-skip-permissions ${_add_dirs}"
60
62
  if [[ -n "$effort" ]]; then
61
63
  base="$base --effort $effort"
62
64
  fi
@@ -1508,6 +1508,28 @@ _verifier_pane_has_verdict() {
1508
1508
  return 1
1509
1509
  }
1510
1510
 
1511
+ # v0.14.5 Bug Report #6 Fix-M (worker mirror of Fix-A/Fix-D):
1512
+ # Worker (claude sonnet 1m) writes commit + iter-signal.json verify signal
1513
+ # then claude CLI parks at its idle prompt. check_no_progress observes
1514
+ # byte-stasis on the worker pane and would BLOCK after 600s even though
1515
+ # the signal is on disk. When the pane is the worker pane AND a valid
1516
+ # iter-signal is on disk, defer to the harvest step (poll_for_signal in
1517
+ # run_single_worker) instead of escalating BLOCKED.
1518
+ _worker_pane_has_signal() {
1519
+ local pane_id="$1"
1520
+ [[ -n "${WORKER_PANE:-}" && "$pane_id" == "${WORKER_PANE}" ]] || return 1
1521
+ [[ -n "${SIGNAL_FILE:-}" && -s "$SIGNAL_FILE" ]] || return 1
1522
+ jq -e . "$SIGNAL_FILE" >/dev/null 2>&1 || return 1
1523
+ local iter_field us_field status_field
1524
+ iter_field=$(jq -r '.iteration // empty' "$SIGNAL_FILE" 2>/dev/null)
1525
+ us_field=$(jq -r '.us_id // empty' "$SIGNAL_FILE" 2>/dev/null)
1526
+ status_field=$(jq -r '.status // empty' "$SIGNAL_FILE" 2>/dev/null)
1527
+ [[ "$iter_field" =~ ^[0-9]+$ ]] || return 1
1528
+ [[ -n "$us_field" ]] || return 1
1529
+ [[ "$status_field" == "verify" || "$status_field" == "verify_partial" ]] || return 1
1530
+ return 0
1531
+ }
1532
+
1511
1533
  # v5.7 §4.17 (codex Critic HIGH): generic no-progress timeout — independent
1512
1534
  # of prompt detection. Closes the gap where an undetected prompt or alive-
1513
1535
  # but-frozen Worker can bypass Layer 4 and infinite-wait.
@@ -1534,6 +1556,16 @@ check_no_progress() {
1534
1556
  PANE_LAST_CHANGE_TS[$pane_id]=$now
1535
1557
  return 0
1536
1558
  fi
1559
+ # v0.14.5 Bug Report #6 Fix-M: claude worker finishes (commit + iter-signal
1560
+ # write) then parks at its idle prompt. byte-stasis would BLOCK after 600s
1561
+ # even though the signal is on disk. Worker mirror of the verifier branch
1562
+ # above — defer to poll_for_signal harvest when SIGNAL_FILE is valid.
1563
+ if _worker_pane_has_signal "$pane_id"; then
1564
+ PANE_LAST_CONTENT_FOR_PROGRESS[$pane_id]="$capture"
1565
+ PANE_LAST_CHANGE_TS[$pane_id]=$now
1566
+ log_debug "[GOV] iter=${ITERATION:-0} worker_progress_check=signal_present pane=$pane_id signal=${SIGNAL_FILE}"
1567
+ return 0
1568
+ fi
1537
1569
  # v0.14.2: root-cause tracing for Bug Report #4. When the watcher is
1538
1570
  # examining a verifier pane that does NOT have a verdict yet, log once
1539
1571
  # per byte-stasis transition so post-mortem can tell whether the