@fusengine/harness 0.1.2 → 0.1.3

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.
@@ -1,5 +1,3 @@
1
- import { n as readJsonFile, r as writeJsonFile, t as ensureDir } from "./json-io-RH82El2J.mjs";
2
- import { dirname } from "node:path";
3
1
  //#region src/freshness/doc-helpers.ts
4
2
  /** Resolve the sessions array from an auth entry (legacy fallback). */
5
3
  function resolveSessions(auth) {
@@ -41,24 +39,4 @@ function formatDocDeny(framework) {
41
39
  ].join("\n");
42
40
  }
43
41
  //#endregion
44
- //#region src/freshness/trivial-edit-counter.ts
45
- /**
46
- * Increment a session's trivial-edit counter, evicting timestamps older than
47
- * `windowMs`. Decoupled + injectable `now` for testability.
48
- * @param filePath - session state file path
49
- * @param windowMs - sliding window in ms
50
- * @param now - current epoch ms (defaults to `Date.now()`)
51
- * @returns number of trivial edits within the window (including this one)
52
- */
53
- async function incrementTrivialEditCounter(filePath, windowMs, now = Date.now()) {
54
- await ensureDir(dirname(filePath));
55
- const state = await readJsonFile(filePath) ?? {};
56
- const cutoff = now - windowMs;
57
- const edits = (state.trivial_edits ?? []).filter((ts) => ts > cutoff);
58
- edits.push(now);
59
- state.trivial_edits = edits;
60
- await writeJsonFile(filePath, state);
61
- return edits.length;
62
- }
63
- //#endregion
64
- export { resolveSessions as a, isDocConsulted as i, formatDocDeny as n, formatDocSatisfactionStatus as r, incrementTrivialEditCounter as t };
42
+ export { resolveSessions as i, formatDocSatisfactionStatus as n, isDocConsulted as r, formatDocDeny as t };
@@ -1,2 +1,3 @@
1
- import { a as resolveSessions, i as isDocConsulted, n as formatDocDeny, r as formatDocSatisfactionStatus, t as incrementTrivialEditCounter } from "../freshness-DzGoBKKj.mjs";
1
+ import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "../doc-helpers-Dd_x1-tZ.mjs";
2
+ import { t as incrementTrivialEditCounter } from "../freshness-BK9Xg6oG.mjs";
2
3
  export { formatDocDeny, formatDocSatisfactionStatus, incrementTrivialEditCounter, isDocConsulted, resolveSessions };
@@ -0,0 +1,23 @@
1
+ import { n as readJsonFile, r as writeJsonFile, t as ensureDir } from "./json-io-RH82El2J.mjs";
2
+ import { dirname } from "node:path";
3
+ //#region src/freshness/trivial-edit-counter.ts
4
+ /**
5
+ * Increment a session's trivial-edit counter, evicting timestamps older than
6
+ * `windowMs`. Decoupled + injectable `now` for testability.
7
+ * @param filePath - session state file path
8
+ * @param windowMs - sliding window in ms
9
+ * @param now - current epoch ms (defaults to `Date.now()`)
10
+ * @returns number of trivial edits within the window (including this one)
11
+ */
12
+ async function incrementTrivialEditCounter(filePath, windowMs, now = Date.now()) {
13
+ await ensureDir(dirname(filePath));
14
+ const state = await readJsonFile(filePath) ?? {};
15
+ const cutoff = now - windowMs;
16
+ const edits = (state.trivial_edits ?? []).filter((ts) => ts > cutoff);
17
+ edits.push(now);
18
+ state.trivial_edits = edits;
19
+ await writeJsonFile(filePath, state);
20
+ return edits.length;
21
+ }
22
+ //#endregion
23
+ export { incrementTrivialEditCounter as t };
@@ -1,4 +1,6 @@
1
1
  import { t as Prompt } from "./types-D56jSgD9.mjs";
2
+ import { t as AuthEntry } from "./doc-helpers-CG1nuf-c.mjs";
3
+ import { t as RefMeta } from "./types-CY5qT2X1.mjs";
2
4
 
3
5
  //#region src/policy/detect-project.d.ts
4
6
  /** Project types detected from filesystem indicators. */
@@ -77,4 +79,36 @@ interface PolicyResult {
77
79
  */
78
80
  declare function evaluate(ctx: PolicyContext): PolicyResult;
79
81
  //#endregion
80
- export { GIT_BLOCKED as a, matchPatterns as c, evaluateFileSize as d, detectFramework as f, isApexCommand as g, detectProjectType as h, GIT_ASK as i, FileSizeVerdict as l, ProjectType as m, PolicyResult as n, PROJECT_INSTALL as o, DEV_KEYWORDS as p, evaluate as r, SYSTEM_INSTALL as s, PolicyContext as t, countLines as u };
82
+ //#region src/policy/apex.d.ts
83
+ /**
84
+ * Session context for the stateful APEX gates. The harness adapter supplies this
85
+ * (the package owns the gate LOGIC; recording the session activity is the
86
+ * adapter's tracking layer).
87
+ */
88
+ interface ApexContext {
89
+ sessionId: string;
90
+ framework: string;
91
+ filePath: string;
92
+ content: string;
93
+ /** Doc-consultation authorizations from session state (Context7/Exa). */
94
+ authorizations?: Record<string, AuthEntry>;
95
+ /** Available SOLID references for the framework's skill. */
96
+ refs?: RefMeta[];
97
+ /** Absolute paths of SOLID refs already read this session. */
98
+ refsRead?: string[];
99
+ }
100
+ /** A single APEX gate: returns a blocking {@link Prompt}, or null to pass. */
101
+ type ApexGate = (ctx: ApexContext) => Prompt | null;
102
+ /** Gate: Context7 + Exa must have been consulted this session. */
103
+ declare const docConsultedGate: ApexGate;
104
+ /** Gate: the routed SOLID references for this edit must have been read. */
105
+ declare const solidReadGate: ApexGate;
106
+ /** Default APEX gate chain. */
107
+ declare const APEX_GATES: ReadonlyArray<ApexGate>;
108
+ /**
109
+ * Run the APEX gates (chain-of-responsibility): the first failing gate's prompt
110
+ * wins; null means every gate passed (allow).
111
+ */
112
+ declare function evaluateApex(ctx: ApexContext, gates?: ReadonlyArray<ApexGate>): Prompt | null;
113
+ //#endregion
114
+ export { isApexCommand as S, evaluateFileSize as _, evaluateApex as a, ProjectType as b, PolicyResult as c, GIT_BLOCKED as d, PROJECT_INSTALL as f, countLines as g, FileSizeVerdict as h, docConsultedGate as i, evaluate as l, matchPatterns as m, ApexContext as n, solidReadGate as o, SYSTEM_INSTALL as p, ApexGate as r, PolicyContext as s, APEX_GATES as t, GIT_ASK as u, detectFramework as v, detectProjectType as x, DEV_KEYWORDS as y };
@@ -1,28 +1,5 @@
1
- //#region src/refs/types.d.ts
2
- /** Parsed frontmatter metadata from a reference .md file. */
3
- interface RefMeta {
4
- name: string;
5
- description: string;
6
- keywords: string;
7
- priority: string;
8
- related: string;
9
- appliesTo: string;
10
- triggerOnEdit: string;
11
- level: string;
12
- filePath: string;
13
- }
14
- /** A reference with its computed routing score. */
15
- interface ScoredRef {
16
- meta: RefMeta;
17
- score: number;
18
- }
19
- /** Routing result with categorized references. */
20
- interface RouteResult {
21
- required: ScoredRef[];
22
- optional: ScoredRef[];
23
- skillPath: string;
24
- }
25
- //#endregion
1
+ import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
2
+
26
3
  //#region src/refs/frontmatter.d.ts
27
4
  /** Extract frontmatter key/value pairs from markdown content (quotes stripped). */
28
5
  declare function parseFrontmatter(content: string): Record<string, string>;
@@ -41,4 +18,4 @@ declare function scoreReferences(refs: RefMeta[], filePath: string, content: str
41
18
  */
42
19
  declare function routeReferences(refs: RefMeta[], filePath: string, content: string, skillPath?: string): RouteResult | null;
43
20
  //#endregion
44
- export { RefMeta as a, parseFrontmatter as i, scoreReferences as n, RouteResult as o, globToRe as r, ScoredRef as s, routeReferences as t };
21
+ export { parseFrontmatter as i, scoreReferences as n, globToRe as r, routeReferences as t };
package/dist/index.d.mts CHANGED
@@ -5,9 +5,10 @@ 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 { i as compactJson, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./index-C1vLIMwN.mjs";
8
- import { a as GIT_BLOCKED, c as matchPatterns, d as evaluateFileSize, f as detectFramework, g as isApexCommand, h as detectProjectType, i as GIT_ASK, l as FileSizeVerdict, m as ProjectType, n as PolicyResult, o as PROJECT_INSTALL, p as DEV_KEYWORDS, r as evaluate, s as SYSTEM_INSTALL, t as PolicyContext, u as countLines } from "./index-D7MkQNdc.mjs";
8
+ import { S as isApexCommand, _ as evaluateFileSize, a as evaluateApex, b as ProjectType, c as PolicyResult, d as GIT_BLOCKED, f as PROJECT_INSTALL, g as countLines, h as FileSizeVerdict, i as docConsultedGate, l as evaluate, m as matchPatterns, n as ApexContext, o as solidReadGate, p as SYSTEM_INSTALL, r as ApexGate, s as PolicyContext, t as APEX_GATES, u as GIT_ASK, v as detectFramework, x as detectProjectType, y as DEV_KEYWORDS } from "./index-BXBWKbL8.mjs";
9
+ import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
9
10
  import { a as ReminderState, c as setStateField, i as registryFile, l as stateFileFor, n as addRoot, o as nowStamp, r as readRoots, s as readState, t as ensureMemoryGitignore, u as throttleMs } from "./index-BEM-mQMC.mjs";
10
- import { a as RefMeta, i as parseFrontmatter, n as scoreReferences, o as RouteResult, r as globToRe, s as ScoredRef, t as routeReferences } from "./index-DqNKW8Ki.mjs";
11
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./index-C2Lz-cwJ.mjs";
11
12
  import { a as taskStart, c as ensureStateDir, d as stateFilePath, f as acquireLock, i as taskCreate, l as loadState, n as ApexTaskFile, o as ApexState, r as taskComplete, s as apexStateDir, t as ApexTask, u as saveState } from "./index-CPoF_hLP.mjs";
12
13
  import { _ as TIME_INTERVALS, a as formatCost, c as formatTokens, d as colors, f as progressiveColor, g as PROGRESS_CHARS, h as PROGRESS_BAR_DEFAULTS, i as formatBasename, l as ColorFn, m as GRADIENT_BLOCKS, n as generateGradientBar, o as formatPath, p as COLOR_THRESHOLDS, r as generateProgressBar, s as formatTimeLeft, t as ProgressBarOptions, u as Palette } from "./index-BWK8slRi.mjs";
13
- export { ApexState, ApexTask, ApexTaskFile, AuthEntry, COLOR_THRESHOLDS, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DocSatisfactionStatus, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, HarnessId, HarnessInfo, HarnessMode, HarnessVia, IndexSummary, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, Palette, PolicyContext, PolicyResult, ProgressBarOptions, ProjectType, Prompt, PromptKind, RefMeta, ReminderState, RouteResult, SYSTEM_INSTALL, ScoredRef, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, ttlLabel };
14
+ export { APEX_GATES, ApexContext, ApexGate, ApexState, ApexTask, ApexTaskFile, AuthEntry, COLOR_THRESHOLDS, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DocSatisfactionStatus, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, HarnessId, HarnessInfo, HarnessMode, HarnessVia, IndexSummary, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, Palette, PolicyContext, PolicyResult, ProgressBarOptions, ProjectType, Prompt, PromptKind, RefMeta, ReminderState, RouteResult, SYSTEM_INSTALL, ScoredRef, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, ttlLabel };
package/dist/index.mjs CHANGED
@@ -3,13 +3,14 @@ import { i as ttlLabel, n as TTL_ENV_KEY, r as resolveTtlSec, t as DEFAULT_TTL_S
3
3
  import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
4
4
  import { n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
5
5
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-C8Nxxyn_.mjs";
6
- import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "./policy-C_pXmeNB.mjs";
6
+ import { a as DEV_KEYWORDS, i as solidReadGate, n as docConsultedGate, o as detectProjectType, r as evaluateApex, s as isApexCommand, t as APEX_GATES } from "./policy-DMpyaPZ_.mjs";
7
7
  import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "./evaluate-CsYyUucy.mjs";
8
+ import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
9
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-Dj3AfgBE.mjs";
8
10
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
9
11
  import { a as readState, c as throttleMs, i as nowStamp, l as ensureMemoryGitignore, n as readRoots, o as setStateField, r as registryFile, s as stateFileFor, t as addRoot } from "./memory-BVNt4Ary.mjs";
10
12
  import { a as jaccardSimilar, i as compactMarkdown, n as loadIndex, o as queryHash, r as summarizeIndex, t as extractText } from "./cache-DbPSJ9bC.mjs";
11
- import { a as resolveSessions, i as isDocConsulted, n as formatDocDeny, r as formatDocSatisfactionStatus, t as incrementTrivialEditCounter } from "./freshness-DzGoBKKj.mjs";
12
- import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./refs-Dj3AfgBE.mjs";
13
+ import { t as incrementTrivialEditCounter } from "./freshness-BK9Xg6oG.mjs";
13
14
  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-Bc4wdnCG.mjs";
14
15
  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";
15
- export { COLOR_THRESHOLDS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, SYSTEM_INSTALL, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, ttlLabel };
16
+ export { APEX_GATES, COLOR_THRESHOLDS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, SYSTEM_INSTALL, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, ttlLabel };
@@ -1,2 +1,2 @@
1
- import { a as GIT_BLOCKED, c as matchPatterns, d as evaluateFileSize, f as detectFramework, g as isApexCommand, h as detectProjectType, i as GIT_ASK, l as FileSizeVerdict, m as ProjectType, n as PolicyResult, o as PROJECT_INSTALL, p as DEV_KEYWORDS, r as evaluate, s as SYSTEM_INSTALL, t as PolicyContext, u as countLines } from "../index-D7MkQNdc.mjs";
2
- export { DEV_KEYWORDS, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, PolicyContext, PolicyResult, ProjectType, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, evaluate, evaluateFileSize, isApexCommand, matchPatterns };
1
+ import { S as isApexCommand, _ as evaluateFileSize, a as evaluateApex, b as ProjectType, c as PolicyResult, d as GIT_BLOCKED, f as PROJECT_INSTALL, g as countLines, h as FileSizeVerdict, i as docConsultedGate, l as evaluate, m as matchPatterns, n as ApexContext, o as solidReadGate, p as SYSTEM_INSTALL, r as ApexGate, s as PolicyContext, t as APEX_GATES, u as GIT_ASK, v as detectFramework, x as detectProjectType, y as DEV_KEYWORDS } from "../index-BXBWKbL8.mjs";
2
+ export { APEX_GATES, ApexContext, ApexGate, DEV_KEYWORDS, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, PolicyContext, PolicyResult, ProjectType, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, isApexCommand, matchPatterns, solidReadGate };
@@ -1,3 +1,3 @@
1
- import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "../policy-C_pXmeNB.mjs";
1
+ import { a as DEV_KEYWORDS, i as solidReadGate, n as docConsultedGate, o as detectProjectType, r as evaluateApex, s as isApexCommand, t as APEX_GATES } from "../policy-DMpyaPZ_.mjs";
2
2
  import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "../evaluate-CsYyUucy.mjs";
3
- export { DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, evaluate, evaluateFileSize, isApexCommand, matchPatterns };
3
+ export { APEX_GATES, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, isApexCommand, matchPatterns, solidReadGate };
@@ -1,3 +1,5 @@
1
+ import { r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
2
+ import { t as routeReferences } from "./router-Dj3AfgBE.mjs";
1
3
  import { existsSync } from "node:fs";
2
4
  import { join } from "node:path";
3
5
  //#region src/policy/detect-project.ts
@@ -30,4 +32,37 @@ function detectProjectType(dir) {
30
32
  return "generic";
31
33
  }
32
34
  //#endregion
33
- export { detectProjectType as n, isApexCommand as r, DEV_KEYWORDS as t };
35
+ //#region src/policy/apex.ts
36
+ /** Gate: Context7 + Exa must have been consulted this session. */
37
+ const docConsultedGate = (ctx) => isDocConsulted(ctx.authorizations, ctx.sessionId) ? null : {
38
+ kind: "block",
39
+ title: "APEX: documentation not consulted",
40
+ reason: formatDocDeny(ctx.framework),
41
+ actions: ["Call mcp__context7__query-docs", "Call mcp__exa__web_search_exa"]
42
+ };
43
+ /** Gate: the routed SOLID references for this edit must have been read. */
44
+ const solidReadGate = (ctx) => {
45
+ if (!ctx.refs?.length) return null;
46
+ const routed = routeReferences(ctx.refs, ctx.filePath, ctx.content);
47
+ if (!routed) return null;
48
+ const read = new Set(ctx.refsRead ?? []);
49
+ const missing = routed.required.map((r) => r.meta.filePath).filter((p) => !read.has(p));
50
+ if (missing.length === 0) return null;
51
+ return {
52
+ kind: "block",
53
+ title: `APEX: read SOLID references for ${ctx.framework}`,
54
+ reason: `Read these before editing ${ctx.filePath}:`,
55
+ actions: missing
56
+ };
57
+ };
58
+ /** Default APEX gate chain. */
59
+ const APEX_GATES = [docConsultedGate, solidReadGate];
60
+ /**
61
+ * Run the APEX gates (chain-of-responsibility): the first failing gate's prompt
62
+ * wins; null means every gate passed (allow).
63
+ */
64
+ function evaluateApex(ctx, gates = APEX_GATES) {
65
+ return gates.reduce((hit, gate) => hit ?? gate(ctx), null);
66
+ }
67
+ //#endregion
68
+ export { DEV_KEYWORDS as a, solidReadGate as i, docConsultedGate as n, detectProjectType as o, evaluateApex as r, isApexCommand as s, APEX_GATES as t };
@@ -1,2 +1,3 @@
1
- import { a as RefMeta, i as parseFrontmatter, n as scoreReferences, o as RouteResult, r as globToRe, s as ScoredRef, t as routeReferences } from "../index-DqNKW8Ki.mjs";
1
+ import { n as RouteResult, r as ScoredRef, t as RefMeta } from "../types-CY5qT2X1.mjs";
2
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "../index-C2Lz-cwJ.mjs";
2
3
  export { RefMeta, RouteResult, ScoredRef, globToRe, parseFrontmatter, routeReferences, scoreReferences };
@@ -1,2 +1,3 @@
1
- import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "../refs-Dj3AfgBE.mjs";
1
+ import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "../router-Dj3AfgBE.mjs";
2
+ import "../refs-la_KkjCS.mjs";
2
3
  export { globToRe, parseFrontmatter, routeReferences, scoreReferences };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ //#region src/refs/types.d.ts
2
+ /** Parsed frontmatter metadata from a reference .md file. */
3
+ interface RefMeta {
4
+ name: string;
5
+ description: string;
6
+ keywords: string;
7
+ priority: string;
8
+ related: string;
9
+ appliesTo: string;
10
+ triggerOnEdit: string;
11
+ level: string;
12
+ filePath: string;
13
+ }
14
+ /** A reference with its computed routing score. */
15
+ interface ScoredRef {
16
+ meta: RefMeta;
17
+ score: number;
18
+ }
19
+ /** Routing result with categorized references. */
20
+ interface RouteResult {
21
+ required: ScoredRef[];
22
+ optional: ScoredRef[];
23
+ skillPath: string;
24
+ }
25
+ //#endregion
26
+ export { RouteResult as n, ScoredRef as r, RefMeta as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",
File without changes