instar 1.3.468 → 1.3.469

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 (67) hide show
  1. package/dist/commands/init.js +5 -0
  2. package/dist/commands/init.js.map +1 -1
  3. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  4. package/dist/config/ConfigDefaults.js +12 -0
  5. package/dist/config/ConfigDefaults.js.map +1 -1
  6. package/dist/core/EscalationGovernor.d.ts +138 -0
  7. package/dist/core/EscalationGovernor.d.ts.map +1 -0
  8. package/dist/core/EscalationGovernor.js +308 -0
  9. package/dist/core/EscalationGovernor.js.map +1 -0
  10. package/dist/core/ModelSwapService.d.ts +116 -0
  11. package/dist/core/ModelSwapService.d.ts.map +1 -0
  12. package/dist/core/ModelSwapService.js +266 -0
  13. package/dist/core/ModelSwapService.js.map +1 -0
  14. package/dist/core/ModelTierEscalation.d.ts +128 -0
  15. package/dist/core/ModelTierEscalation.d.ts.map +1 -0
  16. package/dist/core/ModelTierEscalation.js +232 -0
  17. package/dist/core/ModelTierEscalation.js.map +1 -0
  18. package/dist/core/PostUpdateMigrator.d.ts +3 -1
  19. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  20. package/dist/core/PostUpdateMigrator.js +313 -1
  21. package/dist/core/PostUpdateMigrator.js.map +1 -1
  22. package/dist/core/SessionManager.d.ts +5 -0
  23. package/dist/core/SessionManager.d.ts.map +1 -1
  24. package/dist/core/SessionManager.js +9 -4
  25. package/dist/core/SessionManager.js.map +1 -1
  26. package/dist/core/types.d.ts +14 -0
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/core/types.js.map +1 -1
  29. package/dist/monitoring/BurnDetector.d.ts +10 -0
  30. package/dist/monitoring/BurnDetector.d.ts.map +1 -1
  31. package/dist/monitoring/BurnDetector.js +6 -0
  32. package/dist/monitoring/BurnDetector.js.map +1 -1
  33. package/dist/monitoring/GuardPostureTripwire.d.ts +3 -0
  34. package/dist/monitoring/GuardPostureTripwire.d.ts.map +1 -1
  35. package/dist/monitoring/GuardPostureTripwire.js +44 -0
  36. package/dist/monitoring/GuardPostureTripwire.js.map +1 -1
  37. package/dist/monitoring/TokenLedger.d.ts +7 -0
  38. package/dist/monitoring/TokenLedger.d.ts.map +1 -1
  39. package/dist/monitoring/TokenLedger.js +17 -0
  40. package/dist/monitoring/TokenLedger.js.map +1 -1
  41. package/dist/monitoring/UltraSessionCapMonitor.d.ts +61 -0
  42. package/dist/monitoring/UltraSessionCapMonitor.d.ts.map +1 -0
  43. package/dist/monitoring/UltraSessionCapMonitor.js +103 -0
  44. package/dist/monitoring/UltraSessionCapMonitor.js.map +1 -0
  45. package/dist/scaffold/templates.d.ts.map +1 -1
  46. package/dist/scaffold/templates.js +4 -0
  47. package/dist/scaffold/templates.js.map +1 -1
  48. package/dist/server/AgentServer.d.ts +2 -0
  49. package/dist/server/AgentServer.d.ts.map +1 -1
  50. package/dist/server/AgentServer.js +120 -1
  51. package/dist/server/AgentServer.js.map +1 -1
  52. package/dist/server/routes.d.ts +5 -0
  53. package/dist/server/routes.d.ts.map +1 -1
  54. package/dist/server/routes.js +55 -6
  55. package/dist/server/routes.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/data/builtin-manifest.json +83 -67
  58. package/src/scaffold/templates.ts +4 -0
  59. package/src/templates/hooks/model-tier-reconciler.js +137 -0
  60. package/src/templates/hooks/model-tier-skill-entry.sh +72 -0
  61. package/src/templates/hooks/settings-template.json +15 -0
  62. package/upgrades/1.3.469.md +71 -0
  63. package/upgrades/session-mgmt-buildctx-race.eli16.md +9 -0
  64. package/upgrades/side-effects/model-tier-escalation.md +267 -0
  65. package/upgrades/side-effects/session-mgmt-buildctx-race.md +48 -0
  66. package/upgrades/side-effects/watchdog-launchctl-test-guard.md +84 -0
  67. package/upgrades/watchdog-launchctl-test-guard.eli16.md +9 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelTierEscalation.js","sourceRoot":"","sources":["../../src/core/ModelTierEscalation.ts"],"names":[],"mappings":"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"}
@@ -668,7 +668,7 @@ export declare class PostUpdateMigrator {
668
668
  * Get the content of a named hook template.
669
669
  * Used by init.ts to share canonical hook content without duplication.
670
670
  */
671
- getHookContent(name: 'session-start' | 'mcp-health-autorefresh' | 'compaction-recovery' | 'external-operation-gate' | 'deferral-detector' | 'self-stop-guard' | 'slopcheck-guard' | 'post-action-reflection' | 'external-communication-guard' | 'scope-coherence-collector' | 'scope-coherence-checkpoint' | 'claim-intercept' | 'claim-intercept-response' | 'telegram-topic-context' | 'response-review' | 'stop-gate-router' | 'auto-approve-permissions' | 'skill-usage-telemetry' | 'build-stop-hook'): string;
671
+ getHookContent(name: 'session-start' | 'mcp-health-autorefresh' | 'compaction-recovery' | 'external-operation-gate' | 'deferral-detector' | 'self-stop-guard' | 'slopcheck-guard' | 'post-action-reflection' | 'external-communication-guard' | 'scope-coherence-collector' | 'scope-coherence-checkpoint' | 'claim-intercept' | 'claim-intercept-response' | 'telegram-topic-context' | 'response-review' | 'stop-gate-router' | 'auto-approve-permissions' | 'skill-usage-telemetry' | 'build-stop-hook' | 'model-tier-skill-entry' | 'model-tier-reconciler'): string;
672
672
  /** Public accessor for grounding-before-messaging hook content (used by init.ts) */
673
673
  getGroundingBeforeMessagingPublic(): string;
674
674
  /** Public accessor for convergence-check script content (used by init.ts) */
@@ -762,6 +762,8 @@ export declare class PostUpdateMigrator {
762
762
  private getStopGateRouterHook;
763
763
  private getClaimInterceptResponseHook;
764
764
  private getSkillUsageTelemetryHook;
765
+ private getModelTierSkillEntryHook;
766
+ private getModelTierReconcilerHook;
765
767
  private getBuildStopHook;
766
768
  private getAutoApprovePermissionsHook;
767
769
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PostUpdateMigrator.d.ts","sourceRoot":"","sources":["../../src/core/PostUpdateMigrator.ts"],"names":[],"mappings":"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"}
@@ -1322,7 +1322,18 @@ export class PostUpdateMigrator {
1322
1322
  return;
1323
1323
  }
1324
1324
  // Reload only if plist changed (script-only changes don't need launchd touch).
1325
- if (plistChanged) {
1325
+ //
1326
+ // NEVER under a test harness: launchd is a MACHINE-GLOBAL registry that a
1327
+ // $HOME redirect does not scope. Before this guard, every darwin test that
1328
+ // ran migrate() with a redirected HOME booted out the REAL fleet watchdog
1329
+ // and bootstrapped one pointing at the test tmpdir — the RunAtLoad run then
1330
+ // wrote watchdog-launchd.{log,err} into the tmpdir mid-cleanup (the
1331
+ // worktree-spotlight-exclusion ENOTEMPTY flake, 2026-06-09), and after
1332
+ // cleanup the machine's watchdog service pointed at a DELETED plist (fleet
1333
+ // watchdog silently dead until the next real update). File writes above
1334
+ // stay active under tests (hermetic, HOME-scoped); only the launchd
1335
+ // mutation is skipped.
1336
+ if (plistChanged && !process.env.VITEST && process.env.NODE_ENV !== 'test') {
1326
1337
  const uid = process.getuid?.() ?? 501;
1327
1338
  try {
1328
1339
  execFileSync('launchctl', ['bootout', `gui/${uid}`, plistPath], { stdio: 'ignore' });
@@ -2226,6 +2237,23 @@ export class PostUpdateMigrator {
2226
2237
  catch (err) {
2227
2238
  result.errors.push(`skill-usage-telemetry.sh: ${err instanceof Error ? err.message : String(err)}`);
2228
2239
  }
2240
+ // Model-Tier Escalation §5.4 signal hooks (FABLE-MODEL-ESCALATION-SPEC
2241
+ // §10) — built-in instar/ hooks, ALWAYS overwritten on migration so no
2242
+ // agent can get stuck on a broken template.
2243
+ try {
2244
+ fs.writeFileSync(path.join(instarHooksDir, 'model-tier-skill-entry.sh'), this.getModelTierSkillEntryHook(), { mode: 0o755 });
2245
+ result.upgraded.push('hooks/instar/model-tier-skill-entry.sh (model-tier trigger signal)');
2246
+ }
2247
+ catch (err) {
2248
+ result.errors.push(`model-tier-skill-entry.sh: ${err instanceof Error ? err.message : String(err)}`);
2249
+ }
2250
+ try {
2251
+ fs.writeFileSync(path.join(instarHooksDir, 'model-tier-reconciler.js'), this.getModelTierReconcilerHook(), { mode: 0o755 });
2252
+ result.upgraded.push('hooks/instar/model-tier-reconciler.js (model-tier reconciler)');
2253
+ }
2254
+ catch (err) {
2255
+ result.errors.push(`model-tier-reconciler.js: ${err instanceof Error ? err.message : String(err)}`);
2256
+ }
2229
2257
  // Build stop hook — structural enforcement for /build pipeline.
2230
2258
  // Previously only installed once by init.ts, so existing agents that initialized
2231
2259
  // before it was added never received the file, yet settings.json references it
@@ -2900,6 +2928,21 @@ Rule: I do not state that work landed inside another agent's state unless I have
2900
2928
  patched = true;
2901
2929
  result.upgraded.push('CLAUDE.md: added Threadline Conversation Coherence holder-view section');
2902
2930
  }
2931
+ // Model-Tier Escalation (FABLE-MODEL-ESCALATION-SPEC §10) — agent-facing
2932
+ // awareness in the proactive-trigger form, tagged EXPERIMENTAL per
2933
+ // maturity-honesty (dark on the fleet; never announced as a finished user
2934
+ // capability). Content MUST stay byte-identical to the generateClaudeMd()
2935
+ // section in src/scaffold/templates.ts — parity tests assert it.
2936
+ if (!content.includes('Model-Tier Escalation (EXPERIMENTAL')) {
2937
+ const modelTierSection = `
2938
+ **Model-Tier Escalation (EXPERIMENTAL — escalate the model for heavy work)** — A policy layer that can run my claude-code sessions on the ultra model (\`claude-fable-5\`) for the two heavy-work triggers — spec/project design (\`spec-converge\`) and implementation or long autonomous runs (\`build\`, \`autonomous\`, \`instar-dev\`) — and on the default tier (\`claude-opus-4-8\`) the rest of the time. EXPERIMENTAL and dark by default: \`models.tierEscalation\` in \`.instar/config.json\` ships \`enabled:false\` (and \`dryRun:true\`, which logs intended swaps without performing them). Frameworks with no escalated model configured (codex/gemini/pi) are never touched. Every escalation passes cost guards first (quota headroom, per-account concurrent-escalation cap, hourly budget, TTL + dwell hysteresis) and is audited.
2939
+ - Swap a session's tier (server-side authority — body carries a TIER ONLY, never a model id): \`curl -X POST -H "Authorization: Bearer $AUTH" http://localhost:${port}/sessions/SESSION_NAME/model-swap -H 'Content-Type: application/json' -d '{"tier":"escalated"}'\` (\`"default"\` to de-escalate). Refuses protected/non-idle sessions; honors enabled/dryRun; 202 = swap sent but unconfirmed.
2940
+ - Proactive: user asks "what model are you running?" / "why are you on Fable/Opus?" → \`GET /sessions\` reports each session's live \`model\`; name the trigger that escalated it (or say escalation is disabled/dry-run on this agent). User says "stop using the expensive model" → set \`models.tierEscalation.enabled:false\` and restart sessions to apply.
2941
+ `;
2942
+ content += '\n' + modelTierSection;
2943
+ patched = true;
2944
+ result.upgraded.push('CLAUDE.md: added Model-Tier Escalation awareness section');
2945
+ }
2903
2946
  // MTP Protocol — the two EXO 3.0 tests (refusal + endorsement) on ORG-INTENT.
2904
2947
  // Existing agents need to know the /intent/org/test-action endpoint + the
2905
2948
  // three-layer protocol exist. Content-sniffed on a distinctive marker.
@@ -4847,6 +4890,12 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
4847
4890
  // never learns the holder view will claim a thread held elsewhere
4848
4891
  // "doesn't exist" — the exact dishonesty P3 kills.
4849
4892
  '**Threadline Conversation Coherence (which machine holds each agent-to-agent thread)**',
4893
+ // Model-Tier Escalation (FABLE-MODEL-ESCALATION-SPEC §10): a Codex/
4894
+ // Gemini agent spawns claude-code sessions through the same spawn/swap
4895
+ // routes — without this awareness it would never escalate (or explain)
4896
+ // a heavy-work session's model tier. Mid-session swap remains
4897
+ // claude-code-only; other frameworks are honest no-ops.
4898
+ '**Model-Tier Escalation (EXPERIMENTAL — escalate the model for heavy work)**',
4850
4899
  // Session Boot Self-Knowledge (spec session-boot-self-knowledge): vault
4851
4900
  // secret NAMES + operational facts at boot. A Codex/Gemini agent that
4852
4901
  // never learns the facts writer + secret-get retrieval will re-ask the
@@ -5421,6 +5470,48 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
5421
5470
  result.upgraded.push('.claude/settings.json: added PostToolUse skill-usage-telemetry hook');
5422
5471
  }
5423
5472
  }
5473
+ // Model-Tier Escalation (FABLE-MODEL-ESCALATION-SPEC §10) — append-with-
5474
+ // dedup registration for the two §5.4 signal hooks. Idempotent: appends
5475
+ // only when missing, never reorders or removes.
5476
+ {
5477
+ const postToolUse = (hooks.PostToolUse || []);
5478
+ const hasSkillEntry = postToolUse.some(e => e.matcher === 'Skill' && e.hooks?.some(h => h.command?.includes('model-tier-skill-entry')));
5479
+ if (!hasSkillEntry) {
5480
+ const skillEntry = postToolUse.find(e => e.matcher === 'Skill');
5481
+ const hookDef = {
5482
+ type: 'command',
5483
+ command: 'bash ${CLAUDE_PROJECT_DIR}/.instar/hooks/instar/model-tier-skill-entry.sh',
5484
+ timeout: 3000,
5485
+ };
5486
+ if (skillEntry) {
5487
+ skillEntry.hooks = skillEntry.hooks ?? [];
5488
+ skillEntry.hooks.push(hookDef);
5489
+ }
5490
+ else {
5491
+ postToolUse.push({ matcher: 'Skill', hooks: [hookDef] });
5492
+ }
5493
+ hooks.PostToolUse = postToolUse;
5494
+ patched = true;
5495
+ result.upgraded.push('.claude/settings.json: added PostToolUse model-tier-skill-entry hook');
5496
+ }
5497
+ }
5498
+ {
5499
+ const userPromptSubmit = (hooks.UserPromptSubmit || []);
5500
+ const hasReconciler = userPromptSubmit.some(e => e.hooks?.some(h => h.command?.includes('model-tier-reconciler')));
5501
+ if (!hasReconciler) {
5502
+ userPromptSubmit.push({
5503
+ matcher: '',
5504
+ hooks: [{
5505
+ type: 'command',
5506
+ command: 'node ${CLAUDE_PROJECT_DIR}/.instar/hooks/instar/model-tier-reconciler.js',
5507
+ timeout: 5000,
5508
+ }],
5509
+ });
5510
+ hooks.UserPromptSubmit = userPromptSubmit;
5511
+ patched = true;
5512
+ result.upgraded.push('.claude/settings.json: added UserPromptSubmit model-tier-reconciler hook');
5513
+ }
5514
+ }
5424
5515
  // Migrate all hook paths from flat layout to instar/ subdirectory
5425
5516
  if (hooks.PostToolUse) {
5426
5517
  this.migrateSettingsHookPaths(hooks.PostToolUse, result);
@@ -6240,6 +6331,8 @@ Create worktrees for collaborator repos with \`instar worktree create <branch>\`
6240
6331
  case 'auto-approve-permissions': return this.getAutoApprovePermissionsHook();
6241
6332
  case 'skill-usage-telemetry': return this.getSkillUsageTelemetryHook();
6242
6333
  case 'build-stop-hook': return this.getBuildStopHook();
6334
+ case 'model-tier-skill-entry': return this.getModelTierSkillEntryHook();
6335
+ case 'model-tier-reconciler': return this.getModelTierReconcilerHook();
6243
6336
  }
6244
6337
  }
6245
6338
  /** Public accessor for grounding-before-messaging hook content (used by init.ts) */
@@ -9913,6 +10006,225 @@ SESSION_ID="\${INSTAR_SESSION_ID:-}"
9913
10006
 
9914
10007
  mkdir -p "$INSTAR_DIR"
9915
10008
  echo "{\\"timestamp\\":\\"$TIMESTAMP\\",\\"skill\\":\\"$SKILL_NAME\\",\\"args\\":\\"$SKILL_ARGS\\",\\"session_id\\":\\"$SESSION_ID\\",\\"output_length\\":$OUTPUT_LEN}" >> "$TELEMETRY_FILE"
10009
+ `;
10010
+ }
10011
+ getModelTierSkillEntryHook() {
10012
+ // Canonical source: src/templates/hooks/model-tier-skill-entry.sh
10013
+ // If you edit either, keep them byte-identical — tests assert equality.
10014
+ return `#!/bin/bash
10015
+ # Model-Tier Skill Entry — PostToolUse hook for the Skill tool.
10016
+ #
10017
+ # FABLE-MODEL-ESCALATION-SPEC §5.4: records that a trigger skill STARTED by
10018
+ # writing the per-instance mode-state — ONLY on a tier transition (§6
10019
+ # write-on-transition; never on every PostToolUse). This is a SIGNAL writer:
10020
+ # it never swaps anything and never carries a model id; the reconciler +
10021
+ # server-side swap service (the single authority) decide what happens.
10022
+ #
10023
+ # Instance key: INSTAR_SESSION_ID — the spawn-generated session id. A
10024
+ # resume/respawn gets a fresh id, so a predecessor's mode-state can never be
10025
+ # inherited (§5.5). Fail-closed: any missing input exits 0 silently.
10026
+
10027
+ INPUT=$(cat)
10028
+
10029
+ TOOL_NAME=$(echo "$INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('tool_name',''))" 2>/dev/null)
10030
+ if [ "$TOOL_NAME" != "Skill" ]; then
10031
+ exit 0
10032
+ fi
10033
+
10034
+ if [ -z "\${INSTAR_SESSION_ID:-}" ]; then
10035
+ exit 0
10036
+ fi
10037
+
10038
+ INSTAR_DIR="\${CLAUDE_PROJECT_DIR:-.}/.instar"
10039
+ CONFIG_FILE="$INSTAR_DIR/config.json"
10040
+ if [ ! -f "$CONFIG_FILE" ]; then
10041
+ exit 0
10042
+ fi
10043
+
10044
+ SKILL_NAME=$(echo "$INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('tool_input',{}).get('skill',''))" 2>/dev/null)
10045
+ if [ -z "$SKILL_NAME" ]; then
10046
+ exit 0
10047
+ fi
10048
+
10049
+ MODE_FILE="$INSTAR_DIR/state/model-tier-escalation/mode-state-\${INSTAR_SESSION_ID}.json"
10050
+
10051
+ python3 - "$CONFIG_FILE" "$SKILL_NAME" "$MODE_FILE" "\${INSTAR_SESSION_ID}" "\${INSTAR_SESSION_NAME:-}" <<'PYEOF' 2>/dev/null
10052
+ import json, os, sys, datetime
10053
+ config_file, skill, mode_file, instance_id, session_name = sys.argv[1:6]
10054
+ try:
10055
+ cfg = json.load(open(config_file))
10056
+ except Exception:
10057
+ sys.exit(0)
10058
+ te = ((cfg.get('models') or {}).get('tierEscalation') or {})
10059
+ if te.get('enabled') is not True:
10060
+ sys.exit(0)
10061
+ triggers = ((te.get('triggers') or {}).get('skills')) or ['build', 'autonomous', 'instar-dev', 'spec-converge']
10062
+ if skill not in triggers:
10063
+ sys.exit(0)
10064
+ # Write-on-transition only (spec section 6): an existing same-instance
10065
+ # escalated mode-state means no transition - never rewrite (no churn).
10066
+ try:
10067
+ existing = json.load(open(mode_file))
10068
+ if existing.get('instanceId') == instance_id and existing.get('tier') == 'escalated':
10069
+ sys.exit(0)
10070
+ except Exception:
10071
+ pass
10072
+ os.makedirs(os.path.dirname(mode_file), exist_ok=True)
10073
+ state = {
10074
+ 'tier': 'escalated',
10075
+ 'trigger': skill,
10076
+ 'since': datetime.datetime.now(datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
10077
+ 'instanceId': instance_id,
10078
+ 'sessionName': session_name,
10079
+ }
10080
+ tmp = mode_file + '.tmp'
10081
+ with open(tmp, 'w') as f:
10082
+ json.dump(state, f)
10083
+ os.replace(tmp, mode_file)
10084
+ PYEOF
10085
+ exit 0
10086
+ `;
10087
+ }
10088
+ getModelTierReconcilerHook() {
10089
+ // Canonical source: src/templates/hooks/model-tier-reconciler.js
10090
+ // If you edit either, keep them byte-identical — tests assert equality.
10091
+ return `#!/usr/bin/env node
10092
+ // Model-Tier Reconciler — UserPromptSubmit hook.
10093
+ //
10094
+ // FABLE-MODEL-ESCALATION-SPEC sections 5.3(1)/5.4/5.5/6: computes the desired
10095
+ // tier from durable signals and, ONLY on a transition, asks the server-side
10096
+ // swap endpoint to act. It never performs a swap itself, never blocks the
10097
+ // turn, and emits no prompt context. The common path is PURE FILESYSTEM with
10098
+ // an early-exit no-op when desired == last-applied (no HTTP, no tmux).
10099
+ // Fail-closed: anything missing or unparseable exits 0 and the session stays
10100
+ // on its default model.
10101
+ //
10102
+ // NOTE: dynamic import('node:...') so this works under both CJS and ESM
10103
+ // hosts (the hook-event-reporter lesson).
10104
+
10105
+ const sid = process.env.INSTAR_SESSION_ID || '';
10106
+ const sessionName = process.env.INSTAR_SESSION_NAME || '';
10107
+ const serverUrl = process.env.INSTAR_SERVER_URL || '';
10108
+ const authToken = process.env.INSTAR_AUTH_TOKEN || '';
10109
+ if (!sid || !sessionName || !serverUrl || !authToken) process.exit(0);
10110
+
10111
+ (async () => {
10112
+ const fs = await import('node:fs');
10113
+ const path = await import('node:path');
10114
+ const projectDir = process.env.CLAUDE_PROJECT_DIR || '.';
10115
+ const instarDir = path.join(projectDir, '.instar');
10116
+ const stateDir = path.join(instarDir, 'state', 'model-tier-escalation');
10117
+ const modeFile = path.join(stateDir, 'mode-state-' + sid + '.json');
10118
+ const markerFile = path.join(stateDir, 'last-applied-' + sid + '.json');
10119
+
10120
+ const readJson = (p) => {
10121
+ try { return JSON.parse(fs.readFileSync(p, 'utf-8')); } catch { return null; }
10122
+ };
10123
+
10124
+ const cfgAll = readJson(path.join(instarDir, 'config.json'));
10125
+ const te = (cfgAll && cfgAll.models && cfgAll.models.tierEscalation) || null;
10126
+ if (!te || te.enabled !== true) process.exit(0);
10127
+ const guards = te.costGuards || {};
10128
+ const ttlMs = typeof guards.maxEscalationTtlMs === 'number' ? guards.maxEscalationTtlMs : 21600000;
10129
+ const dwellMs = typeof guards.minTierDwellMs === 'number' ? guards.minTierDwellMs : 300000;
10130
+ const dwellTurns = typeof guards.minTierDwellTurns === 'number' ? guards.minTierDwellTurns : 1;
10131
+
10132
+ // Desired tier — re-derived LIVE each turn from the durable signal (never
10133
+ // a persisted "escalated" flag that must be cleared). The mode-state is
10134
+ // self-expiring on read (spec 5.5): past TTL it is QUARANTINED (renamed),
10135
+ // so re-escalation needs a FRESH trigger, not a clock reset.
10136
+ let desired = 'default';
10137
+ const mode = readJson(modeFile);
10138
+ if (mode && mode.instanceId === sid && mode.tier === 'escalated') {
10139
+ const since = Date.parse(mode.since || '');
10140
+ if (Number.isFinite(since) && Date.now() - since < ttlMs) {
10141
+ desired = 'escalated';
10142
+ } else {
10143
+ try { fs.renameSync(modeFile, modeFile + '.expired'); } catch { /* already gone */ }
10144
+ // One audit breadcrumb — a TTL firing means the primary path failed.
10145
+ try {
10146
+ fs.mkdirSync(stateDir, { recursive: true });
10147
+ fs.appendFileSync(
10148
+ path.join(stateDir, 'audit.jsonl'),
10149
+ JSON.stringify({ ts: new Date().toISOString(), source: 'reconciler', type: 'ttl-expired', instanceId: sid }) + '\\n',
10150
+ );
10151
+ } catch { /* best-effort */ }
10152
+ }
10153
+ }
10154
+
10155
+ const marker = readJson(markerFile) || { tier: 'default', at: 0, turnsClear: 0 };
10156
+
10157
+ // FAST PATH (spec section 6): desired == last applied. Pure read, zero
10158
+ // writes, no HTTP. (A stale turnsClear can survive an interrupted
10159
+ // de-escalation streak; worst case is a de-escalation one turn early,
10160
+ // still bounded by dwellMs here AND by the server-side dwell backstop.)
10161
+ if (marker.tier === desired) process.exit(0);
10162
+
10163
+ const writeMarker = (m) => {
10164
+ try {
10165
+ fs.mkdirSync(stateDir, { recursive: true });
10166
+ const tmp = markerFile + '.tmp';
10167
+ fs.writeFileSync(tmp, JSON.stringify(m));
10168
+ fs.renameSync(tmp, markerFile);
10169
+ } catch { /* a lost marker only costs one redundant no-op POST */ }
10170
+ };
10171
+
10172
+ // Asymmetric hysteresis (spec 5.5): escalate immediately; de-escalate only
10173
+ // after the condition has been clear for dwellTurns consecutive turns AND
10174
+ // dwellMs since the last swap. Suppressed flaps leave the marker counting.
10175
+ if (desired === 'default') {
10176
+ const turnsClear = (marker.turnsClear || 0) + 1;
10177
+ if (turnsClear < dwellTurns || (marker.at && Date.now() - marker.at < dwellMs)) {
10178
+ writeMarker({ ...marker, turnsClear });
10179
+ process.exit(0);
10180
+ }
10181
+ }
10182
+
10183
+ // Stable-refusal cooldown: 'disabled' / 'launch-time-only-framework' can't
10184
+ // change turn-to-turn — don't hammer the endpoint for 10 minutes.
10185
+ if (
10186
+ marker.refusedReason &&
10187
+ marker.refusedDesired === desired &&
10188
+ Date.now() - (marker.refusedAt || 0) < 600000
10189
+ ) {
10190
+ process.exit(0);
10191
+ }
10192
+
10193
+ // TRANSITION: ask the server — the single swap authority. Bounded (4s);
10194
+ // any failure leaves the marker untouched, so the next idle boundary
10195
+ // retries. The reconciler reconciles against the OBSERVED outcome
10196
+ // ('swapped' = canary-confirmed), never its own write-intent.
10197
+ try {
10198
+ const controller = new AbortController();
10199
+ const timer = setTimeout(() => controller.abort(), 4000);
10200
+ const res = await fetch(
10201
+ serverUrl + '/sessions/' + encodeURIComponent(sessionName) + '/model-swap',
10202
+ {
10203
+ method: 'POST',
10204
+ headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + authToken },
10205
+ body: JSON.stringify({ tier: desired }),
10206
+ signal: controller.signal,
10207
+ },
10208
+ );
10209
+ clearTimeout(timer);
10210
+ const body = await res.json().catch(() => ({}));
10211
+ const status = body && body.status;
10212
+ if (status === 'swapped' || status === 'dry-run' || status === 'noop') {
10213
+ // 'swapped': independent oracle confirmed. 'dry-run'/'noop': nothing
10214
+ // will change for this tier — marking prevents per-turn re-POSTs while
10215
+ // keeping exactly one audit line per transition.
10216
+ writeMarker({ tier: desired, at: Date.now(), turnsClear: 0 });
10217
+ } else if (
10218
+ status === 'refused' &&
10219
+ (body.reason === 'disabled' || body.reason === 'launch-time-only-framework')
10220
+ ) {
10221
+ writeMarker({ ...marker, refusedReason: body.reason, refusedDesired: desired, refusedAt: Date.now() });
10222
+ }
10223
+ // 'unconfirmed' and transient refusals (not-idle / dwell / cost-guard):
10224
+ // do NOT mark reconciled (spec 5.3) — behaviourally default; retry later.
10225
+ } catch { /* never blocks the turn */ }
10226
+ process.exit(0);
10227
+ })();
9916
10228
  `;
9917
10229
  }
9918
10230
  getBuildStopHook() {