@fusengine/harness 0.1.32 → 0.1.34
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/adapters/claude/index.mjs +1 -1
- package/dist/adapters/cline/index.mjs +1 -1
- package/dist/adapters/codex/index.mjs +1 -1
- package/dist/adapters/cursor/index.mjs +1 -1
- package/dist/adapters/gemini/index.mjs +1 -1
- package/dist/claude-3PqBGt_7.mjs +137 -0
- package/dist/cli/bin.mjs +3 -3
- package/dist/cli/index.mjs +1 -1
- package/dist/{evaluate-9ch1K2kt.mjs → evaluate-zyxeVZPB.mjs} +44 -10
- package/dist/freshness/index.mjs +1 -1
- package/dist/{freshness-otdUpuvP.mjs → freshness-43gxYpiX.mjs} +1 -1
- package/dist/{handle-DJqHZcml.mjs → handle-DMHjTY1E.mjs} +192 -92
- package/dist/{index-DmbOUJK8.d.mts → index-QzK2dv0V.d.mts} +12 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +4 -4
- package/dist/init/index.mjs +1 -1
- package/dist/{json-io-CAn72gI4.mjs → json-io-CvSumjtz.mjs} +6 -2
- package/dist/policy/index.d.mts +1 -1
- package/dist/policy/index.mjs +2 -2
- package/dist/{run-CQbtlAKa.mjs → run-CUL70W0k.mjs} +1 -1
- package/dist/{run-D91N4ul1.mjs → run-Do2JltgU.mjs} +2 -2
- package/dist/runtime/index.d.mts +29 -2
- package/dist/runtime/index.mjs +2 -2
- package/dist/state/index.mjs +1 -1
- package/dist/{state-ByhLeKyD.mjs → state-BthKK4Jj.mjs} +1 -1
- package/dist/store-7j02oGjt.mjs +184 -0
- package/dist/tracking/index.d.mts +12 -2
- package/dist/tracking/index.mjs +1 -1
- package/dist/{validate-CccewDwk.mjs → validate-DLrWtaDR.mjs} +1 -1
- package/package.json +1 -1
- package/dist/claude-BWZcrZbS.mjs +0 -66
- package/dist/store-D-ge2ZPI.mjs +0 -89
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import { r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
|
|
2
2
|
import { r as projectLayout } from "./layout-C0jaaCQC.mjs";
|
|
3
3
|
import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
|
|
4
|
-
import { A as evaluateApex, E as detectCreationIntent, L as requiredArchSkill, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, l as parseField, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS$1 } from "./validate-
|
|
5
|
-
import { j as detectFramework, k as countLines, n as FAIL_CLOSED, t as evaluate } from "./evaluate-
|
|
4
|
+
import { A as evaluateApex, E as detectCreationIntent, L as requiredArchSkill, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, l as parseField, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS$1 } from "./validate-DLrWtaDR.mjs";
|
|
5
|
+
import { j as detectFramework, k as countLines, n as FAIL_CLOSED, t as evaluate } from "./evaluate-zyxeVZPB.mjs";
|
|
6
6
|
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
7
7
|
import { a as nowStamp, l as throttleMs, n as readRoots, o as readState, s as setStateField, t as addRoot } from "./registry-BkoEbdec.mjs";
|
|
8
8
|
import { a as extractText, o as loadIndex, r as cacheStore, t as cacheLookup } from "./store-PrNPm6So.mjs";
|
|
9
|
-
import {
|
|
9
|
+
import { a as writeJsonFile, i as readJsonFile, r as hashText, t as atomicWrite } from "./json-io-CvSumjtz.mjs";
|
|
10
10
|
import { t as loadRefs } from "./loader-CyAoJv2W.mjs";
|
|
11
|
-
import { a as recordAgent, c as recordRefRead, l as recordTrivialEdit, n as saveTrack, o as recordBrainstormRequired, r as agentsFresh, s as recordDoc, t as loadTrack, u as trivialCount } from "./store-
|
|
12
|
-
import { n as denyResponse, t as contextResponse } from "./claude-
|
|
11
|
+
import { a as recordAgent, c as recordRefRead, l as recordTrivialEdit, n as saveTrack, o as recordBrainstormRequired, r as agentsFresh, s as recordDoc, t as loadTrack, u as trivialCount } from "./store-7j02oGjt.mjs";
|
|
12
|
+
import { c as pathExists, d as spawnCapture, f as writeText, l as readText, n as denyResponse, s as collectFiles, t as contextResponse, u as sleep } from "./claude-3PqBGt_7.mjs";
|
|
13
13
|
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
14
14
|
import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
|
-
import { homedir
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
17
|
import { mkdir, rmdir } from "node:fs/promises";
|
|
18
18
|
import { execFileSync } from "node:child_process";
|
|
19
|
-
import { Glob } from "bun";
|
|
20
19
|
//#region src/runtime/activity.ts
|
|
21
20
|
/** Min response length (chars) for a lead agent call to count as `sufficient`. */
|
|
22
21
|
const AGENT_QUALITY_MIN = 500;
|
|
@@ -170,9 +169,54 @@ function normalizeEvent(id, payload) {
|
|
|
170
169
|
}
|
|
171
170
|
//#endregion
|
|
172
171
|
//#region src/runtime/paths.ts
|
|
173
|
-
/**
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
/**
|
|
173
|
+
* @module paths
|
|
174
|
+
* Runtime path helpers — per-project, out-of-tree harness state.
|
|
175
|
+
*
|
|
176
|
+
* Default base: ~/.claude/fuse-harness/state/<projectHash>/
|
|
177
|
+
* where projectHash = 8-char MD5 of CLAUDE_PROJECT_DIR (or cwd).
|
|
178
|
+
* Persistent and not world-writable (unlike /tmp), and OUTSIDE the repo so the
|
|
179
|
+
* agent has no "legitimate" reason to write it (the protected-path guard denies
|
|
180
|
+
* it, and the gate verifies freshness from the transcript, not this file).
|
|
181
|
+
*
|
|
182
|
+
* @packageDocumentation
|
|
183
|
+
*/
|
|
184
|
+
/** Resolve the project root from the environment or fall back to cwd. */
|
|
185
|
+
function resolveProjectDir() {
|
|
186
|
+
return process.env["CLAUDE_PROJECT_DIR"] ?? process.cwd();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Compute a stable 8-char hex hash for a project directory path.
|
|
190
|
+
* Delegates to `hashText` (MD5, non-cryptographic — used as a stable dir key only).
|
|
191
|
+
*
|
|
192
|
+
* @param projectDir - Absolute path to the project root; defaults to CLAUDE_PROJECT_DIR/cwd.
|
|
193
|
+
* @returns 8-char lowercase hex string.
|
|
194
|
+
*/
|
|
195
|
+
function projectHash$1(projectDir) {
|
|
196
|
+
return hashText(projectDir ?? resolveProjectDir());
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Canonical base directory for per-project harness state.
|
|
200
|
+
* Resolves to: ~/.claude/fuse-harness/state/<projectHash>/
|
|
201
|
+
*
|
|
202
|
+
* @param projectDir - Optional override for hashing; defaults to CLAUDE_PROJECT_DIR/cwd.
|
|
203
|
+
* @returns Absolute directory path (not yet created on disk).
|
|
204
|
+
*/
|
|
205
|
+
function defaultStateDir(projectDir) {
|
|
206
|
+
return join(homedir(), ".claude", "fuse-harness", "state", projectHash$1(projectDir));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Absolute path to a session's track JSON file.
|
|
210
|
+
*
|
|
211
|
+
* The session identifier is sanitised to `[A-Za-z0-9_-]` before use in the filename.
|
|
212
|
+
*
|
|
213
|
+
* @param sessionId - Claude session identifier (raw value accepted; sanitised internally).
|
|
214
|
+
* @param baseDir - Override the base directory. Omit in production; pass an explicit
|
|
215
|
+
* temp path in unit tests to avoid touching $HOME.
|
|
216
|
+
* @returns Absolute path, e.g. ~/.claude/fuse-harness/state/a1b2c3d4/track-abc123.json
|
|
217
|
+
*/
|
|
218
|
+
function trackFile(sessionId, baseDir) {
|
|
219
|
+
return join(baseDir ?? defaultStateDir(), `track-${sessionId.replace(/[^A-Za-z0-9_-]/g, "_") || "default"}.json`);
|
|
176
220
|
}
|
|
177
221
|
//#endregion
|
|
178
222
|
//#region src/runtime/record.ts
|
|
@@ -1910,8 +1954,8 @@ function cartographerContext() {
|
|
|
1910
1954
|
async function injectApexSubagentContext(cwd, home = homedir()) {
|
|
1911
1955
|
const apexDir = join(process.env.CLAUDE_PROJECT_DIR ?? cwd, ".claude", "apex");
|
|
1912
1956
|
if (!existsSync(apexDir)) return "";
|
|
1913
|
-
const
|
|
1914
|
-
const agents =
|
|
1957
|
+
const agentsPath = join(apexDir, "AGENTS.md");
|
|
1958
|
+
const agents = existsSync(agentsPath) ? readText(agentsPath).slice(0, 4e3) : "";
|
|
1915
1959
|
const taskData = await readJsonFile(join(apexDir, "task.json"));
|
|
1916
1960
|
return contextResponse("SubagentStart", `## APEX Sub-Agent Instructions
|
|
1917
1961
|
|
|
@@ -1967,7 +2011,7 @@ function cacheAge(ts, now = Date.now()) {
|
|
|
1967
2011
|
/** Full SHA-256 hex checksum of a file's text; "" when unreadable. */
|
|
1968
2012
|
async function fileChecksum(path) {
|
|
1969
2013
|
try {
|
|
1970
|
-
return createHash("sha256").update(
|
|
2014
|
+
return createHash("sha256").update(readText(path)).digest("hex");
|
|
1971
2015
|
} catch {
|
|
1972
2016
|
return "";
|
|
1973
2017
|
}
|
|
@@ -2036,9 +2080,8 @@ function parseEntries(raw) {
|
|
|
2036
2080
|
async function cacheAnalyticsSave(home = homedir(), now = Date.now()) {
|
|
2037
2081
|
const dir = join(cacheBaseDir(home), "analytics");
|
|
2038
2082
|
const sessionsFile = join(dir, "sessions.jsonl");
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
const raw = await file.text();
|
|
2083
|
+
if (!pathExists(sessionsFile)) return;
|
|
2084
|
+
const raw = readText(sessionsFile);
|
|
2042
2085
|
if (!raw.trim()) return;
|
|
2043
2086
|
const entries = parseEntries(raw);
|
|
2044
2087
|
if (entries.length === 0) return;
|
|
@@ -2066,8 +2109,7 @@ async function cacheAnalyticsSave(home = homedir(), now = Date.now()) {
|
|
|
2066
2109
|
}
|
|
2067
2110
|
await writeJsonFile(join(dir, "summary.json"), merged, true);
|
|
2068
2111
|
const cutoff = (/* @__PURE__ */ new Date(now - 30 * 864e5)).toISOString();
|
|
2069
|
-
|
|
2070
|
-
await Bun.write(sessionsFile, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
2112
|
+
writeText(sessionsFile, entries.filter((e) => e.ts >= cutoff).map((e) => JSON.stringify(e)).join("\n") + "\n");
|
|
2071
2113
|
}
|
|
2072
2114
|
//#endregion
|
|
2073
2115
|
//#region src/runtime/lifecycle/aipilot/inject-explore.ts
|
|
@@ -2091,17 +2133,11 @@ const CONFIG_FILES = [
|
|
|
2091
2133
|
/** Compute a config hash from git-tracked config files; "noconfig" on failure. */
|
|
2092
2134
|
async function configHash(cwd) {
|
|
2093
2135
|
try {
|
|
2094
|
-
const
|
|
2095
|
-
"git",
|
|
2136
|
+
const output = spawnCapture("git", [
|
|
2096
2137
|
"ls-tree",
|
|
2097
2138
|
"HEAD",
|
|
2098
2139
|
...CONFIG_FILES
|
|
2099
|
-
],
|
|
2100
|
-
cwd,
|
|
2101
|
-
stdout: "pipe",
|
|
2102
|
-
stderr: "ignore"
|
|
2103
|
-
});
|
|
2104
|
-
const output = await new Response(proc.stdout).text();
|
|
2140
|
+
], cwd);
|
|
2105
2141
|
return output.trim() ? hashText16(output) : "noconfig";
|
|
2106
2142
|
} catch {
|
|
2107
2143
|
return "noconfig";
|
|
@@ -2127,8 +2163,7 @@ async function injectExploreCache(cwd, home = homedir(), now = Date.now()) {
|
|
|
2127
2163
|
const cfgHash = await configHash(projPath);
|
|
2128
2164
|
let context = "";
|
|
2129
2165
|
const meta = await readJsonFile(metaFile);
|
|
2130
|
-
const
|
|
2131
|
-
const snapshot = await snapBunFile.exists() ? await snapBunFile.text() : "";
|
|
2166
|
+
const snapshot = pathExists(snapFile) ? readText(snapFile) : "";
|
|
2132
2167
|
if (meta?.timestamp && snapshot) {
|
|
2133
2168
|
const age = cacheAge(meta.timestamp, now);
|
|
2134
2169
|
if (age < TTL_SECONDS$2 && meta.config_hash === cfgHash) {
|
|
@@ -2164,9 +2199,9 @@ async function buildDocsContext(entries, docsDir, now) {
|
|
|
2164
2199
|
if (age > maxAge) maxAge = age;
|
|
2165
2200
|
if (!entry.hash || seen.has(entry.hash)) continue;
|
|
2166
2201
|
seen.add(entry.hash);
|
|
2167
|
-
const
|
|
2168
|
-
if (!
|
|
2169
|
-
const content =
|
|
2202
|
+
const docPath = join(docsDir, `${entry.hash}.md`);
|
|
2203
|
+
if (!pathExists(docPath)) continue;
|
|
2204
|
+
const content = readText(docPath);
|
|
2170
2205
|
if (!content) continue;
|
|
2171
2206
|
ctx += `\n${content}\n`;
|
|
2172
2207
|
count++;
|
|
@@ -2202,32 +2237,36 @@ async function injectDocCache(cwd, home = homedir(), now = Date.now()) {
|
|
|
2202
2237
|
* Ported from the ai-pilot plugin's `cache/source-collector.ts` +
|
|
2203
2238
|
* the stack detection in `cache/lesson-helpers.ts` (now removed).
|
|
2204
2239
|
*/
|
|
2205
|
-
/** Source
|
|
2206
|
-
const
|
|
2207
|
-
"
|
|
2208
|
-
"
|
|
2209
|
-
"
|
|
2210
|
-
"
|
|
2211
|
-
];
|
|
2240
|
+
/** Source extensions to collect (monorepo-aware, dot-prefixed for matching). */
|
|
2241
|
+
const SRC_EXTS = /* @__PURE__ */ new Set([
|
|
2242
|
+
".ts",
|
|
2243
|
+
".tsx",
|
|
2244
|
+
".js",
|
|
2245
|
+
".jsx"
|
|
2246
|
+
]);
|
|
2247
|
+
/** Roots walked: `src`, `app`, plus each child `src` under `apps/` and `packages/`. */
|
|
2248
|
+
const TOP_DIRS = ["src", "app"];
|
|
2249
|
+
const NESTED_PARENTS = ["apps", "packages"];
|
|
2250
|
+
/** Collect the existing monorepo `src` roots nested under `apps/` and `packages/`. */
|
|
2251
|
+
function nestedRoots(projectPath) {
|
|
2252
|
+
const roots = [];
|
|
2253
|
+
for (const parent of NESTED_PARENTS) try {
|
|
2254
|
+
for (const e of readdirSync(join(projectPath, parent), { withFileTypes: true })) if (e.isDirectory()) roots.push(join(projectPath, parent, e.name, "src"));
|
|
2255
|
+
} catch {}
|
|
2256
|
+
return roots;
|
|
2257
|
+
}
|
|
2212
2258
|
/**
|
|
2213
2259
|
* Scan source files in `projectPath` (monorepo-aware), capped at `maxFiles`.
|
|
2260
|
+
* Node+Bun portable: walks `node:fs` recursively (replaces the Bun `Glob`).
|
|
2214
2261
|
* @param projectPath - Absolute project root.
|
|
2215
2262
|
* @param maxFiles - Max files to collect (default 200).
|
|
2216
|
-
* @returns Absolute paths matching the source
|
|
2263
|
+
* @returns Absolute paths matching the source extensions.
|
|
2217
2264
|
*/
|
|
2218
2265
|
async function scanSourceFiles(projectPath, maxFiles = 200) {
|
|
2219
2266
|
const files = [];
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
cwd: projectPath,
|
|
2224
|
-
absolute: true
|
|
2225
|
-
})) {
|
|
2226
|
-
if (p.includes("node_modules")) continue;
|
|
2227
|
-
files.push(p);
|
|
2228
|
-
if (files.length >= maxFiles) break;
|
|
2229
|
-
}
|
|
2230
|
-
} catch {}
|
|
2267
|
+
const roots = [...TOP_DIRS.map((d) => join(projectPath, d)), ...nestedRoots(projectPath)];
|
|
2268
|
+
for (const root of roots) {
|
|
2269
|
+
collectFiles(root, SRC_EXTS, files, maxFiles);
|
|
2231
2270
|
if (files.length >= maxFiles) break;
|
|
2232
2271
|
}
|
|
2233
2272
|
return files;
|
|
@@ -2455,7 +2494,7 @@ function projectRootFromPaths(filePaths) {
|
|
|
2455
2494
|
}
|
|
2456
2495
|
/** Extract all absolute file paths from tool_use entries in a JSONL transcript. */
|
|
2457
2496
|
async function transcriptFilePaths(transcriptPath) {
|
|
2458
|
-
const text =
|
|
2497
|
+
const text = readText(transcriptPath);
|
|
2459
2498
|
const paths = /* @__PURE__ */ new Set();
|
|
2460
2499
|
for (const line of text.split("\n").filter(Boolean)) try {
|
|
2461
2500
|
const content = JSON.parse(line)?.message?.content;
|
|
@@ -2470,7 +2509,7 @@ async function transcriptFilePaths(transcriptPath) {
|
|
|
2470
2509
|
}
|
|
2471
2510
|
/** Extract deduplicated Edit tool_use entries (keyed by basename) from a transcript. */
|
|
2472
2511
|
async function transcriptEdits(transcriptPath) {
|
|
2473
|
-
const text =
|
|
2512
|
+
const text = readText(transcriptPath);
|
|
2474
2513
|
const edits = [];
|
|
2475
2514
|
for (const line of text.split("\n").filter(Boolean)) try {
|
|
2476
2515
|
const content = JSON.parse(line)?.message?.content;
|
|
@@ -2487,7 +2526,7 @@ async function transcriptEdits(transcriptPath) {
|
|
|
2487
2526
|
}
|
|
2488
2527
|
/** Extract the last assistant text report (first 500 lines) from a transcript. */
|
|
2489
2528
|
async function transcriptReport(transcriptPath) {
|
|
2490
|
-
const text =
|
|
2529
|
+
const text = readText(transcriptPath);
|
|
2491
2530
|
let lastReport = "";
|
|
2492
2531
|
for (const line of text.split("\n").filter(Boolean)) try {
|
|
2493
2532
|
const entry = JSON.parse(line);
|
|
@@ -2515,7 +2554,7 @@ const RETRY_DELAYS = [
|
|
|
2515
2554
|
];
|
|
2516
2555
|
/** Extract the longest assistant synthesis + queried library ids from a transcript. */
|
|
2517
2556
|
async function extractSynthesis(path) {
|
|
2518
|
-
const lines = (
|
|
2557
|
+
const lines = readText(path).split("\n").filter(Boolean);
|
|
2519
2558
|
const libraries = [];
|
|
2520
2559
|
let synthesis = "";
|
|
2521
2560
|
for (const line of lines) try {
|
|
@@ -2543,14 +2582,14 @@ async function extractSynthesis(path) {
|
|
|
2543
2582
|
* @param home - Home dir (defaults to `~`).
|
|
2544
2583
|
*/
|
|
2545
2584
|
async function cacheDocFromTranscript(transcript, cwd, home = homedir()) {
|
|
2546
|
-
if (!transcript || !
|
|
2585
|
+
if (!transcript || !pathExists(transcript)) return;
|
|
2547
2586
|
const projPath = projectRootFromPaths(await transcriptFilePaths(transcript)) ?? process.env.CLAUDE_PROJECT_DIR ?? cwd;
|
|
2548
2587
|
const cacheDir = cacheDirFor("doc", projPath, home);
|
|
2549
2588
|
const docsDir = join(cacheDir, "docs");
|
|
2550
2589
|
let result = await extractSynthesis(transcript);
|
|
2551
2590
|
for (const delay of RETRY_DELAYS) {
|
|
2552
2591
|
if (result.text.length >= MIN_TEXT_SIZE && result.libraries.length > 0) break;
|
|
2553
|
-
await
|
|
2592
|
+
await sleep(delay);
|
|
2554
2593
|
result = await extractSynthesis(transcript);
|
|
2555
2594
|
}
|
|
2556
2595
|
const { text, libraries } = result;
|
|
@@ -2564,7 +2603,7 @@ async function cacheDocFromTranscript(transcript, cwd, home = homedir()) {
|
|
|
2564
2603
|
const content = text.slice(0, MAX_DOC_SIZE);
|
|
2565
2604
|
const topic = libraries.join(", ");
|
|
2566
2605
|
const docHash = hashText16(topic);
|
|
2567
|
-
|
|
2606
|
+
writeText(join(docsDir, `${docHash}.md`), content);
|
|
2568
2607
|
const sizeKb = Math.floor(content.length / 1024);
|
|
2569
2608
|
for (const lib of libraries) {
|
|
2570
2609
|
index.docs = index.docs.filter((d) => d.library !== lib);
|
|
@@ -2594,7 +2633,7 @@ async function cacheDocFromTranscript(transcript, cwd, home = homedir()) {
|
|
|
2594
2633
|
* @param home - Home dir (defaults to `~`).
|
|
2595
2634
|
*/
|
|
2596
2635
|
async function cacheSniperLessons(transcript, cwd, home = homedir()) {
|
|
2597
|
-
if (!transcript || !
|
|
2636
|
+
if (!transcript || !pathExists(transcript)) return;
|
|
2598
2637
|
const edits = await transcriptEdits(transcript);
|
|
2599
2638
|
if (edits.length === 0) return;
|
|
2600
2639
|
const projectPath = projectRootFromPaths(edits.map((e) => e.file)) ?? process.env.CLAUDE_PROJECT_DIR ?? cwd;
|
|
@@ -2633,7 +2672,7 @@ async function cacheSniperLessons(transcript, cwd, home = homedir()) {
|
|
|
2633
2672
|
*/
|
|
2634
2673
|
/** Extract linter-related command/output text from a JSONL transcript. */
|
|
2635
2674
|
async function extractLinterOutput(path) {
|
|
2636
|
-
const text =
|
|
2675
|
+
const text = readText(path);
|
|
2637
2676
|
const outputs = [];
|
|
2638
2677
|
for (const line of text.split("\n").filter(Boolean)) try {
|
|
2639
2678
|
const content = JSON.parse(line)?.message?.content;
|
|
@@ -2655,7 +2694,7 @@ async function extractLinterOutput(path) {
|
|
|
2655
2694
|
* @param home - Home dir (defaults to `~`).
|
|
2656
2695
|
*/
|
|
2657
2696
|
async function cacheTestResults(transcript, cwd, home = homedir()) {
|
|
2658
|
-
if (!transcript || !
|
|
2697
|
+
if (!transcript || !pathExists(transcript)) return;
|
|
2659
2698
|
const projectPath = projectRootFromPaths(await transcriptFilePaths(transcript)) ?? process.env.CLAUDE_PROJECT_DIR ?? cwd;
|
|
2660
2699
|
const pHash = projectHash(projectPath);
|
|
2661
2700
|
const cacheDir = cacheDirFor("tests", projectPath, home);
|
|
@@ -2715,7 +2754,7 @@ async function acquireLock(lockDir, timeoutMs = 5e3) {
|
|
|
2715
2754
|
} catch {}
|
|
2716
2755
|
};
|
|
2717
2756
|
} catch {
|
|
2718
|
-
await
|
|
2757
|
+
await sleep(100);
|
|
2719
2758
|
}
|
|
2720
2759
|
return null;
|
|
2721
2760
|
}
|
|
@@ -2781,16 +2820,7 @@ async function taskComplete(file, id) {
|
|
|
2781
2820
|
/** True when the project has uncommitted git changes. */
|
|
2782
2821
|
async function hasGitChanges(cwd) {
|
|
2783
2822
|
try {
|
|
2784
|
-
|
|
2785
|
-
"git",
|
|
2786
|
-
"status",
|
|
2787
|
-
"--porcelain"
|
|
2788
|
-
], {
|
|
2789
|
-
cwd,
|
|
2790
|
-
stdout: "pipe",
|
|
2791
|
-
stderr: "ignore"
|
|
2792
|
-
});
|
|
2793
|
-
return (await new Response(proc.stdout).text()).trim().length > 0;
|
|
2823
|
+
return spawnCapture("git", ["status", "--porcelain"], cwd).trim().length > 0;
|
|
2794
2824
|
} catch {
|
|
2795
2825
|
return false;
|
|
2796
2826
|
}
|
|
@@ -3250,6 +3280,90 @@ function postEditContext(scope, event, now) {
|
|
|
3250
3280
|
return trackSessionChanges(event.sessionId, event.filePath, void 0, now) || postEditTypescript(event.filePath);
|
|
3251
3281
|
}
|
|
3252
3282
|
//#endregion
|
|
3283
|
+
//#region src/runtime/gate-helpers.ts
|
|
3284
|
+
/**
|
|
3285
|
+
* Code-only line count of the existing on-disk file (undefined if
|
|
3286
|
+
* absent/unreadable). Uses {@link countLines} (skips blank/comment lines) so a
|
|
3287
|
+
* partial Edit judges the full file by the SAME metric as the incoming snippet —
|
|
3288
|
+
* a raw `split("\n").length` would over-count JSDoc/blank lines (and add a
|
|
3289
|
+
* trailing-newline off-by-one), falsely blocking well-documented files.
|
|
3290
|
+
* @param path - Absolute path of the file being edited (or undefined).
|
|
3291
|
+
* @returns Code-only line count, or undefined when the file is absent/unreadable.
|
|
3292
|
+
*/
|
|
3293
|
+
function existingLineCount(path) {
|
|
3294
|
+
if (!path) return void 0;
|
|
3295
|
+
try {
|
|
3296
|
+
return existsSync(path) ? countLines(readFileSync(path, "utf8")) : void 0;
|
|
3297
|
+
} catch {
|
|
3298
|
+
return;
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
//#endregion
|
|
3302
|
+
//#region src/freshness/agent-evidence.ts
|
|
3303
|
+
/**
|
|
3304
|
+
* Platform-authored transcript evidence for APEX agent freshness.
|
|
3305
|
+
* Parses the Claude Code session JSONL transcript to find genuine Task
|
|
3306
|
+
* tool_use entries — forging this requires writing into the transcript file
|
|
3307
|
+
* which the Claude Code platform controls, unlike the self-recorded track.
|
|
3308
|
+
*/
|
|
3309
|
+
/** Parse a raw `timestamp` field to epoch ms; `undefined` when absent or invalid. */
|
|
3310
|
+
function parseTs(raw) {
|
|
3311
|
+
if (raw === void 0) return void 0;
|
|
3312
|
+
if (typeof raw === "number") return raw;
|
|
3313
|
+
const ms = Date.parse(raw);
|
|
3314
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
3315
|
+
}
|
|
3316
|
+
/**
|
|
3317
|
+
* Return `true` ONLY when, for EVERY name in `names`, the Claude Code
|
|
3318
|
+
* transcript at `transcriptPath` contains a genuine `tool_use` of the `Task`
|
|
3319
|
+
* tool whose `subagent_type` (or `name`) input field matches, with the entry
|
|
3320
|
+
* timestamp within `windowMs` of `now`.
|
|
3321
|
+
*
|
|
3322
|
+
* **Timestamp note:** when a transcript entry carries no `timestamp` field it
|
|
3323
|
+
* is counted as within-window (we cannot prove staleness). This is
|
|
3324
|
+
* intentionally lenient to stay robust across transcript-format evolution; the
|
|
3325
|
+
* tamper-resistance guarantee derives from the platform authoring the file —
|
|
3326
|
+
* not from the timestamp alone.
|
|
3327
|
+
*
|
|
3328
|
+
* @param transcriptPath - Absolute path to the session `.jsonl` transcript
|
|
3329
|
+
* (hook payload field: `transcript_path`). Returns `false` when `undefined`.
|
|
3330
|
+
* @param names - Required agent `subagent_type` values — ALL must appear.
|
|
3331
|
+
* @param windowMs - Freshness window in milliseconds.
|
|
3332
|
+
* @param now - Current epoch ms (pass `Date.now()` at the call-site).
|
|
3333
|
+
* @returns `true` when ALL agents have real, within-window transcript evidence.
|
|
3334
|
+
*/
|
|
3335
|
+
function agentsRanFromTranscript(transcriptPath, names, windowMs, now) {
|
|
3336
|
+
if (!transcriptPath || names.length === 0) return false;
|
|
3337
|
+
let text;
|
|
3338
|
+
try {
|
|
3339
|
+
text = readText(transcriptPath);
|
|
3340
|
+
} catch {
|
|
3341
|
+
return false;
|
|
3342
|
+
}
|
|
3343
|
+
const cutoff = now - windowMs;
|
|
3344
|
+
const found = /* @__PURE__ */ new Set();
|
|
3345
|
+
for (const line of text.split("\n")) {
|
|
3346
|
+
if (!line.trim()) continue;
|
|
3347
|
+
let entry;
|
|
3348
|
+
try {
|
|
3349
|
+
entry = JSON.parse(line);
|
|
3350
|
+
} catch {
|
|
3351
|
+
continue;
|
|
3352
|
+
}
|
|
3353
|
+
const ts = parseTs(entry.timestamp);
|
|
3354
|
+
if (ts !== void 0 && ts <= cutoff) continue;
|
|
3355
|
+
const content = entry.message?.content;
|
|
3356
|
+
if (!Array.isArray(content)) continue;
|
|
3357
|
+
for (const block of content) {
|
|
3358
|
+
if (block?.type !== "tool_use" || block.name !== "Task") continue;
|
|
3359
|
+
const agent = block.input?.subagent_type ?? block.input?.name;
|
|
3360
|
+
if (typeof agent === "string" && names.includes(agent)) found.add(agent);
|
|
3361
|
+
}
|
|
3362
|
+
if (found.size === names.length) return true;
|
|
3363
|
+
}
|
|
3364
|
+
return names.every((n) => found.has(n));
|
|
3365
|
+
}
|
|
3366
|
+
//#endregion
|
|
3253
3367
|
//#region src/runtime/dry-patterns.ts
|
|
3254
3368
|
/** Short identifiers never worth a duplication check (control flow, tiny names). */
|
|
3255
3369
|
const DRY_KEYWORDS = /* @__PURE__ */ new Set([
|
|
@@ -3585,22 +3699,6 @@ const DEFAULT_WINDOW_MS = 12e4;
|
|
|
3585
3699
|
/** Trivial edits allowed within the window before the full APEX gates apply. */
|
|
3586
3700
|
const TRIVIAL_BUDGET = 4;
|
|
3587
3701
|
/**
|
|
3588
|
-
* Code-only line count of the existing on-disk file (undefined if
|
|
3589
|
-
* absent/unreadable). Uses {@link countLines} (skips blank/comment lines) to
|
|
3590
|
-
* mirror the Python `count_code_lines(get_full_file_content(...))`, so a partial
|
|
3591
|
-
* Edit judges the full file by the SAME metric as the incoming snippet — a raw
|
|
3592
|
-
* `split("\n").length` would over-count JSDoc/blank lines (and add a
|
|
3593
|
-
* trailing-newline off-by-one), falsely blocking well-documented files.
|
|
3594
|
-
*/
|
|
3595
|
-
function existingLineCount(path) {
|
|
3596
|
-
if (!path) return void 0;
|
|
3597
|
-
try {
|
|
3598
|
-
return existsSync(path) ? countLines(readFileSync(path, "utf8")) : void 0;
|
|
3599
|
-
} catch {
|
|
3600
|
-
return;
|
|
3601
|
-
}
|
|
3602
|
-
}
|
|
3603
|
-
/**
|
|
3604
3702
|
* Full gate: the stateless guards (file-size, git, security...) first, then a
|
|
3605
3703
|
* trivial-edit fast path, then the stateful APEX gates fed from the session
|
|
3606
3704
|
* track. Returns the first blocking prompt, or null to allow.
|
|
@@ -3635,6 +3733,7 @@ async function gate(input) {
|
|
|
3635
3733
|
await saveTrack(input.trackFile, recordTrivialEdit(track, input.now, window, input.now));
|
|
3636
3734
|
return null;
|
|
3637
3735
|
}
|
|
3736
|
+
const freshnessFor = (names) => input.transcriptPath ? agentsRanFromTranscript(input.transcriptPath, names, window, input.now) : agentsFresh(track, names, window, input.now);
|
|
3638
3737
|
const ctx = {
|
|
3639
3738
|
sessionId: input.sessionId,
|
|
3640
3739
|
framework: input.framework,
|
|
@@ -3643,9 +3742,9 @@ async function gate(input) {
|
|
|
3643
3742
|
authorizations: track.authorizations,
|
|
3644
3743
|
refs: input.refs,
|
|
3645
3744
|
refsRead: track.refsRead,
|
|
3646
|
-
agentsFresh:
|
|
3745
|
+
agentsFresh: freshnessFor([...REQUIRED_AGENTS]),
|
|
3647
3746
|
brainstormRequired: track.brainstormRequired,
|
|
3648
|
-
brainstormFresh:
|
|
3747
|
+
brainstormFresh: freshnessFor(["brainstorming"])
|
|
3649
3748
|
};
|
|
3650
3749
|
try {
|
|
3651
3750
|
const apex = evaluateApex(ctx);
|
|
@@ -3708,7 +3807,8 @@ async function handlePre(ctx) {
|
|
|
3708
3807
|
agentType: event.agentType,
|
|
3709
3808
|
windowMs: opts.windowMs,
|
|
3710
3809
|
now: opts.now,
|
|
3711
|
-
trackFile: file
|
|
3810
|
+
trackFile: file,
|
|
3811
|
+
transcriptPath: typeof payload.transcript_path === "string" ? payload.transcript_path : void 0
|
|
3712
3812
|
});
|
|
3713
3813
|
return prompt ? {
|
|
3714
3814
|
stdout: respond(id, prompt),
|
|
@@ -3733,7 +3833,7 @@ function rawEventName(payload) {
|
|
|
3733
3833
|
async function handleHook(id, payload, opts) {
|
|
3734
3834
|
const event = normalizeEvent(id, payload);
|
|
3735
3835
|
const layout = projectLayout(opts.cwd);
|
|
3736
|
-
const file = trackFile(event.sessionId,
|
|
3836
|
+
const file = trackFile(event.sessionId, defaultStateDir(opts.cwd));
|
|
3737
3837
|
const mcpDir = layout.cacheDir;
|
|
3738
3838
|
const framework = detectFramework(event.filePath ?? "", event.content ?? "");
|
|
3739
3839
|
if (designLifecycle(payload, mcpDir, opts.cwd, String(opts.now), opts.now)) return {
|
|
@@ -3803,4 +3903,4 @@ async function handleHook(id, payload, opts) {
|
|
|
3803
3903
|
});
|
|
3804
3904
|
}
|
|
3805
3905
|
//#endregion
|
|
3806
|
-
export { detectSolidProfile as $, dispatchLessons as A,
|
|
3906
|
+
export { detectSolidProfile as $, dispatchLessons as A, mcpPreIntercept as At, mergeLines as B, securityStateDir as C, defaultStateDir as Ct, dispatchLifecycle as D, MCP_TTL_MS as Dt, trackEnrichment as E, normalizeEvent as Et, writePluginMap as F, trackSessionChanges as G, getFileDesc as H, generateProjectMap as I, saveApexState as J, validateRulesLoaded as K, isProject as L, lessonsStateFileFor as M, activityFor as Mt, cartoSessionStart as N, aipilotPostToolUse as O, isMcpTool as Ot, generateEcosystemMap as P, subagentCacheContext as Q, writeTree as R, saveSecurityState as S, recordActivity as St, todayUtc as T, trackFile as Tt, listChildren as U, countFiles as V, postEditTypescript as W, validateTeammateOutput as X, logToolFailure as Y, trackAgentMemory as Z, trackWatchResearch as _, sessionStatePath as _t, TRIVIAL_BUDGET as a, pruneEmptyDirs as at, isoUtc as b, taskContext as bt, detectDuplication as c, trimLogFile as ct, lifecycleStdout as d, projectContext as dt, solidDetectStart as et, postEditContext as f, claudeHome as ft, postTrackingSideEffects as g, saveSessionState as gt, securityAdvisory as h, sanitizeSessionId as ht, REQUIRED_AGENTS as i, sessionStartCore as it, lessonsFileFor as j, queryOf as jt, dispatchAipilot as k, mcpPostStore as kt, dryGate as l, devContext as lt, seoPostToolUseResponse as m, loadSessionState as mt, handlePre as n, readRules as nt, gate as o, purgeTtlTree as ot, seoPostToolUse as p, fusengineCache as pt, cleanupSession as q, DEFAULT_WINDOW_MS as r, runSessionStartCleanups as rt, preCommitGate as s, removeOldFiles as st, handleHook as t, injectRules as tt, extractSymbols as u, gitContext as ut, trackMcpResearch as v, sessionsDir as vt, securityStatePath as w, projectHash$1 as wt, loadSecurityState as x, respond as xt, trackSkillRead as y, promptSubmitContext as yt, loadEnriched as z };
|
|
@@ -170,9 +170,19 @@ declare const ASK_PATTERNS: RegExp[];
|
|
|
170
170
|
declare function securityGuard(ctx: GuardContext): Prompt | null;
|
|
171
171
|
//#endregion
|
|
172
172
|
//#region src/policy/guards/protected-path.d.ts
|
|
173
|
-
/** Path fragments that mark a location as internal/generated state
|
|
173
|
+
/** Path fragments that mark a location as internal/generated state. */
|
|
174
174
|
declare const PROTECTED_FRAGMENTS: readonly string[];
|
|
175
|
-
/**
|
|
175
|
+
/**
|
|
176
|
+
* Blocks direct edits to internal/generated state directories.
|
|
177
|
+
*
|
|
178
|
+
* Covers:
|
|
179
|
+
* - Write / Edit tool calls whose `filePath` targets a protected fragment.
|
|
180
|
+
* - Bash commands that both reference a protected fragment *and* contain a
|
|
181
|
+
* recognisable shell write operation (best-effort; see `bashHasWriteOp`).
|
|
182
|
+
*
|
|
183
|
+
* @param ctx - The guard context (tool, filePath, command).
|
|
184
|
+
* @returns A blocking {@link Prompt}, or null to allow.
|
|
185
|
+
*/
|
|
176
186
|
declare function protectedPathGuard(ctx: GuardContext): Prompt | null;
|
|
177
187
|
//#endregion
|
|
178
188
|
//#region src/policy/guards/bash-write.d.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { a as detectHarness, i as HarnessVia, n as HarnessInfo, o as detectMode,
|
|
|
5
5
|
import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "./doc-helpers-CG1nuf-c.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 APEX_GATES, A as GUARDS, B as TS_DECL_RE, C as SKILL_TRIGGERS, Ct as detectProjectType, D as capVerbosity, E as MAX_TOKENS, F as GO_DECL_RE, G as bashWriteGuard, H as ASK_WRITERS, I as JAVA_DECL_RE, J as ASK_PATTERNS, K as PROTECTED_FRAGMENTS, L as PHP_DECL_RE, M as registerGuard, N as runGuards, O as detectCreationIntent, P as installGuard, Q as GuardContext, R as PY_MODEL_RE, S as skillTriggerGate, St as detectModularArchitecture, T as MAX_EXA_RESULTS, Tt as requiredArchSkill, U as CODE_MUTATORS, V as interfaceSeparationGuard, W as CODE_REDIRECT, X as securityGuard, Y as CRITICAL_PATTERNS, Z as Guard, _ as DEV_VERBS, _t as evaluateFileSize, a as firstHeading, at as freshnessGate, b as detectClaudeMdProjectType, bt as ModularArchitecture, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as GIT_BLOCKED, et as ApexContext, f as PROJECT_INDICATORS, ft as PROJECT_INSTALL, g as loadApexTaskState, gt as countLines, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as evaluateApex, j as clearUserGuards, k as FAIL_CLOSED, l as parseBodyDesc, lt as evaluate, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as brainstormGate, o as TreeEntry, ot as solidReadGate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as protectedPathGuard, r as descFromText, rt as docConsultedGate, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as ApexGate, u as parseField, ut as GIT_ASK, v as buildApexInstruction, vt as detectFramework, w as frameworkSolidGate, wt as isApexCommand, x as detectRequiredSkills, xt as ProjectType, y as buildClaudeMdContext, yt as DEV_KEYWORDS, z as SWIFT_PROTO_RE } from "./index-
|
|
8
|
+
import { $ as APEX_GATES, A as GUARDS, B as TS_DECL_RE, C as SKILL_TRIGGERS, Ct as detectProjectType, D as capVerbosity, E as MAX_TOKENS, F as GO_DECL_RE, G as bashWriteGuard, H as ASK_WRITERS, I as JAVA_DECL_RE, J as ASK_PATTERNS, K as PROTECTED_FRAGMENTS, L as PHP_DECL_RE, M as registerGuard, N as runGuards, O as detectCreationIntent, P as installGuard, Q as GuardContext, R as PY_MODEL_RE, S as skillTriggerGate, St as detectModularArchitecture, T as MAX_EXA_RESULTS, Tt as requiredArchSkill, U as CODE_MUTATORS, V as interfaceSeparationGuard, W as CODE_REDIRECT, X as securityGuard, Y as CRITICAL_PATTERNS, Z as Guard, _ as DEV_VERBS, _t as evaluateFileSize, a as firstHeading, at as freshnessGate, b as detectClaudeMdProjectType, bt as ModularArchitecture, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as GIT_BLOCKED, et as ApexContext, f as PROJECT_INDICATORS, ft as PROJECT_INSTALL, g as loadApexTaskState, gt as countLines, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as evaluateApex, j as clearUserGuards, k as FAIL_CLOSED, l as parseBodyDesc, lt as evaluate, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as brainstormGate, o as TreeEntry, ot as solidReadGate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as protectedPathGuard, r as descFromText, rt as docConsultedGate, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as ApexGate, u as parseField, ut as GIT_ASK, v as buildApexInstruction, vt as detectFramework, w as frameworkSolidGate, wt as isApexCommand, x as detectRequiredSkills, xt as ProjectType, y as buildClaudeMdContext, yt as DEV_KEYWORDS, z as SWIFT_PROTO_RE } from "./index-QzK2dv0V.mjs";
|
|
9
9
|
import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
|
|
10
10
|
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";
|
|
11
11
|
import { a as globToRe, i as scoreReferences, n as toRefMeta, o as parseFrontmatter, r as routeReferences, t as loadRefs } from "./index-DL8MxjuP.mjs";
|
package/dist/index.mjs
CHANGED
|
@@ -4,16 +4,16 @@ import { n as STATE_ROOT, r as projectLayout, t as STATE_GITIGNORE } from "./lay
|
|
|
4
4
|
import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
|
|
5
5
|
import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
|
|
6
6
|
import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-C8Nxxyn_.mjs";
|
|
7
|
-
import { A as evaluateApex, C as MAX_EXA_RESULTS, D as APEX_GATES, E as detectCreationIntent, F as detectProjectType, I as isApexCommand, L as requiredArchSkill, M as solidReadGate, N as DEV_KEYWORDS, O as brainstormGate, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, a as firstHeading, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, f as buildApexTaskContext, g as buildApexInstruction, h as DEV_VERBS, i as firstComment, j as freshnessGate, k as docConsultedGate, l as parseField, m as loadApexTaskState, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS, v as detectClaudeMdProjectType, w as MAX_TOKENS, x as SKILL_TRIGGERS, y as detectRequiredSkills } from "./validate-
|
|
8
|
-
import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "./evaluate-
|
|
7
|
+
import { A as evaluateApex, C as MAX_EXA_RESULTS, D as APEX_GATES, E as detectCreationIntent, F as detectProjectType, I as isApexCommand, L as requiredArchSkill, M as solidReadGate, N as DEV_KEYWORDS, O as brainstormGate, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, a as firstHeading, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, f as buildApexTaskContext, g as buildApexInstruction, h as DEV_VERBS, i as firstComment, j as freshnessGate, k as docConsultedGate, l as parseField, m as loadApexTaskState, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS, v as detectClaudeMdProjectType, w as MAX_TOKENS, x as SKILL_TRIGGERS, y as detectRequiredSkills } from "./validate-DLrWtaDR.mjs";
|
|
8
|
+
import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "./evaluate-zyxeVZPB.mjs";
|
|
9
9
|
import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
|
|
10
10
|
import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-D8cVrI-s.mjs";
|
|
11
11
|
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
12
12
|
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-BkoEbdec.mjs";
|
|
13
13
|
import { n as jaccardSimilar, r as queryHash, t as compactMarkdown } from "./cache-C9z9LclL.mjs";
|
|
14
14
|
import { a as extractText, i as mcpCacheKey, n as cachePath, o as loadIndex, r as cacheStore, s as summarizeIndex, t as cacheLookup } from "./store-PrNPm6So.mjs";
|
|
15
|
-
import { t as incrementTrivialEditCounter } from "./freshness-
|
|
15
|
+
import { t as incrementTrivialEditCounter } from "./freshness-43gxYpiX.mjs";
|
|
16
16
|
import { n as toRefMeta, t as loadRefs } from "./loader-CyAoJv2W.mjs";
|
|
17
|
-
import { a as ensureStateDir, c as stateFilePath, i as apexStateDir, l as acquireLock, n as taskCreate, o as loadState, r as taskStart, s as saveState, t as taskComplete } from "./state-
|
|
17
|
+
import { a as ensureStateDir, c as stateFilePath, i as apexStateDir, l as acquireLock, n as taskCreate, o as loadState, r as taskStart, s as saveState, t as taskComplete } from "./state-BthKK4Jj.mjs";
|
|
18
18
|
import { a as formatPath, c as colors, d as GRADIENT_BLOCKS, f as PROGRESS_BAR_DEFAULTS, i as formatCost, l as progressiveColor, m as TIME_INTERVALS, n as generateProgressBar, o as formatTimeLeft, p as PROGRESS_CHARS, r as formatBasename, s as formatTokens, t as generateGradientBar, u as COLOR_THRESHOLDS } from "./statusline-D87eUNXl.mjs";
|
|
19
19
|
export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, PHP_DECL_RE, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PY_MODEL_RE, SKILL_TRIGGERS, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, cacheLookup, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectHarness, detectMode, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, firstComment, firstHeading, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, frameworkSolidGate, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, isHtmlLike, jaccardSimilar, lessonsFileFor, loadApexTaskState, loadIndex, loadRefs, loadState, matchPatterns, mcpCacheKey, missingSeoElements, modeFor, nowStamp, parseBodyDesc, parseEnrichment, parseEntry, parseEnvInt, parseField, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, requiredArchSkill, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, skillTriggerGate, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel, walkUpFor };
|
package/dist/init/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as codexInit, i as clineInit, n as writeInitFile, o as cursorInit, r as claudeInit, s as geminiInit, t as initFor } from "../run-
|
|
1
|
+
import { a as codexInit, i as clineInit, n as writeInitFile, o as cursorInit, r as claudeInit, s as geminiInit, t as initFor } from "../run-Do2JltgU.mjs";
|
|
2
2
|
export { claudeInit, clineInit, codexInit, cursorInit, geminiInit, initFor, writeInitFile };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
import { mkdir } from "node:fs/promises";
|
|
6
6
|
//#region src/util/json-io.ts
|
|
7
7
|
/** Atomically write `data` to `path` (temp + rename, 0o600). Cross-FS safe on macOS/Linux. */
|
|
@@ -36,5 +36,9 @@ async function readJsonFile(path) {
|
|
|
36
36
|
async function writeJsonFile(path, data, compact = false) {
|
|
37
37
|
atomicWrite(path, compact ? compactJson(data) : JSON.stringify(data, null, 2));
|
|
38
38
|
}
|
|
39
|
+
/** 8-char MD5 of text (cache key; non-cryptographic). Portable Node+Bun. */
|
|
40
|
+
function hashText(text) {
|
|
41
|
+
return createHash("md5").update(text).digest("hex").slice(0, 8);
|
|
42
|
+
}
|
|
39
43
|
//#endregion
|
|
40
|
-
export { writeJsonFile as i, ensureDir as n,
|
|
44
|
+
export { writeJsonFile as a, readJsonFile as i, ensureDir as n, hashText as r, atomicWrite as t };
|
package/dist/policy/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as APEX_GATES, A as GUARDS, B as TS_DECL_RE, C as SKILL_TRIGGERS, Ct as detectProjectType, D as capVerbosity, E as MAX_TOKENS, F as GO_DECL_RE, G as bashWriteGuard, H as ASK_WRITERS, I as JAVA_DECL_RE, J as ASK_PATTERNS, K as PROTECTED_FRAGMENTS, L as PHP_DECL_RE, M as registerGuard, N as runGuards, O as detectCreationIntent, P as installGuard, Q as GuardContext, R as PY_MODEL_RE, S as skillTriggerGate, St as detectModularArchitecture, T as MAX_EXA_RESULTS, Tt as requiredArchSkill, U as CODE_MUTATORS, V as interfaceSeparationGuard, W as CODE_REDIRECT, X as securityGuard, Y as CRITICAL_PATTERNS, Z as Guard, _ as DEV_VERBS, _t as evaluateFileSize, a as firstHeading, at as freshnessGate, b as detectClaudeMdProjectType, bt as ModularArchitecture, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as GIT_BLOCKED, et as ApexContext, f as PROJECT_INDICATORS, ft as PROJECT_INSTALL, g as loadApexTaskState, gt as countLines, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as evaluateApex, j as clearUserGuards, k as FAIL_CLOSED, l as parseBodyDesc, lt as evaluate, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as brainstormGate, o as TreeEntry, ot as solidReadGate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as protectedPathGuard, r as descFromText, rt as docConsultedGate, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as ApexGate, u as parseField, ut as GIT_ASK, v as buildApexInstruction, vt as detectFramework, w as frameworkSolidGate, wt as isApexCommand, x as detectRequiredSkills, xt as ProjectType, y as buildClaudeMdContext, yt as DEV_KEYWORDS, z as SWIFT_PROTO_RE } from "../index-
|
|
1
|
+
import { $ as APEX_GATES, A as GUARDS, B as TS_DECL_RE, C as SKILL_TRIGGERS, Ct as detectProjectType, D as capVerbosity, E as MAX_TOKENS, F as GO_DECL_RE, G as bashWriteGuard, H as ASK_WRITERS, I as JAVA_DECL_RE, J as ASK_PATTERNS, K as PROTECTED_FRAGMENTS, L as PHP_DECL_RE, M as registerGuard, N as runGuards, O as detectCreationIntent, P as installGuard, Q as GuardContext, R as PY_MODEL_RE, S as skillTriggerGate, St as detectModularArchitecture, T as MAX_EXA_RESULTS, Tt as requiredArchSkill, U as CODE_MUTATORS, V as interfaceSeparationGuard, W as CODE_REDIRECT, X as securityGuard, Y as CRITICAL_PATTERNS, Z as Guard, _ as DEV_VERBS, _t as evaluateFileSize, a as firstHeading, at as freshnessGate, b as detectClaudeMdProjectType, bt as ModularArchitecture, c as parseEntry, ct as PolicyResult, d as EXCLUDE_DIRS, dt as GIT_BLOCKED, et as ApexContext, f as PROJECT_INDICATORS, ft as PROJECT_INSTALL, g as loadApexTaskState, gt as countLines, h as buildApexTaskInjection, ht as FileSizeVerdict, i as firstComment, it as evaluateApex, j as clearUserGuards, k as FAIL_CLOSED, l as parseBodyDesc, lt as evaluate, m as buildApexTaskContext, mt as matchPatterns, n as missingSeoElements, nt as brainstormGate, o as TreeEntry, ot as solidReadGate, p as ApexTaskState, pt as SYSTEM_INSTALL, q as protectedPathGuard, r as descFromText, rt as docConsultedGate, s as parseEnrichment, st as PolicyContext, t as isHtmlLike, tt as ApexGate, u as parseField, ut as GIT_ASK, v as buildApexInstruction, vt as detectFramework, w as frameworkSolidGate, wt as isApexCommand, x as detectRequiredSkills, xt as ProjectType, y as buildClaudeMdContext, yt as DEV_KEYWORDS, z as SWIFT_PROTO_RE } from "../index-QzK2dv0V.mjs";
|
|
2
2
|
export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexTaskState, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, Guard, GuardContext, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, ModularArchitecture, PHP_DECL_RE, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PY_MODEL_RE, PolicyContext, PolicyResult, ProjectType, SKILL_TRIGGERS, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, TreeEntry, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, capVerbosity, clearUserGuards, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, isHtmlLike, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate };
|
package/dist/policy/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as evaluateApex, C as MAX_EXA_RESULTS, D as APEX_GATES, E as detectCreationIntent, F as detectProjectType, I as isApexCommand, L as requiredArchSkill, M as solidReadGate, N as DEV_KEYWORDS, O as brainstormGate, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, a as firstHeading, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, f as buildApexTaskContext, g as buildApexInstruction, h as DEV_VERBS, i as firstComment, j as freshnessGate, k as docConsultedGate, l as parseField, m as loadApexTaskState, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS, v as detectClaudeMdProjectType, w as MAX_TOKENS, x as SKILL_TRIGGERS, y as detectRequiredSkills } from "../validate-
|
|
2
|
-
import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "../evaluate-
|
|
1
|
+
import { A as evaluateApex, C as MAX_EXA_RESULTS, D as APEX_GATES, E as detectCreationIntent, F as detectProjectType, I as isApexCommand, L as requiredArchSkill, M as solidReadGate, N as DEV_KEYWORDS, O as brainstormGate, P as detectModularArchitecture, S as frameworkSolidGate, T as capVerbosity, _ as buildClaudeMdContext, a as firstHeading, b as skillTriggerGate, c as parseBodyDesc, d as PROJECT_INDICATORS, f as buildApexTaskContext, g as buildApexInstruction, h as DEV_VERBS, i as firstComment, j as freshnessGate, k as docConsultedGate, l as parseField, m as loadApexTaskState, n as missingSeoElements, o as parseEnrichment, p as buildApexTaskInjection, r as descFromText, s as parseEntry, t as isHtmlLike, u as EXCLUDE_DIRS, v as detectClaudeMdProjectType, w as MAX_TOKENS, x as SKILL_TRIGGERS, y as detectRequiredSkills } from "../validate-DLrWtaDR.mjs";
|
|
2
|
+
import { A as evaluateFileSize, C as securityGuard, D as SYSTEM_INSTALL, E as PROJECT_INSTALL, O as matchPatterns, S as CRITICAL_PATTERNS, T as GIT_BLOCKED, _ as CODE_REDIRECT, a as registerGuard, b as protectedPathGuard, c as GO_DECL_RE, d as PY_MODEL_RE, f as SWIFT_PROTO_RE, g as CODE_MUTATORS, h as ASK_WRITERS, i as clearUserGuards, j as detectFramework, k as countLines, l as JAVA_DECL_RE, m as interfaceSeparationGuard, n as FAIL_CLOSED, o as runGuards, p as TS_DECL_RE, r as GUARDS, s as installGuard, t as evaluate, u as PHP_DECL_RE, v as bashWriteGuard, w as GIT_ASK, x as ASK_PATTERNS, y as PROTECTED_FRAGMENTS } from "../evaluate-zyxeVZPB.mjs";
|
|
3
3
|
import "../policy-la_KkjCS.mjs";
|
|
4
4
|
export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, PHP_DECL_RE, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PY_MODEL_RE, SKILL_TRIGGERS, SWIFT_PROTO_RE, SYSTEM_INSTALL, TS_DECL_RE, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, capVerbosity, clearUserGuards, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, isHtmlLike, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
|
|
2
|
-
import { t as evaluate } from "./evaluate-
|
|
2
|
+
import { t as evaluate } from "./evaluate-zyxeVZPB.mjs";
|
|
3
3
|
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
4
4
|
import { execSync } from "node:child_process";
|
|
5
5
|
//#region src/cli/run.ts
|