@fusengine/harness 0.1.77 → 0.1.79

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.
@@ -6,7 +6,7 @@ import { B as detectProjectType$1, H as requiredArchSkill, L as detectFramework,
6
6
  import { a as sanitizeSessionId, c as sessionsDir, d as countFrameworkCodeLines, f as countLines, i as loadSessionState, l as PLUGINS_DIR, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, t as claudeHome } from "./home-state-BXf38Zi1.mjs";
7
7
  import { a as writeJsonFile, i as readJsonFile, r as hashText, t as atomicWrite } from "./json-io-DisYd2fb.mjs";
8
8
  import { r as isDocConsulted } from "./doc-helpers-CWZegVdR.mjs";
9
- import { A as detectCreationIntent, E as isExcludedSwiftPath, F as docConsultedGate, I as evaluateApex, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, S as usesTailwindUtilities, T as isExcludedJsPath, _ as scanPlugin, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, h as buildClaudeMdContext, k as capVerbosity, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, r as descFromText, s as parseEntry, t as isHtmlLike, w as frameworkSolidGate, x as skillTriggerGate, y as parseField } from "./validate-DnLU4IHy.mjs";
9
+ import { A as capVerbosity, C as usesTailwindUtilities, D as isExcludedSwiftPath, E as isExcludedJsPath, I as docConsultedGate, L as evaluateApex, N as POST_AUTH_GATES, P as PRE_AUTH_GATES, S as skillTriggerGate, T as frameworkSolidGate, _ as harnessHomeSegment, b as parseField, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, h as buildClaudeMdContext, j as detectCreationIntent, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, r as descFromText, s as parseEntry, t as isHtmlLike, v as scanPlugin } from "./validate-DhOX5hDK.mjs";
10
10
  import { n as findMarketplacePlugins, r as readPluginMeta, t as resolveSkillPath } from "./skill-path-BO2N0XvB.mjs";
11
11
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
12
12
  import { a as nowStamp, l as throttleMs, n as readRoots, o as readState, s as setStateField, t as addRoot } from "./registry-CymilZiZ.mjs";
@@ -591,10 +591,11 @@ function claudeMdKey(prompt, ctx) {
591
591
  * is emitted on EVERY message" is thus preserved.
592
592
  * @param prompt - The raw user prompt.
593
593
  * @param cwd - Project root (for project-type detection).
594
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
594
595
  * @returns The native hook stdout (possibly empty).
595
596
  */
596
- function promptSubmitContext(prompt, cwd) {
597
- const ctx = buildClaudeMdContext(prompt, cwd);
597
+ function promptSubmitContext(prompt, cwd, id = "claude-code") {
598
+ const ctx = buildClaudeMdContext(prompt, cwd, id);
598
599
  if (!ctx) return "";
599
600
  if (!oncePerWindow(claudeMdKey(prompt, ctx), 3e3)) return "";
600
601
  return attachSystemMessage(contextResponse("UserPromptSubmit", ctx), "CLAUDE.md injected");
@@ -605,10 +606,11 @@ function promptSubmitContext(prompt, cwd) {
605
606
  * Harness-produced (not owner CLAUDE.md content), so it is subject to the
606
607
  * per-fragment {@link capFragment} budget — unlike {@link promptSubmitContext}.
607
608
  * @param cwd - Fallback project root when `CLAUDE_PROJECT_DIR` is unset.
609
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
608
610
  * @returns The native hook stdout (possibly empty).
609
611
  */
610
- function taskContext(cwd) {
611
- const ctx = buildApexTaskInjection(process.env.CLAUDE_PROJECT_DIR ?? cwd);
612
+ function taskContext(cwd, id = "claude-code") {
613
+ const ctx = buildApexTaskInjection(process.env.CLAUDE_PROJECT_DIR ?? cwd, id);
612
614
  return ctx ? contextResponse("PreToolUse", capFragment("apex-task", ctx)) : "";
613
615
  }
614
616
  //#endregion
@@ -1442,14 +1444,17 @@ function stamp$1(now) {
1442
1444
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}-${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
1443
1445
  }
1444
1446
  /**
1445
- * Handle PreCompact: back up `.claude/apex/task.json` to `backups/`, keep only
1446
- * the 5 newest, and emit a confirmation. Ports `pre-compact/save-apex-state.py`.
1447
+ * Handle PreCompact: back up the target apex `task.json` (`.claude/apex/`,
1448
+ * `.codex/apex/`, ...) to `backups/`, keep only the 5 newest, and emit a
1449
+ * confirmation. Ports `pre-compact/save-apex-state.py`.
1447
1450
  * @param cwd - Project root.
1448
1451
  * @param now - Clock (defaults to `Date.now()`).
1452
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
1449
1453
  * @returns The native hook stdout (possibly empty when no task.json).
1450
1454
  */
1451
- function saveApexState(cwd, now = Date.now()) {
1452
- const apexDir = join(cwd, ".claude", "apex");
1455
+ function saveApexState(cwd, now = Date.now(), id = "claude-code") {
1456
+ const seg = harnessHomeSegment(id);
1457
+ const apexDir = join(cwd, seg, "apex");
1453
1458
  const stateFile = join(apexDir, "task.json");
1454
1459
  if (!existsSync(stateFile)) return "";
1455
1460
  const backupDir = join(apexDir, "backups");
@@ -1459,7 +1464,7 @@ function saveApexState(cwd, now = Date.now()) {
1459
1464
  for (const old of backups.slice(5)) try {
1460
1465
  rmSync(join(backupDir, old), { force: true });
1461
1466
  } catch {}
1462
- return JSON.stringify({ additionalContext: "APEX state saved before compaction. Previous task state preserved in .claude/apex/backups/" });
1467
+ return JSON.stringify({ additionalContext: `APEX state saved before compaction. Previous task state preserved in ${seg}/apex/backups/` });
1463
1468
  }
1464
1469
  //#endregion
1465
1470
  //#region src/runtime/lifecycle/session-end.ts
@@ -4074,18 +4079,25 @@ function cartographerContext() {
4074
4079
  return `\n### 7. Cartographer Maps\nNavigate branches (index.md) -> leaves link to real files:\n- Plugin skills: ${pluginsMap}\n- Project files: .cartographer/project/index.md`;
4075
4080
  }
4076
4081
  /**
4077
- * Build the APEX sub-agent injection for SubagentStart, or "" when the project
4078
- * has no `.claude/apex/` dir. Reads AGENTS.md (first 4KB) + task.json.
4082
+ * Build the APEX sub-agent injection for SubagentStart, or "" when the project has no target apex dir (`.claude/apex/`, `.codex/apex/`, ...). Reads AGENTS.md (first 4KB) + task.json.
4079
4083
  * @param cwd - Fallback project root when `CLAUDE_PROJECT_DIR` is unset.
4080
4084
  * @param home - Home dir (unused placeholder; kept for symmetry/testing).
4085
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
4081
4086
  * @returns The native hook stdout (possibly empty).
4082
4087
  */
4083
- async function injectApexSubagentContext(cwd, home = homedir()) {
4084
- const apexDir = join(process.env.CLAUDE_PROJECT_DIR ?? cwd, ".claude", "apex");
4088
+ async function injectApexSubagentContext(cwd, home = homedir(), id = "claude-code") {
4089
+ const projectRoot = process.env.CLAUDE_PROJECT_DIR ?? cwd;
4090
+ const seg = harnessHomeSegment(id);
4091
+ const apexDir = join(projectRoot, seg, "apex");
4085
4092
  if (!existsSync(apexDir)) return "";
4086
4093
  const agentsPath = join(apexDir, "AGENTS.md");
4087
4094
  const agents = existsSync(agentsPath) ? readText(agentsPath).slice(0, 4e3) : "";
4088
4095
  const taskData = await readJsonFile(join(apexDir, "task.json"));
4096
+ const completed = taskData ? completedTasks(taskData.tasks) : "none";
4097
+ const pending = taskData ? pendingTasks(taskData.tasks) : "none";
4098
+ const isCodex = id === "codex";
4099
+ const beforeStart = isCodex ? "Use update_plan → mark the active step in_progress before starting" : "Use TaskUpdate(taskId, status: in_progress) before starting";
4100
+ const whenDone = isCodex ? "update_plan → mark the step completed when done" : "TaskUpdate(taskId, status: completed) triggers auto-commit";
4089
4101
  return contextResponse("SubagentStart", capFragment("apex-subagent", `## APEX Sub-Agent Instructions
4090
4102
 
4091
4103
  You are a sub-agent in APEX workflow. Follow these rules:
@@ -4094,24 +4106,24 @@ You are a sub-agent in APEX workflow. Follow these rules:
4094
4106
  ${agents}
4095
4107
 
4096
4108
  ### 2. Task Context
4097
- - Last completed: ${taskData ? completedTasks(taskData.tasks) : "none"}
4098
- - Pending: ${taskData ? pendingTasks(taskData.tasks) : "none"}
4109
+ - Last completed: ${completed}
4110
+ - Pending: ${pending}
4099
4111
 
4100
4112
  ### 3. Before Starting Work
4101
- - Use TaskUpdate(taskId, status: in_progress) before starting
4113
+ - ${beforeStart}
4102
4114
 
4103
4115
  ### 4. SOLID Rules
4104
4116
  - Files < ${resolveMaxLines()} lines | Interfaces in src/interfaces/ | JSDoc/PHPDoc required
4105
4117
 
4106
4118
  ### 5. Research Before Code
4107
- - Use Context7/Exa for docs | Write notes to .claude/apex/docs/
4119
+ - Use Context7/Exa for docs | Write notes to ${seg}/apex/docs/
4108
4120
 
4109
4121
  ### 6. Before Done (NEVER skip)
4110
4122
  - eLicit: self-review with a NAMED elicitation technique; fix findings first
4111
4123
  - Verify: run/functional-check your changes (references⇔declarations)
4112
4124
 
4113
4125
  ### 7. When Done
4114
- - TaskUpdate(taskId, status: completed) triggers auto-commit${cartographerContext()}`));
4126
+ - ${whenDone}${cartographerContext()}`));
4115
4127
  }
4116
4128
  /** 16-char hex SHA-256 of `text` (project hash / doc topic key). */
4117
4129
  function hashText16(text) {
@@ -5047,18 +5059,22 @@ async function onComplete(taskFile, taskId, projectRoot) {
5047
5059
  return contextResponse("PostToolUse", `Task #${taskId} completed: ${(await readJsonFile(taskFile))?.tasks[taskId]?.subject ?? "Task"}\n\nChanges detected. MANDATORY: Run /fuse-commit-pro:commit to commit with smart detection.`);
5048
5060
  }
5049
5061
  /**
5050
- * PostToolUse TaskCreate/TaskUpdate handler.
5062
+ * PostToolUse TaskCreate/TaskUpdate handler. Claude-only by design: Codex never
5063
+ * emits these native task tools, so the `toolName` matcher below intentionally
5064
+ * stays as-is — only the target apex-dir segment is harness-aware.
5051
5065
  * @param payload - The raw hook payload (`tool_name`, `tool_input`, `tool_response`).
5052
5066
  * @param cwd - Fallback project root (uses `CLAUDE_PROJECT_DIR` first).
5067
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
5053
5068
  * @returns The native hook stdout (possibly empty).
5054
5069
  */
5055
- async function syncTaskTracking(payload, cwd) {
5070
+ async function syncTaskTracking(payload, cwd, id = "claude-code") {
5056
5071
  const toolName = String(payload.tool_name ?? "");
5057
5072
  if (toolName !== "TaskCreate" && toolName !== "TaskUpdate") return "";
5058
5073
  const projectRoot = process.env.CLAUDE_PROJECT_DIR ?? cwd;
5059
- const taskFile = join(projectRoot, ".claude", "apex", "task.json");
5074
+ const seg = harnessHomeSegment(id);
5075
+ const taskFile = join(projectRoot, seg, "apex", "task.json");
5060
5076
  if (!existsSync(taskFile)) return "";
5061
- const unlock = await acquireLock(join(projectRoot, ".claude", "apex", ".task.lock"), 1e4);
5077
+ const unlock = await acquireLock(join(projectRoot, seg, "apex", ".task.lock"), 1e4);
5062
5078
  if (!unlock) return "";
5063
5079
  try {
5064
5080
  const ti = payload.tool_input ?? {};
@@ -5267,9 +5283,9 @@ async function typeSpecificCache(agent, cwd, now, home) {
5267
5283
  * entries (APEX context + lessons) fire for EVERY sub-agent, then the type-specific
5268
5284
  * cache is concatenated on top — sniper too, hence no early return.
5269
5285
  */
5270
- async function onSubagentStart(payload, cwd, now, home) {
5286
+ async function onSubagentStart(payload, cwd, now, home, id) {
5271
5287
  const agent = agentTypeOf(payload);
5272
- return combineContext(await injectApexSubagentContext(cwd, home), await injectLessonsCache(cwd, home, now), await typeSpecificCache(agent, cwd, now, home));
5288
+ return combineContext(await injectApexSubagentContext(cwd, home, id), await injectLessonsCache(cwd, home, now), await typeSpecificCache(agent, cwd, now, home));
5273
5289
  }
5274
5290
  /** SubagentStop routing: transcript-driven cache writers, then the universal SOLID check. */
5275
5291
  async function onSubagentStop(payload, cwd, home) {
@@ -5285,10 +5301,10 @@ async function onSubagentStop(payload, cwd, home) {
5285
5301
  /**
5286
5302
  * Dispatch an ai-pilot-scope lifecycle event. Returns the native stdout, or
5287
5303
  * `null` when unhandled (caller falls through to the default pipeline).
5288
- * @param home - Home dir for cache resolution (defaults to `~`; injectable for test isolation).
5304
+ * @param home - Home dir for cache resolution (defaults to `~`; injectable for test isolation); `id` selects the harness target (defaults to "claude-code").
5289
5305
  */
5290
- async function dispatchAipilot(event, payload, cwd, now, home = homedir()) {
5291
- if (event === "SubagentStart") return onSubagentStart(payload, cwd, now, home);
5306
+ async function dispatchAipilot(event, payload, cwd, now, home = homedir(), id = "claude-code") {
5307
+ if (event === "SubagentStart") return onSubagentStart(payload, cwd, now, home, id);
5292
5308
  if (event === "SubagentStop") return onSubagentStop(payload, cwd, home);
5293
5309
  if (event === "SessionEnd" || event === "Stop") {
5294
5310
  await cacheAnalyticsSave(home, now);
@@ -5297,9 +5313,9 @@ async function dispatchAipilot(event, payload, cwd, now, home = homedir()) {
5297
5313
  if (event === "PreToolUse") return docCacheGate(payload, cwd, now, home);
5298
5314
  return null;
5299
5315
  }
5300
- /** PostToolUse (Write/Edit SOLID check, else TaskCreate/TaskUpdate sync) for the ai-pilot scope. */
5301
- async function aipilotPostToolUse(payload, cwd) {
5302
- return checkSolidCompliance(payload) || await syncTaskTracking(payload, cwd);
5316
+ /** PostToolUse (Write/Edit SOLID check, else TaskCreate/TaskUpdate sync) for the ai-pilot scope; `id` selects the harness target (defaults to "claude-code"). */
5317
+ async function aipilotPostToolUse(payload, cwd, id = "claude-code") {
5318
+ return checkSolidCompliance(payload) || await syncTaskTracking(payload, cwd, id);
5303
5319
  }
5304
5320
  //#endregion
5305
5321
  //#region src/runtime/lifecycle/dispatch.ts
@@ -5341,7 +5357,7 @@ function dispatchLifecycle(input) {
5341
5357
  case "TeammateIdle": return teammateIdleContext(input.payload, input.cwd, void 0, input.now);
5342
5358
  case "PostToolUseFailure": return failureLessonContext(input.payload, input.cwd, void 0, input.now);
5343
5359
  case "PostCompact": return input.scope === "core" ? postCompactContext(input.payload, input.cwd, import.meta.url, input.now) : "";
5344
- case "PreCompact": return saveApexState(input.cwd, input.now);
5360
+ case "PreCompact": return saveApexState(input.cwd, input.now, input.id ?? "claude-code");
5345
5361
  case "SessionEnd":
5346
5362
  if (input.scope !== "aipilot") cleanupSession(void 0, input.now);
5347
5363
  return "";
@@ -5883,19 +5899,22 @@ function docTypeOf(filePath) {
5883
5899
  }
5884
5900
  /**
5885
5901
  * Auto-document a Read of a SKILL.md/README/CLAUDE.md/docs/references file
5886
- * into `.claude/apex/docs/task-<current>-<framework>.md` (skipped when the
5887
- * file is already logged, or no project root is found from `filePath`).
5902
+ * into the target apex docs dir (`.claude/apex/docs/`, `.codex/apex/docs/`,
5903
+ * ...) as `task-<current>-<framework>.md` (skipped when the file is already
5904
+ * logged, or no project root is found from `filePath`).
5888
5905
  * @param filePath - The path passed to the Read tool.
5889
5906
  * @param now - Clock (defaults to `Date.now()`).
5907
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
5890
5908
  * @returns The native `systemMessage` stdout, or "" when nothing was logged.
5891
5909
  */
5892
- async function autoDocumentRead(filePath, now = Date.now()) {
5910
+ async function autoDocumentRead(filePath, now = Date.now(), id = "claude-code") {
5893
5911
  if (!filePath || !DOC_PATTERNS.some((p) => p.test(filePath))) return "";
5894
5912
  const root = projectRootOrNull(dirname(filePath));
5895
5913
  if (!root) return "";
5914
+ const seg = harnessHomeSegment(id);
5896
5915
  const framework = detectProjectType$1(root);
5897
- const current = (await readJsonFile(join(root, ".claude", "apex", "task.json")))?.current_task ?? "1";
5898
- const docDir = join(root, ".claude", "apex", "docs");
5916
+ const current = (await readJsonFile(join(root, seg, "apex", "task.json")))?.current_task ?? "1";
5917
+ const docDir = join(root, seg, "apex", "docs");
5899
5918
  const docFile = join(docDir, `task-${current}-${framework}.md`);
5900
5919
  const ts = new Date(now).toISOString().replace(/\.\d{3}Z$/, "Z");
5901
5920
  const fname = basename(filePath);
@@ -5934,15 +5953,17 @@ function additionalContextOf(stdout) {
5934
5953
  * @param cwd - Project root.
5935
5954
  * @param scope - The invoking plugin scope (defaults to `core`).
5936
5955
  * @param now - Clock.
5956
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
5937
5957
  * @returns The native stdout, or `null` when unhandled.
5938
5958
  */
5939
- function lifecycleStdout(payload, cwd, scope, now) {
5959
+ function lifecycleStdout(payload, cwd, scope, now, id = "claude-code") {
5940
5960
  return dispatchLifecycle({
5941
5961
  event: rawEvent(payload),
5942
5962
  payload,
5943
5963
  cwd,
5944
5964
  scope,
5945
- now
5965
+ now,
5966
+ id
5946
5967
  });
5947
5968
  }
5948
5969
  /**
@@ -5955,11 +5976,12 @@ function lifecycleStdout(payload, cwd, scope, now) {
5955
5976
  * @param scope - The invoking plugin scope.
5956
5977
  * @param event - The normalized event.
5957
5978
  * @param now - Clock.
5979
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
5958
5980
  * @returns The extra stdout (possibly empty).
5959
5981
  */
5960
- async function postEditContext(scope, event, now) {
5982
+ async function postEditContext(scope, event, now, id = "claude-code") {
5961
5983
  if (scope !== "core" || !event.filePath) return "";
5962
- if (event.tool === "Read") return autoDocumentRead(event.filePath, now);
5984
+ if (event.tool === "Read") return autoDocumentRead(event.filePath, now, id);
5963
5985
  if (event.tool !== "Write" && event.tool !== "Edit") return "";
5964
5986
  const sniper = trackSessionChanges(event.sessionId, event.filePath, void 0, now);
5965
5987
  const lint = postEditTypescript(event.filePath);
@@ -6019,7 +6041,7 @@ const EXEMPT_PATTERNS = [
6019
6041
  /\.claude-plugin\//,
6020
6042
  /CHANGELOG\.md$/,
6021
6043
  /marketplace\.json$/,
6022
- /\/\.claude\/(apex|memory|logs|fusengine-cache)\//,
6044
+ /\/\.(claude|codex)\/(apex|memory|logs|fusengine-cache)\//,
6023
6045
  /\/\.fuse-harness\//
6024
6046
  ];
6025
6047
  /**
@@ -7873,7 +7895,7 @@ async function handlePre(ctx) {
7873
7895
  exit: 0
7874
7896
  };
7875
7897
  if (event.tool === "Task") {
7876
- const taskCtx = taskContext(opts.cwd);
7898
+ const taskCtx = taskContext(opts.cwd, id);
7877
7899
  if (taskCtx) return {
7878
7900
  stdout: taskCtx,
7879
7901
  exit: 0
@@ -8440,7 +8462,7 @@ async function handlePost(ctx) {
8440
8462
  };
8441
8463
  }
8442
8464
  if (opts.scope === "aipilot" && (event.tool === "TaskCreate" || event.tool === "TaskUpdate" || event.tool === "Write" || event.tool === "Edit")) {
8443
- const out = await aipilotPostToolUse(payload, opts.cwd);
8465
+ const out = await aipilotPostToolUse(payload, opts.cwd, id);
8444
8466
  if (out) return {
8445
8467
  stdout: out,
8446
8468
  exit: 0
@@ -8448,7 +8470,7 @@ async function handlePost(ctx) {
8448
8470
  }
8449
8471
  let extra = "";
8450
8472
  for (const f of files) {
8451
- extra = await postEditContext(opts.scope ?? "core", f, opts.now);
8473
+ extra = await postEditContext(opts.scope ?? "core", f, opts.now, id);
8452
8474
  if (extra) break;
8453
8475
  }
8454
8476
  const notice = designPassNotice({
@@ -8508,10 +8530,11 @@ async function handlePost(ctx) {
8508
8530
  * @param payload - The raw hook payload.
8509
8531
  * @param cwd - Project root.
8510
8532
  * @param now - Clock.
8533
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
8511
8534
  * @returns The native stdout when intercepted, or `null` to fall through.
8512
8535
  */
8513
- async function asyncScopeStdout(scope, event, payload, cwd, now) {
8514
- if (scope === "aipilot") return dispatchAipilot(event, payload, cwd, now);
8536
+ async function asyncScopeStdout(scope, event, payload, cwd, now, id = "claude-code") {
8537
+ if (scope === "aipilot") return dispatchAipilot(event, payload, cwd, now, void 0, id);
8515
8538
  if (scope === "memory") return dispatchMemory(event, payload, cwd, now);
8516
8539
  return null;
8517
8540
  }
@@ -8925,12 +8948,12 @@ async function handleHook(id, payload, opts) {
8925
8948
  exit: 0
8926
8949
  };
8927
8950
  if (id === "codex" && rawEventName(payload) === "SessionStart") resyncCodexAgents();
8928
- const asyncOut = await asyncScopeStdout(opts.scope, rawEventName(payload), payload, opts.cwd, opts.now);
8951
+ const asyncOut = await asyncScopeStdout(opts.scope, rawEventName(payload), payload, opts.cwd, opts.now, id);
8929
8952
  if (asyncOut !== null) return {
8930
8953
  stdout: asyncOut,
8931
8954
  exit: 0
8932
8955
  };
8933
- const life = lifecycleStdout(payload, opts.cwd, opts.scope ?? "core", opts.now);
8956
+ const life = lifecycleStdout(payload, opts.cwd, opts.scope ?? "core", opts.now, id);
8934
8957
  if (life !== null) return {
8935
8958
  stdout: id === "claude-code" ? attachBudgetRecap(life, rawEventName(payload), event.sessionId, opts.cwd, opts.now) : life,
8936
8959
  exit: 0
@@ -8939,7 +8962,7 @@ async function handleHook(id, payload, opts) {
8939
8962
  if (userPrompt !== void 0) {
8940
8963
  await saveTrack(file, recordBrainstormRequired(await loadTrack(file), detectCreationIntent(userPrompt)));
8941
8964
  return {
8942
- stdout: promptSubmitContext(userPrompt, opts.cwd),
8965
+ stdout: promptSubmitContext(userPrompt, opts.cwd, id),
8943
8966
  exit: 0
8944
8967
  };
8945
8968
  }
@@ -412,9 +412,7 @@ declare function usesTailwindUtilities(filePath: string, content: string): boole
412
412
  */
413
413
  declare function skillTriggerGate(framework: string, content: string, refsRead: readonly string[], forcedSkill?: string | null, cwd?: string, filePath?: string): Prompt | null;
414
414
  //#endregion
415
- //#region src/policy/claude-md-context.d.ts
416
- /** Dev-verb regex (FR/EN) that triggers the APEX preamble (case-insensitive). */
417
- declare const DEV_VERBS: RegExp;
415
+ //#region src/policy/detect-claude-md-project-type.d.ts
418
416
  /**
419
417
  * Detect the project type from the cwd, reproducing the legacy Python logic:
420
418
  * package.json containing "next" → nextjs, else "react" → react; else
@@ -424,22 +422,29 @@ declare const DEV_VERBS: RegExp;
424
422
  * @returns The detected project type label.
425
423
  */
426
424
  declare function detectClaudeMdProjectType(cwd: string): ProjectType;
425
+ //#endregion
426
+ //#region src/policy/claude-md-context.d.ts
427
+ /** Dev-verb regex (FR/EN) that triggers the APEX preamble (case-insensitive). */
428
+ declare const DEV_VERBS: RegExp;
427
429
  /**
428
430
  * Build the APEX instruction preamble for a development task.
429
431
  * @param projectType - Detected project type label.
430
432
  * @param maxLines - SOLID per-file line ceiling.
433
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
431
434
  * @returns The APEX instruction text.
432
435
  */
433
- declare function buildApexInstruction(projectType: ProjectType, maxLines: number): string;
436
+ declare function buildApexInstruction(projectType: ProjectType, maxLines: number, id?: string): string;
434
437
  /**
435
- * Build the UserPromptSubmit injection text: read `~/.claude/CLAUDE.md` and,
438
+ * Build the UserPromptSubmit injection text: read the target's root
439
+ * instructions doc (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, ...) and,
436
440
  * when the prompt matches a dev verb, prepend the APEX instruction. Returns
437
- * `null` when CLAUDE.md is absent/unreadable (the hook then emits nothing).
441
+ * `null` when the doc is absent/unreadable (the hook then emits nothing).
438
442
  * @param prompt - The raw user prompt.
439
443
  * @param cwd - Project root (for project-type detection).
444
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
440
445
  * @returns The injection text, or `null` to emit nothing.
441
446
  */
442
- declare function buildClaudeMdContext(prompt: string, cwd: string): string | null;
447
+ declare function buildClaudeMdContext(prompt: string, cwd: string, id?: string): string | null;
443
448
  //#endregion
444
449
  //#region src/policy/apex-task-context.d.ts
445
450
  /** Parsed task state injected into a Task sub-agent prompt. */
@@ -464,16 +469,19 @@ declare function loadApexTaskState(taskFile: string): ApexTaskState;
464
469
  * Build the APEX context string injected into a Task sub-agent prompt.
465
470
  * @param state - The parsed task state.
466
471
  * @param maxLines - SOLID per-file line ceiling.
472
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
467
473
  * @returns The injection text.
468
474
  */
469
- declare function buildApexTaskContext(state: ApexTaskState, maxLines: number): string;
475
+ declare function buildApexTaskContext(state: ApexTaskState, maxLines: number, id?: string): string;
470
476
  /**
471
- * Build the PreToolUse Task injection, gated on the existence of the project's
472
- * `.claude/apex/` directory. Returns `null` when APEX is not active (no dir).
477
+ * Build the PreToolUse Task injection, gated on the existence of the
478
+ * project's target apex dir (`.claude/apex/`, `.codex/apex/`, ...). Returns
479
+ * `null` when APEX is not active (no dir).
473
480
  * @param projectRoot - `CLAUDE_PROJECT_DIR` or cwd.
481
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
474
482
  * @returns The injection text, or `null` to emit nothing.
475
483
  */
476
- declare function buildApexTaskInjection(projectRoot: string): string | null;
484
+ declare function buildApexTaskInjection(projectRoot: string, id?: string): string | null;
477
485
  //#endregion
478
486
  //#region src/policy/cartographer/indicators.d.ts
479
487
  /**
package/dist/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import { a as HarnessInfo, i as HarnessId, n as detectMode, o as HarnessMode, r
5
5
  import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "./doc-helpers-CEKzGg2u.mjs";
6
6
  import { t as incrementTrivialEditCounter } from "./index-BOBXQ91y.mjs";
7
7
  import { a as compactJson, i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./index-BEMumjOw.mjs";
8
- import { $ as protectedPathGuard, A as FAIL_CLOSED, B as RUST_DECL_RE, C as usesTailwindUtilities, Ct as DEV_KEYWORDS, D as MAX_TOKENS, Dt as detectProjectType, E as MAX_EXA_RESULTS, Et as detectModularArchitecture, F as installGuard, G as ASK_WRITERS, H as TS_DECL_RE, I as GO_DECL_RE, J as FILE_REDIRECT, K as CODE_MUTATORS, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as isApexCommand, P as runGuards, Q as PROTECTED_GIT_RE, R as PHP_DECL_RE, S as skillTriggerGate, St as detectFramework, T as frameworkSolidGate, Tt as ProjectType, U as interfaceSeparationGuard, V as SWIFT_PROTO_RE, W as bashWriteGuard, X as SESSION_STATE_FRAGMENT, Y as SAFE_PREFIXES, Z as PROTECTED_FRAGMENTS, _ as DEV_VERBS, _t as PLUGINS_DIR, a as firstHeading, at as GuardContext, b as detectClaudeMdProjectType, bt as countLines, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as PROJECT_INSTALL, et as ASK_PATTERNS, f as PROJECT_INDICATORS, ft as RALPH_SAFE, g as loadApexTaskState, gt as FileSizeVerdict, h as buildApexTaskInjection, ht as matchPatterns, i as firstComment, it as Guard, j as GUARDS, k as detectCreationIntent, kt as requiredArchSkill, l as parseBodyDesc, lt as GIT_ASK, m as buildApexTaskContext, mt as isRalphMode, n as missingSeoElements, nt as LabeledPattern, o as TreeEntry, ot as evaluate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as CODE_REDIRECT, r as descFromText, rt as securityGuard, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as CRITICAL_PATTERNS, u as parseField, ut as GIT_BLOCKED, v as buildApexInstruction, vt as SOLID_REF, w as SKILL_TRIGGERS, wt as ModularArchitecture, x as detectRequiredSkills, xt as evaluateFileSize, y as buildClaudeMdContext, yt as countFrameworkCodeLines, z as PY_MODEL_RE } from "./index-DJw1OGwE.mjs";
8
+ import { $ as protectedPathGuard, A as FAIL_CLOSED, B as RUST_DECL_RE, C as usesTailwindUtilities, Ct as DEV_KEYWORDS, D as MAX_TOKENS, Dt as detectProjectType, E as MAX_EXA_RESULTS, Et as detectModularArchitecture, F as installGuard, G as ASK_WRITERS, H as TS_DECL_RE, I as GO_DECL_RE, J as FILE_REDIRECT, K as CODE_MUTATORS, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as isApexCommand, P as runGuards, Q as PROTECTED_GIT_RE, R as PHP_DECL_RE, S as skillTriggerGate, St as detectFramework, T as frameworkSolidGate, Tt as ProjectType, U as interfaceSeparationGuard, V as SWIFT_PROTO_RE, W as bashWriteGuard, X as SESSION_STATE_FRAGMENT, Y as SAFE_PREFIXES, Z as PROTECTED_FRAGMENTS, _ as DEV_VERBS, _t as PLUGINS_DIR, a as firstHeading, at as GuardContext, b as detectClaudeMdProjectType, bt as countLines, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as PROJECT_INSTALL, et as ASK_PATTERNS, f as PROJECT_INDICATORS, ft as RALPH_SAFE, g as loadApexTaskState, gt as FileSizeVerdict, h as buildApexTaskInjection, ht as matchPatterns, i as firstComment, it as Guard, j as GUARDS, k as detectCreationIntent, kt as requiredArchSkill, l as parseBodyDesc, lt as GIT_ASK, m as buildApexTaskContext, mt as isRalphMode, n as missingSeoElements, nt as LabeledPattern, o as TreeEntry, ot as evaluate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as CODE_REDIRECT, r as descFromText, rt as securityGuard, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as CRITICAL_PATTERNS, u as parseField, ut as GIT_BLOCKED, v as buildApexInstruction, vt as SOLID_REF, w as SKILL_TRIGGERS, wt as ModularArchitecture, x as detectRequiredSkills, xt as evaluateFileSize, y as buildClaudeMdContext, yt as countFrameworkCodeLines, z as PY_MODEL_RE } from "./index-BIGVNQB8.mjs";
9
9
  import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
10
10
  import { a as PRE_AUTH_GATES, c as evaluateApex, i as POST_AUTH_GATES, l as freshnessGate, n as ApexContext, o as brainstormGate, r as ApexGate, s as docConsultedGate, t as APEX_GATES, u as solidReadGate } from "./apex-Wdi1nq_w.mjs";
11
11
  import { a as ReminderState, c as readState, d as throttleMs, i as registryFile, l as setStateField, n as addRoot, o as lessonsFileFor, r as readRoots, s as nowStamp, t as ensureMemoryGitignore, u as stateFileFor } from "./index-DLYhervv.mjs";
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import { A as GIT_ASK, B as detectProjectType, C as SESSION_STATE_FRAGMENT, D as
8
8
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "./home-state-BXf38Zi1.mjs";
9
9
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-CWZegVdR.mjs";
10
10
  import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-PKVNBHge.mjs";
11
- import { A as detectCreationIntent, C as SKILL_TRIGGERS, D as MAX_EXA_RESULTS, F as docConsultedGate, I as evaluateApex, L as freshnessGate, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, O as MAX_TOKENS, P as brainstormGate, R as solidReadGate, S as usesTailwindUtilities, a as firstHeading, b as detectRequiredSkills, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as APEX_GATES, k as capVerbosity, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, v as parseBodyDesc, w as frameworkSolidGate, x as skillTriggerGate, y as parseField } from "./validate-DnLU4IHy.mjs";
11
+ import { A as capVerbosity, C as usesTailwindUtilities, F as brainstormGate, I as docConsultedGate, L as evaluateApex, M as APEX_GATES, N as POST_AUTH_GATES, O as MAX_EXA_RESULTS, P as PRE_AUTH_GATES, R as freshnessGate, S as skillTriggerGate, T as frameworkSolidGate, a as firstHeading, b as parseField, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as detectCreationIntent, k as MAX_TOKENS, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as SKILL_TRIGGERS, x as detectRequiredSkills, y as parseBodyDesc, z as solidReadGate } from "./validate-DhOX5hDK.mjs";
12
12
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
13
13
  import { a as nowStamp, c as stateFileFor, i as lessonsFileFor, l as throttleMs, n as readRoots, o as readState, r as registryFile, s as setStateField, t as addRoot, u as ensureMemoryGitignore } from "./registry-CymilZiZ.mjs";
14
14
  import { a as cacheLookupSubstring, c as cacheStore, d as loadIndex, f as summarizeIndex, h as queryHash, i as cacheLookupMeta, l as mcpCacheKey, m as jaccardSimilar, n as webfetchCacheWrite, o as cacheLookupSubstringMeta, p as compactMarkdown, r as cacheLookup, s as cachePath, t as mcpCacheWrite, u as extractText } from "./mcp-store-BkBDmuxN.mjs";
@@ -1,3 +1,3 @@
1
- import { $ as protectedPathGuard, A as FAIL_CLOSED, B as RUST_DECL_RE, C as usesTailwindUtilities, Ct as DEV_KEYWORDS, D as MAX_TOKENS, Dt as detectProjectType, E as MAX_EXA_RESULTS, Et as detectModularArchitecture, F as installGuard, G as ASK_WRITERS, H as TS_DECL_RE, I as GO_DECL_RE, J as FILE_REDIRECT, K as CODE_MUTATORS, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as isApexCommand, P as runGuards, Q as PROTECTED_GIT_RE, R as PHP_DECL_RE, S as skillTriggerGate, St as detectFramework, T as frameworkSolidGate, Tt as ProjectType, U as interfaceSeparationGuard, V as SWIFT_PROTO_RE, W as bashWriteGuard, X as SESSION_STATE_FRAGMENT, Y as SAFE_PREFIXES, Z as PROTECTED_FRAGMENTS, _ as DEV_VERBS, _t as PLUGINS_DIR, a as firstHeading, at as GuardContext, b as detectClaudeMdProjectType, bt as countLines, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as PROJECT_INSTALL, et as ASK_PATTERNS, f as PROJECT_INDICATORS, ft as RALPH_SAFE, g as loadApexTaskState, gt as FileSizeVerdict, h as buildApexTaskInjection, ht as matchPatterns, i as firstComment, it as Guard, j as GUARDS, k as detectCreationIntent, kt as requiredArchSkill, l as parseBodyDesc, lt as GIT_ASK, m as buildApexTaskContext, mt as isRalphMode, n as missingSeoElements, nt as LabeledPattern, o as TreeEntry, ot as evaluate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as CODE_REDIRECT, r as descFromText, rt as securityGuard, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as CRITICAL_PATTERNS, u as parseField, ut as GIT_BLOCKED, v as buildApexInstruction, vt as SOLID_REF, w as SKILL_TRIGGERS, wt as ModularArchitecture, x as detectRequiredSkills, xt as evaluateFileSize, y as buildClaudeMdContext, yt as countFrameworkCodeLines, z as PY_MODEL_RE } from "../index-DJw1OGwE.mjs";
1
+ import { $ as protectedPathGuard, A as FAIL_CLOSED, B as RUST_DECL_RE, C as usesTailwindUtilities, Ct as DEV_KEYWORDS, D as MAX_TOKENS, Dt as detectProjectType, E as MAX_EXA_RESULTS, Et as detectModularArchitecture, F as installGuard, G as ASK_WRITERS, H as TS_DECL_RE, I as GO_DECL_RE, J as FILE_REDIRECT, K as CODE_MUTATORS, L as JAVA_DECL_RE, M as clearUserGuards, N as registerGuard, O as capVerbosity, Ot as isApexCommand, P as runGuards, Q as PROTECTED_GIT_RE, R as PHP_DECL_RE, S as skillTriggerGate, St as detectFramework, T as frameworkSolidGate, Tt as ProjectType, U as interfaceSeparationGuard, V as SWIFT_PROTO_RE, W as bashWriteGuard, X as SESSION_STATE_FRAGMENT, Y as SAFE_PREFIXES, Z as PROTECTED_FRAGMENTS, _ as DEV_VERBS, _t as PLUGINS_DIR, a as firstHeading, at as GuardContext, b as detectClaudeMdProjectType, bt as countLines, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as PROJECT_INSTALL, et as ASK_PATTERNS, f as PROJECT_INDICATORS, ft as RALPH_SAFE, g as loadApexTaskState, gt as FileSizeVerdict, h as buildApexTaskInjection, ht as matchPatterns, i as firstComment, it as Guard, j as GUARDS, k as detectCreationIntent, kt as requiredArchSkill, l as parseBodyDesc, lt as GIT_ASK, m as buildApexTaskContext, mt as isRalphMode, n as missingSeoElements, nt as LabeledPattern, o as TreeEntry, ot as evaluate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as CODE_REDIRECT, r as descFromText, rt as securityGuard, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as CRITICAL_PATTERNS, u as parseField, ut as GIT_BLOCKED, v as buildApexInstruction, vt as SOLID_REF, w as SKILL_TRIGGERS, wt as ModularArchitecture, x as detectRequiredSkills, xt as evaluateFileSize, y as buildClaudeMdContext, yt as countFrameworkCodeLines, z as PY_MODEL_RE } from "../index-BIGVNQB8.mjs";
2
2
  import { a as PRE_AUTH_GATES, c as evaluateApex, i as POST_AUTH_GATES, l as freshnessGate, n as ApexContext, o as brainstormGate, r as ApexGate, s as docConsultedGate, t as APEX_GATES, u as solidReadGate } from "../apex-Wdi1nq_w.mjs";
3
3
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexTaskState, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, Guard, GuardContext, JAVA_DECL_RE, LabeledPattern, MAX_EXA_RESULTS, MAX_TOKENS, ModularArchitecture, PHP_DECL_RE, PLUGINS_DIR, POST_AUTH_GATES, PRE_AUTH_GATES, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, type PolicyContext, type PolicyResult, ProjectType, RALPH_SAFE, RUST_DECL_RE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, TreeEntry, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, capVerbosity, clearUserGuards, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, isHtmlLike, isRalphMode, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate, usesTailwindUtilities };
@@ -1,5 +1,5 @@
1
1
  import { A as GIT_ASK, B as detectProjectType, C as SESSION_STATE_FRAGMENT, D as ASK_PATTERNS, E as protectedPathGuard, F as isRalphMode, H as requiredArchSkill, I as matchPatterns, L as detectFramework, M as PROJECT_INSTALL, N as RALPH_SAFE, O as CRITICAL_PATTERNS, P as SYSTEM_INSTALL, R as DEV_KEYWORDS, S as SAFE_PREFIXES, T as PROTECTED_GIT_RE, V as isApexCommand, _ as bashWriteGuard, a as registerGuard, b as CODE_REDIRECT, c as GO_DECL_RE, d as PY_MODEL_RE, f as RUST_DECL_RE, h as interfaceSeparationGuard, i as clearUserGuards, j as GIT_BLOCKED, k as securityGuard, l as JAVA_DECL_RE, m as TS_DECL_RE, n as FAIL_CLOSED, o as runGuards, p as SWIFT_PROTO_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as ASK_WRITERS, w as PROTECTED_FRAGMENTS, x as FILE_REDIRECT, y as CODE_MUTATORS, z as detectModularArchitecture } from "../evaluate-ClfbCDiY.mjs";
2
2
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "../home-state-BXf38Zi1.mjs";
3
- import { A as detectCreationIntent, C as SKILL_TRIGGERS, D as MAX_EXA_RESULTS, F as docConsultedGate, I as evaluateApex, L as freshnessGate, M as POST_AUTH_GATES, N as PRE_AUTH_GATES, O as MAX_TOKENS, P as brainstormGate, R as solidReadGate, S as usesTailwindUtilities, a as firstHeading, b as detectRequiredSkills, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as APEX_GATES, k as capVerbosity, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, v as parseBodyDesc, w as frameworkSolidGate, x as skillTriggerGate, y as parseField } from "../validate-DnLU4IHy.mjs";
3
+ import { A as capVerbosity, C as usesTailwindUtilities, F as brainstormGate, I as docConsultedGate, L as evaluateApex, M as APEX_GATES, N as POST_AUTH_GATES, O as MAX_EXA_RESULTS, P as PRE_AUTH_GATES, R as freshnessGate, S as skillTriggerGate, T as frameworkSolidGate, a as firstHeading, b as parseField, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as detectClaudeMdProjectType, h as buildClaudeMdContext, i as firstComment, j as detectCreationIntent, k as MAX_TOKENS, l as PROJECT_INDICATORS, m as buildApexInstruction, n as missingSeoElements, o as parseEnrichment, p as DEV_VERBS, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as SKILL_TRIGGERS, x as detectRequiredSkills, y as parseBodyDesc, z as solidReadGate } from "../validate-DhOX5hDK.mjs";
4
4
  import "../policy-la_KkjCS.mjs";
5
5
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, PHP_DECL_RE, PLUGINS_DIR, POST_AUTH_GATES, PRE_AUTH_GATES, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, RALPH_SAFE, RUST_DECL_RE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, capVerbosity, clearUserGuards, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, isHtmlLike, isRalphMode, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate, usesTailwindUtilities };
@@ -287,18 +287,20 @@ declare function claudeMdKey(prompt: string, ctx: string): string;
287
287
  * is emitted on EVERY message" is thus preserved.
288
288
  * @param prompt - The raw user prompt.
289
289
  * @param cwd - Project root (for project-type detection).
290
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
290
291
  * @returns The native hook stdout (possibly empty).
291
292
  */
292
- declare function promptSubmitContext(prompt: string, cwd: string): string;
293
+ declare function promptSubmitContext(prompt: string, cwd: string, id?: string): string;
293
294
  /**
294
295
  * PreToolUse Task context injection: render the APEX sub-agent context as a
295
296
  * Claude `additionalContext` response when `.claude/apex/` exists, else "".
296
297
  * Harness-produced (not owner CLAUDE.md content), so it is subject to the
297
298
  * per-fragment {@link capFragment} budget — unlike {@link promptSubmitContext}.
298
299
  * @param cwd - Fallback project root when `CLAUDE_PROJECT_DIR` is unset.
300
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
299
301
  * @returns The native hook stdout (possibly empty).
300
302
  */
301
- declare function taskContext(cwd: string): string;
303
+ declare function taskContext(cwd: string, id?: string): string;
302
304
  //#endregion
303
305
  //#region src/runtime/home-state.d.ts
304
306
  /** Home `~/.claude` dir — per-harness config (CLAUDE.md, logs, plugins). */
@@ -472,13 +474,15 @@ declare function logToolFailure(data: Record<string, unknown>, home?: string, no
472
474
  //#endregion
473
475
  //#region src/runtime/lifecycle/pre-compact.d.ts
474
476
  /**
475
- * Handle PreCompact: back up `.claude/apex/task.json` to `backups/`, keep only
476
- * the 5 newest, and emit a confirmation. Ports `pre-compact/save-apex-state.py`.
477
+ * Handle PreCompact: back up the target apex `task.json` (`.claude/apex/`,
478
+ * `.codex/apex/`, ...) to `backups/`, keep only the 5 newest, and emit a
479
+ * confirmation. Ports `pre-compact/save-apex-state.py`.
477
480
  * @param cwd - Project root.
478
481
  * @param now - Clock (defaults to `Date.now()`).
482
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
479
483
  * @returns The native hook stdout (possibly empty when no task.json).
480
484
  */
481
- declare function saveApexState(cwd: string, now?: number): string;
485
+ declare function saveApexState(cwd: string, now?: number, id?: string): string;
482
486
  //#endregion
483
487
  //#region src/runtime/lifecycle/session-end.d.ts
484
488
  /**
@@ -526,11 +530,11 @@ declare function postEditTypescript(filePath: string): string;
526
530
  /**
527
531
  * Dispatch an ai-pilot-scope lifecycle event. Returns the native stdout, or
528
532
  * `null` when unhandled (caller falls through to the default pipeline).
529
- * @param home - Home dir for cache resolution (defaults to `~`; injectable for test isolation).
533
+ * @param home - Home dir for cache resolution (defaults to `~`; injectable for test isolation); `id` selects the harness target (defaults to "claude-code").
530
534
  */
531
- declare function dispatchAipilot(event: string, payload: Record<string, unknown>, cwd: string, now: number, home?: string): Promise<string | null>;
532
- /** PostToolUse (Write/Edit SOLID check, else TaskCreate/TaskUpdate sync) for the ai-pilot scope. */
533
- declare function aipilotPostToolUse(payload: Record<string, unknown>, cwd: string): Promise<string>;
535
+ declare function dispatchAipilot(event: string, payload: Record<string, unknown>, cwd: string, now: number, home?: string, id?: string): Promise<string | null>;
536
+ /** PostToolUse (Write/Edit SOLID check, else TaskCreate/TaskUpdate sync) for the ai-pilot scope; `id` selects the harness target (defaults to "claude-code"). */
537
+ declare function aipilotPostToolUse(payload: Record<string, unknown>, cwd: string, id?: string): Promise<string>;
534
538
  //#endregion
535
539
  //#region src/runtime/lifecycle/dispatch.d.ts
536
540
  /** Which plugin's hooks.json invoked the harness (selects SessionStart behavior). */
@@ -542,6 +546,8 @@ interface LifecycleInput {
542
546
  cwd: string;
543
547
  scope: PluginScope;
544
548
  now: number;
549
+ /** Harness target id (defaults to "claude-code" — zero-regression default). */
550
+ id?: string;
545
551
  }
546
552
  /**
547
553
  * Route a lifecycle/session/context hook event to its ported handler. Returns
@@ -815,9 +821,10 @@ declare function writePluginMap(outputDir: string, pluginName: string, version:
815
821
  * @param cwd - Project root.
816
822
  * @param scope - The invoking plugin scope (defaults to `core`).
817
823
  * @param now - Clock.
824
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
818
825
  * @returns The native stdout, or `null` when unhandled.
819
826
  */
820
- declare function lifecycleStdout(payload: Record<string, unknown>, cwd: string, scope: PluginScope, now: number): string | null;
827
+ declare function lifecycleStdout(payload: Record<string, unknown>, cwd: string, scope: PluginScope, now: number, id?: string): string | null;
821
828
  /**
822
829
  * Post-edit additions for core-scope PostToolUse: auto-document a Read of a
823
830
  * SKILL.md/README/docs file; else (Write/Edit) track cumulative session
@@ -828,9 +835,10 @@ declare function lifecycleStdout(payload: Record<string, unknown>, cwd: string,
828
835
  * @param scope - The invoking plugin scope.
829
836
  * @param event - The normalized event.
830
837
  * @param now - Clock.
838
+ * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
831
839
  * @returns The extra stdout (possibly empty).
832
840
  */
833
- declare function postEditContext(scope: PluginScope, event: NormalizedEvent, now: number): Promise<string>;
841
+ declare function postEditContext(scope: PluginScope, event: NormalizedEvent, now: number, id?: string): Promise<string>;
834
842
  //#endregion
835
843
  //#region src/runtime/handle-types.d.ts
836
844
  /** Options for {@link handleHook} (caller supplies the clock + project root). */
@@ -1,6 +1,6 @@
1
1
  import { r as projectLayout } from "../layout-C0jaaCQC.mjs";
2
2
  import { a as sanitizeSessionId, c as sessionsDir, i as loadSessionState, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, s as sessionStatePath, t as claudeHome } from "../home-state-BXf38Zi1.mjs";
3
- import { A as trackMcpResearch, At as defaultStateDir, B as generateProjectMap, C as seoPostToolUse, Ct as trimLogFile, D as securityAdvisoryForPatch, Dt as claudeMdKey, E as securityAdvisory, Et as projectContext, F as dispatchAipilot, Ft as loadSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as saveSecurityState, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStateDir, M as trackEnrichment, Mt as trackFile, N as dispatchLifecycle, Nt as normalizeEvent, O as postTrackingSideEffects, Ot as promptSubmitContext, P as aipilotPostToolUse, Pt as isoUtc, R as generateEcosystemMap, Rt as securityStatePath, S as postEditContext, St as removeOldFiles, T as dispatchMemory, Tt as gitContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as readRules, a as recordActivity, at as saveApexState, b as extractSymbols, bt as pruneEmptyDirs, c as MCP_TTL_MS, ct as trackAgentMemory, d as isMcpTool, dt as validateSolidGate, f as queryOf, ft as checkFileSize, g as gate, gt as injectRules, h as TRIVIAL_BUDGET, ht as solidDetectStart, i as respond, it as cleanupSession, j as trackSkillRead, jt as projectHash, k as trackWatchResearch, kt as taskContext, l as WEBFETCH_TTL_MS, lt as subagentCacheContext, m as REQUIRED_AGENTS, mt as detectSolidProfile, n as activityFor, nt as trackSessionChanges, o as mcpPostStore, ot as logToolFailure, p as DEFAULT_WINDOW_MS, pt as countLoc, q as listChildren, r as handlePre, rt as validateRulesLoaded, s as mcpPreIntercept, st as validateTeammateOutput, t as handleHook, tt as postEditTypescript, u as cacheQueryOf, ut as validateTailwind, v as detectDuplication, vt as runSessionStartCleanups, w as seoPostToolUseResponse, wt as devContext, x as lifecycleStdout, xt as purgeTtlTree, y as dryGate, yt as sessionStartCore, z as writePluginMap, zt as todayUtc } from "../handle-BDlk2utY.mjs";
3
+ import { A as trackMcpResearch, At as defaultStateDir, B as generateProjectMap, C as seoPostToolUse, Ct as trimLogFile, D as securityAdvisoryForPatch, Dt as claudeMdKey, E as securityAdvisory, Et as projectContext, F as dispatchAipilot, Ft as loadSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as saveSecurityState, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStateDir, M as trackEnrichment, Mt as trackFile, N as dispatchLifecycle, Nt as normalizeEvent, O as postTrackingSideEffects, Ot as promptSubmitContext, P as aipilotPostToolUse, Pt as isoUtc, R as generateEcosystemMap, Rt as securityStatePath, S as postEditContext, St as removeOldFiles, T as dispatchMemory, Tt as gitContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as readRules, a as recordActivity, at as saveApexState, b as extractSymbols, bt as pruneEmptyDirs, c as MCP_TTL_MS, ct as trackAgentMemory, d as isMcpTool, dt as validateSolidGate, f as queryOf, ft as checkFileSize, g as gate, gt as injectRules, h as TRIVIAL_BUDGET, ht as solidDetectStart, i as respond, it as cleanupSession, j as trackSkillRead, jt as projectHash, k as trackWatchResearch, kt as taskContext, l as WEBFETCH_TTL_MS, lt as subagentCacheContext, m as REQUIRED_AGENTS, mt as detectSolidProfile, n as activityFor, nt as trackSessionChanges, o as mcpPostStore, ot as logToolFailure, p as DEFAULT_WINDOW_MS, pt as countLoc, q as listChildren, r as handlePre, rt as validateRulesLoaded, s as mcpPreIntercept, st as validateTeammateOutput, t as handleHook, tt as postEditTypescript, u as cacheQueryOf, ut as validateTailwind, v as detectDuplication, vt as runSessionStartCleanups, w as seoPostToolUseResponse, wt as devContext, x as lifecycleStdout, xt as purgeTtlTree, y as dryGate, yt as sessionStartCore, z as writePluginMap, zt as todayUtc } from "../handle-Dthtlp7Z.mjs";
4
4
  //#region src/runtime/storage.ts
5
5
  /**
6
6
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,