@fusengine/harness 0.1.77 → 0.1.78
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/dist/cli/bin.mjs +1 -1
- package/dist/{handle-BDlk2utY.mjs → handle-Dthtlp7Z.mjs} +73 -50
- package/dist/{index-DJw1OGwE.d.mts → index-BIGVNQB8.d.mts} +19 -11
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/policy/index.d.mts +1 -1
- package/dist/policy/index.mjs +1 -1
- package/dist/runtime/index.d.mts +19 -11
- package/dist/runtime/index.mjs +1 -1
- package/dist/{validate-DnLU4IHy.mjs → validate-DhOX5hDK.mjs} +76 -25
- package/package.json +1 -1
package/dist/cli/bin.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { t as detectHarness } from "../harness-Cb9xR8dC.mjs";
|
|
|
4
4
|
import { t as claudeHome } from "../home-state-BXf38Zi1.mjs";
|
|
5
5
|
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-3tyTW9Ud.mjs";
|
|
6
6
|
import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
|
|
7
|
-
import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, t as handleHook, zt as todayUtc } from "../handle-
|
|
7
|
+
import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, t as handleHook, zt as todayUtc } from "../handle-Dthtlp7Z.mjs";
|
|
8
8
|
import { p as readStdin$1 } from "../claude-51RSspJ1.mjs";
|
|
9
9
|
import { delimiter, join } from "node:path";
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
@@ -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
|
|
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
|
|
1446
|
-
* the 5 newest, and emit a
|
|
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
|
|
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:
|
|
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
|
|
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: ${
|
|
4098
|
-
- Pending: ${
|
|
4109
|
+
- Last completed: ${completed}
|
|
4110
|
+
- Pending: ${pending}
|
|
4099
4111
|
|
|
4100
4112
|
### 3. Before Starting Work
|
|
4101
|
-
-
|
|
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
|
|
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
|
-
-
|
|
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
|
|
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,
|
|
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/
|
|
5887
|
-
*
|
|
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,
|
|
5898
|
-
const docDir = join(root,
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
472
|
-
* `.claude/apex
|
|
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-
|
|
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
|
|
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";
|
package/dist/policy/index.d.mts
CHANGED
|
@@ -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-
|
|
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 };
|
package/dist/policy/index.mjs
CHANGED
|
@@ -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
|
|
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 };
|
package/dist/runtime/index.d.mts
CHANGED
|
@@ -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
|
|
476
|
-
* the 5 newest, and emit a
|
|
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). */
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -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-
|
|
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,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
|
|
2
|
-
import { c as ttlLabel } from "./dotenv-Jj8aL1FL.mjs";
|
|
2
|
+
import { c as ttlLabel, t as HOME_DIR } from "./dotenv-Jj8aL1FL.mjs";
|
|
3
3
|
import { R as DEV_KEYWORDS, g as moduleAwarePath } from "./evaluate-ClfbCDiY.mjs";
|
|
4
4
|
import { d as countFrameworkCodeLines, l as PLUGINS_DIR, u as SOLID_REF } from "./home-state-BXf38Zi1.mjs";
|
|
5
5
|
import { r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-CWZegVdR.mjs";
|
|
@@ -1187,9 +1187,48 @@ function getExpertAgent(type, pluginsDirOverride) {
|
|
|
1187
1187
|
return "general-purpose";
|
|
1188
1188
|
}
|
|
1189
1189
|
//#endregion
|
|
1190
|
-
//#region src/policy/
|
|
1191
|
-
/**
|
|
1192
|
-
|
|
1190
|
+
//#region src/policy/apex-target.ts
|
|
1191
|
+
/**
|
|
1192
|
+
* Harness-target helpers for the APEX context builders. Single source of
|
|
1193
|
+
* truth for the home-dir segment / root doc name / plan-tool idiom that
|
|
1194
|
+
* differ between Claude Code and Codex (and beyond), so the builders in
|
|
1195
|
+
* `claude-md-context.ts`, `apex-task-context.ts`, and `inject-apex.ts` never
|
|
1196
|
+
* hardcode `.claude`/`CLAUDE.md`/`TaskCreate` again. Runtime `id` values flow
|
|
1197
|
+
* through the pipeline as plain `string` (see `handleHook(id: string, ...)`),
|
|
1198
|
+
* so these helpers accept `string` and narrow internally — same idiom as the
|
|
1199
|
+
* existing `HOME_DIR[id] ?? ".claude"` precedent in `cartographer/detect.ts`.
|
|
1200
|
+
*/
|
|
1201
|
+
/**
|
|
1202
|
+
* Home-dir segment for a harness target (".claude", ".codex", ...). Falls
|
|
1203
|
+
* back to ".claude" for any harness without a {@link HOME_DIR} entry.
|
|
1204
|
+
* @param id - Harness id (e.g. "claude-code", "codex").
|
|
1205
|
+
* @returns The home-dir segment, e.g. ".claude".
|
|
1206
|
+
*/
|
|
1207
|
+
function harnessHomeSegment(id) {
|
|
1208
|
+
return HOME_DIR[id] ?? ".claude";
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Root instructions doc name for a harness target: "AGENTS.md" for Codex,
|
|
1212
|
+
* "CLAUDE.md" for every other target (including the default/unknown fallback).
|
|
1213
|
+
* @param id - Harness id.
|
|
1214
|
+
* @returns The doc file name.
|
|
1215
|
+
*/
|
|
1216
|
+
function apexDocName(id) {
|
|
1217
|
+
return id === "codex" ? "AGENTS.md" : "CLAUDE.md";
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Native plan/track tool name for a harness target: Codex's `update_plan` vs
|
|
1221
|
+
* Claude's `TaskCreate`. Covers only the PLAN-step line — other Claude-only
|
|
1222
|
+
* tool references (`TaskList`, `TaskUpdate`) are branched inline by the
|
|
1223
|
+
* builders since their surrounding prose differs structurally, not just by token.
|
|
1224
|
+
* @param id - Harness id.
|
|
1225
|
+
* @returns The plan-tool name.
|
|
1226
|
+
*/
|
|
1227
|
+
function apexPlanTool(id) {
|
|
1228
|
+
return id === "codex" ? "update_plan" : "TaskCreate";
|
|
1229
|
+
}
|
|
1230
|
+
//#endregion
|
|
1231
|
+
//#region src/policy/detect-claude-md-project-type.ts
|
|
1193
1232
|
/**
|
|
1194
1233
|
* Detect the project type from the cwd, reproducing the legacy Python logic:
|
|
1195
1234
|
* package.json containing "next" → nextjs, else "react" → react; else
|
|
@@ -1212,31 +1251,35 @@ function detectClaudeMdProjectType(cwd) {
|
|
|
1212
1251
|
} catch {}
|
|
1213
1252
|
return "generic";
|
|
1214
1253
|
}
|
|
1254
|
+
//#endregion
|
|
1255
|
+
//#region src/policy/claude-md-context.ts
|
|
1256
|
+
/** Dev-verb regex (FR/EN) that triggers the APEX preamble (case-insensitive). */
|
|
1257
|
+
const DEV_VERBS = /(cr[ée]er|impl[ée]menter|ajouter|d[ée]velopper|construire|build|refactor|migrer|implement|create|add|develop)/i;
|
|
1215
1258
|
/**
|
|
1216
1259
|
* Build the APEX instruction preamble for a development task.
|
|
1217
1260
|
* @param projectType - Detected project type label.
|
|
1218
1261
|
* @param maxLines - SOLID per-file line ceiling.
|
|
1262
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
1219
1263
|
* @returns The APEX instruction text.
|
|
1220
1264
|
*/
|
|
1221
|
-
function buildApexInstruction(projectType, maxLines) {
|
|
1265
|
+
function buildApexInstruction(projectType, maxLines, id = "claude-code") {
|
|
1222
1266
|
const expertAgent = getExpertAgent(projectType);
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
**TRACKING FILE**: [project]/.claude/apex/task.json — create it yourself via apex-methodology Step 0 (init-tracking) if missing
|
|
1226
|
-
|
|
1227
|
-
1. **ANALYZE** (MANDATORY - 3 AGENTS IN PARALLEL):
|
|
1228
|
-
- explore-codebase + research-expert + ${expertAgent} (framework expertise)\n - Project type detected: ${projectType}\n\n2. **PLAN**: Use TaskCreate to break down tasks (<${maxLines} lines per file)\n\n3. **EXECUTE**: ${expertAgent}, follow SOLID principles, split at ${maxLines - 10} lines\n\n4. **eLICIT**: self-review with NAMED elicitation techniques (apex ref 03.5-elicit) — fix findings BEFORE validation\n\n5. **VERIFY**: functional check — run it, confirm references⇔declarations consistency\n\n6. **eXAMINE**: Run sniper agent after ANY modification\n\n**GATE**: eLicit + Verify BEFORE sniper — NEVER skip.\n\n**IMPORTANT**: Read .claude/apex/task.json to check documentation status before writing code.`;
|
|
1267
|
+
const seg = harnessHomeSegment(id);
|
|
1268
|
+
return `INSTRUCTION: This is a development task. Use APEX methodology:\n\n**TRACKING FILE**: [project]/${seg}/apex/task.json — create it yourself via apex-methodology Step 0 (init-tracking) if missing\n\n1. **ANALYZE** (MANDATORY - 3 AGENTS IN PARALLEL):\n - explore-codebase + research-expert + ${expertAgent} (framework expertise)\n - Project type detected: ${projectType}\n\n2. **PLAN**: Use ${apexPlanTool(id)} to break down tasks (<${maxLines} lines per file)\n\n3. **EXECUTE**: ${expertAgent}, follow SOLID principles, split at ${maxLines - 10} lines\n\n4. **eLICIT**: self-review with NAMED elicitation techniques (apex ref 03.5-elicit) — fix findings BEFORE validation\n\n5. **VERIFY**: functional check — run it, confirm references⇔declarations consistency\n\n6. **eXAMINE**: Run sniper agent after ANY modification\n\n**GATE**: eLicit + Verify BEFORE sniper — NEVER skip.\n\n**IMPORTANT**: Read ${seg}/apex/task.json to check documentation status before writing code.`;
|
|
1229
1269
|
}
|
|
1230
1270
|
/**
|
|
1231
|
-
* Build the UserPromptSubmit injection text: read
|
|
1271
|
+
* Build the UserPromptSubmit injection text: read the target's root
|
|
1272
|
+
* instructions doc (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, ...) and,
|
|
1232
1273
|
* when the prompt matches a dev verb, prepend the APEX instruction. Returns
|
|
1233
|
-
* `null` when
|
|
1274
|
+
* `null` when the doc is absent/unreadable (the hook then emits nothing).
|
|
1234
1275
|
* @param prompt - The raw user prompt.
|
|
1235
1276
|
* @param cwd - Project root (for project-type detection).
|
|
1277
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
1236
1278
|
* @returns The injection text, or `null` to emit nothing.
|
|
1237
1279
|
*/
|
|
1238
|
-
function buildClaudeMdContext(prompt, cwd) {
|
|
1239
|
-
const
|
|
1280
|
+
function buildClaudeMdContext(prompt, cwd, id = "claude-code") {
|
|
1281
|
+
const docName = apexDocName(id);
|
|
1282
|
+
const claudeMd = join(homedir(), harnessHomeSegment(id), docName);
|
|
1240
1283
|
if (!existsSync(claudeMd)) return null;
|
|
1241
1284
|
let claudeContent;
|
|
1242
1285
|
try {
|
|
@@ -1244,8 +1287,8 @@ function buildClaudeMdContext(prompt, cwd) {
|
|
|
1244
1287
|
} catch {
|
|
1245
1288
|
return null;
|
|
1246
1289
|
}
|
|
1247
|
-
if (!DEV_VERBS.test(prompt) && !DEV_KEYWORDS.test(prompt)) return `#
|
|
1248
|
-
return `${buildApexInstruction(detectClaudeMdProjectType(cwd), resolveMaxLines())}\n\n#
|
|
1290
|
+
if (!DEV_VERBS.test(prompt) && !DEV_KEYWORDS.test(prompt)) return `# ${docName}\n${claudeContent}`;
|
|
1291
|
+
return `${buildApexInstruction(detectClaudeMdProjectType(cwd), resolveMaxLines(), id)}\n\n# ${docName}\n${claudeContent}`;
|
|
1249
1292
|
}
|
|
1250
1293
|
//#endregion
|
|
1251
1294
|
//#region src/policy/apex-task-context.ts
|
|
@@ -1282,21 +1325,29 @@ function loadApexTaskState(taskFile) {
|
|
|
1282
1325
|
* Build the APEX context string injected into a Task sub-agent prompt.
|
|
1283
1326
|
* @param state - The parsed task state.
|
|
1284
1327
|
* @param maxLines - SOLID per-file line ceiling.
|
|
1328
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
1285
1329
|
* @returns The injection text.
|
|
1286
1330
|
*/
|
|
1287
|
-
function buildApexTaskContext(state, maxLines) {
|
|
1288
|
-
|
|
1331
|
+
function buildApexTaskContext(state, maxLines, id = "claude-code") {
|
|
1332
|
+
const seg = harnessHomeSegment(id);
|
|
1333
|
+
const isCodex = id === "codex";
|
|
1334
|
+
const step3 = isCodex ? "update_plan → review the current plan" : "TaskList → see pending tasks";
|
|
1335
|
+
const step4 = isCodex ? "update_plan → mark the active step in_progress before starting" : "TaskUpdate(in_progress) → before starting";
|
|
1336
|
+
const step7 = isCodex ? "update_plan → mark the step completed when done" : "TaskUpdate(completed) → triggers auto-commit";
|
|
1337
|
+
return `⚠️ APEX MODE - Read ${seg}/apex/AGENTS.md for rules\n\nCurrent: Task #${state.id} - ${state.subject} (Phase: ${state.phase})\nDocs consulted: ${state.docs}\n\nAgent must:\n1. Read task.json → find last 3 completed tasks\n2. Read their notes in docs/ (task-{ID}-{subject}.md)\n3. ${step3}\n4. ${step4}\n5. Apply SOLID (files < ${maxLines} lines)\n6. Write notes to docs/task-{ID}-{subject}.md\n7. ${step7}`;
|
|
1289
1338
|
}
|
|
1290
1339
|
/**
|
|
1291
|
-
* Build the PreToolUse Task injection, gated on the existence of the
|
|
1292
|
-
* `.claude/apex
|
|
1340
|
+
* Build the PreToolUse Task injection, gated on the existence of the
|
|
1341
|
+
* project's target apex dir (`.claude/apex/`, `.codex/apex/`, ...). Returns
|
|
1342
|
+
* `null` when APEX is not active (no dir).
|
|
1293
1343
|
* @param projectRoot - `CLAUDE_PROJECT_DIR` or cwd.
|
|
1344
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
1294
1345
|
* @returns The injection text, or `null` to emit nothing.
|
|
1295
1346
|
*/
|
|
1296
|
-
function buildApexTaskInjection(projectRoot) {
|
|
1297
|
-
const apexDir = join(projectRoot,
|
|
1347
|
+
function buildApexTaskInjection(projectRoot, id = "claude-code") {
|
|
1348
|
+
const apexDir = join(projectRoot, harnessHomeSegment(id), "apex");
|
|
1298
1349
|
if (!existsSync(apexDir)) return null;
|
|
1299
|
-
return buildApexTaskContext(loadApexTaskState(join(apexDir, "task.json")), resolveMaxLines());
|
|
1350
|
+
return buildApexTaskContext(loadApexTaskState(join(apexDir, "task.json")), resolveMaxLines(), id);
|
|
1300
1351
|
}
|
|
1301
1352
|
//#endregion
|
|
1302
1353
|
//#region src/policy/cartographer/indicators.ts
|
|
@@ -1540,4 +1591,4 @@ function missingSeoElements(html) {
|
|
|
1540
1591
|
return missing;
|
|
1541
1592
|
}
|
|
1542
1593
|
//#endregion
|
|
1543
|
-
export {
|
|
1594
|
+
export { capVerbosity as A, usesTailwindUtilities as C, isExcludedSwiftPath as D, isExcludedJsPath as E, brainstormGate as F, docConsultedGate as I, evaluateApex as L, APEX_GATES as M, POST_AUTH_GATES as N, MAX_EXA_RESULTS as O, PRE_AUTH_GATES as P, freshnessGate as R, skillTriggerGate as S, frameworkSolidGate as T, harnessHomeSegment as _, firstHeading as a, parseField as b, EXCLUDE_DIRS as c, buildApexTaskInjection as d, loadApexTaskState as f, detectClaudeMdProjectType as g, buildClaudeMdContext as h, firstComment as i, detectCreationIntent as j, MAX_TOKENS as k, PROJECT_INDICATORS as l, buildApexInstruction as m, missingSeoElements as n, parseEnrichment as o, DEV_VERBS as p, descFromText as r, parseEntry as s, isHtmlLike as t, buildApexTaskContext as u, scanPlugin as v, SKILL_TRIGGERS as w, detectRequiredSkills as x, parseBodyDesc as y, solidReadGate as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusengine/harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.78",
|
|
4
4
|
"description": "Harness-agnostic toolkit for AI coding agents: runtime harness detection (Claude Code, Codex, Cursor, Cline, Gemini, Aider...), pure policy core (env config, project/framework detection, SOLID/file-size limits, APEX freshness, guard patterns, portable prompts), cache, project memory, ref routing, state/locks, statusline, per-harness adapters (Claude/Cursor/Cline/Gemini) and a cli-mode harness-check binary. Bun-native, with a built dist for Node + bundlers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|