@fusengine/harness 0.1.91 → 0.1.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +17 -0
  2. package/dist/adapters/claude/index.mjs +1 -1
  3. package/dist/adapters/codex/index.mjs +1 -1
  4. package/dist/adapters/cursor/index.mjs +1 -1
  5. package/dist/adapters/hermes/index.mjs +1 -1
  6. package/dist/adapters/kimi/index.mjs +1 -1
  7. package/dist/apex-target-Xc2M32Pl.mjs +48 -0
  8. package/dist/apex-task-store-Cb65rE5i.mjs +467 -0
  9. package/dist/{claude-Ckv2_TgP.mjs → claude-D62hkUfS.mjs} +2 -84
  10. package/dist/cli/bin.mjs +7 -5
  11. package/dist/cli/index.d.mts +69 -1
  12. package/dist/cli/index.mjs +2 -2
  13. package/dist/config/index.mjs +2 -1
  14. package/dist/{dotenv-BLBkBTww.mjs → dotenv-C1LkcfW-.mjs} +1 -26
  15. package/dist/{handle-C43gA-Pr.mjs → handle-B-g9KL_9.mjs} +4837 -3466
  16. package/dist/{hermes-B9-p_3IF.mjs → hermes-ByopGx6C.mjs} +1 -1
  17. package/dist/index.d.mts +1 -1
  18. package/dist/index.mjs +3 -2
  19. package/dist/{kimi-G2wcSh5-.mjs → kimi-C-Oia9q-.mjs} +1 -1
  20. package/dist/{normalize-BjG6unTj.mjs → normalize-Dy8g9Ybl.mjs} +83 -3
  21. package/dist/policy/index.mjs +1 -1
  22. package/dist/prd-PvK7PKWS.mjs +494 -0
  23. package/dist/runtime/index.d.mts +13 -1
  24. package/dist/runtime/index.mjs +1 -1
  25. package/dist/runtime-io-DuumUeE6.mjs +84 -0
  26. package/dist/{session-state-D5gLr66m.d.mts → session-state-COg7Ej_2.d.mts} +32 -1
  27. package/dist/{skill-path-DVML3zfp.mjs → skill-path-Cz8WFaGu.mjs} +1 -1
  28. package/dist/{store-5-ZPKb0u.mjs → store-BVY6gIYM.mjs} +75 -3
  29. package/dist/tracking/index.d.mts +2 -2
  30. package/dist/tracking/index.mjs +2 -2
  31. package/dist/ttl-Dgwg_QAv.mjs +26 -0
  32. package/dist/{validate-KjZ1X9tH.mjs → validate-Dcjl0LUS.mjs} +4 -49
  33. package/package.json +1 -1
  34. package/src/adapters/cursor/context-budget.ts +144 -0
  35. package/src/adapters/cursor/context-limit.ts +115 -0
  36. package/src/adapters/cursor/context.ts +21 -2
  37. package/src/adapters/cursor/interfaces/context-budget.ts +25 -0
  38. package/src/adapters/cursor/native-response.ts +10 -129
  39. package/src/adapters/cursor/native-schemas.ts +161 -0
  40. package/src/adapters/cursor/normalize.ts +65 -0
  41. package/src/adapters/cursor/plugin-root.ts +103 -0
  42. package/src/adapters/cursor/respond.ts +94 -47
  43. package/src/cli/bin.ts +3 -0
  44. package/src/cli/index.ts +1 -0
  45. package/src/cli/prd/compact.ts +53 -0
  46. package/src/cli/prd/format.ts +23 -0
  47. package/src/cli/prd/index.ts +23 -0
  48. package/src/cli/prd/resolve.ts +88 -0
  49. package/src/cli/prd/shared.ts +80 -0
  50. package/src/cli/prd/status.ts +87 -0
  51. package/src/cli/prd/validate.ts +90 -0
  52. package/src/policy/prd/index.ts +36 -0
  53. package/src/policy/prd/interfaces/types.ts +103 -0
  54. package/src/policy/prd/prd-compact.ts +28 -0
  55. package/src/policy/prd/prd-context.ts +131 -0
  56. package/src/policy/prd/prd-crosscheck.ts +76 -0
  57. package/src/policy/prd/prd-enabled.ts +39 -0
  58. package/src/policy/prd/prd-io.ts +89 -0
  59. package/src/policy/prd/prd-ownership.ts +99 -0
  60. package/src/policy/prd/prd-paths.ts +88 -0
  61. package/src/policy/prd/prd-schema.ts +151 -0
  62. package/src/runtime/handle-post.ts +2 -0
  63. package/src/runtime/handle-pre.ts +11 -0
  64. package/src/runtime/handle.ts +87 -6
  65. package/src/runtime/lifecycle/aipilot/dispatch-aipilot.ts +7 -1
  66. package/src/runtime/lifecycle/dispatch.ts +18 -5
  67. package/src/runtime/lifecycle/failure-lesson.ts +6 -2
  68. package/src/runtime/lifecycle/rules-root.ts +18 -2
  69. package/src/runtime/normalize.ts +4 -0
  70. package/src/runtime/prd/index.ts +8 -0
  71. package/src/runtime/prd/prd-bash-targets.ts +199 -0
  72. package/src/runtime/prd/prd-candidate-files.ts +23 -0
  73. package/src/runtime/prd/prd-canon.ts +50 -0
  74. package/src/runtime/prd/prd-identity.ts +32 -0
  75. package/src/runtime/prd/prd-post-check.ts +73 -0
  76. package/src/runtime/prd/prd-pre-gate.ts +172 -0
  77. package/src/runtime/prd/prd-stop-gate.ts +101 -0
  78. package/src/runtime/prd/prd-subagent-context.ts +69 -0
  79. package/src/runtime/prd/prd-subagent-stop.ts +152 -0
  80. package/src/tracking/session-state.ts +46 -0
  81. package/src/tracking/track-diff.ts +3 -0
  82. package/src/tracking/track-journal.ts +10 -1
  83. package/dist/run-DkrzC0gb.mjs +0 -42
@@ -1,89 +1,7 @@
1
1
  import { t as evaluate } from "./evaluate-CMiIqHeH.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
+ import { r as readStdin } from "./runtime-io-DuumUeE6.mjs";
3
4
  import { t as commandToString } from "./command-string-CALMTnwN.mjs";
4
- import { dirname, join } from "node:path";
5
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
6
- import { spawnSync } from "node:child_process";
7
- //#region src/util/runtime-io.ts
8
- /**
9
- * Cross-runtime I/O helpers (Node + Bun). The published CLI ships a `node`
10
- * shebang and is invoked via `npx`/`npm`/`bunx`/`bun`; using only `node:*` APIs
11
- * here keeps the bundle runnable under EVERY runtime — replacing the Bun-only
12
- * `Bun.file/write/spawn/sleep/stdin` calls and the `bun` `Glob` import that made
13
- * the package crash with `Cannot find package 'bun'` under plain Node.
14
- */
15
- /** Read a file as UTF-8 text (throws on missing/unreadable — callers catch). */
16
- function readText(path) {
17
- return readFileSync(path, "utf8");
18
- }
19
- /** True when `path` exists. */
20
- function pathExists(path) {
21
- return existsSync(path);
22
- }
23
- /** Write `data` to `path`, creating parent dirs (mirrors `Bun.write`). */
24
- function writeText(path, data) {
25
- mkdirSync(dirname(path), { recursive: true });
26
- writeFileSync(path, data, { encoding: "utf8" });
27
- }
28
- /** Resolve after `ms` milliseconds (`Bun.sleep` replacement). */
29
- function sleep(ms) {
30
- return new Promise((resolve) => setTimeout(resolve, ms));
31
- }
32
- /** Run `cmd args` in `cwd` and capture stdout text ("" on failure/non-zero). */
33
- function spawnCapture(cmd, args, cwd) {
34
- try {
35
- const r = spawnSync(cmd, args, {
36
- cwd,
37
- encoding: "utf8"
38
- });
39
- return r.status === 0 ? r.stdout ?? "" : "";
40
- } catch {
41
- return "";
42
- }
43
- }
44
- /**
45
- * Read the full process stdin as UTF-8 text (works under Node and Bun).
46
- * Synchronous fd-0 read — never `for await (const c of process.stdin)` —
47
- * because Bun has a confirmed Linux-only bug where merely adding a new
48
- * top-level module import shifts stdin's internal init order and makes
49
- * that async iterator silently yield zero bytes (oven-sh/bun#25320,
50
- * #27849): exactly what broke every `harness hook` invocation on CI the
51
- * moment `figures` became this package's first runtime dependency.
52
- * `readFileSync(0)` bypasses that stream/ownership machinery entirely and
53
- * is well-supported for piped (non-TTY) stdin under both runtimes.
54
- */
55
- async function readStdin() {
56
- try {
57
- return readFileSync(0, "utf8");
58
- } catch {
59
- return "";
60
- }
61
- }
62
- /**
63
- * Recursively collect files under `dir` whose extension is in `exts`, skipping
64
- * `node_modules` and dot-dirs, capped at `cap`. `Bun.Glob().scan()` replacement.
65
- * @param dir - Directory to walk.
66
- * @param exts - Allowed extensions including the dot (e.g. `.ts`).
67
- * @param out - Accumulator (mutated in place).
68
- * @param cap - Max files to collect.
69
- */
70
- function collectFiles(dir, exts, out, cap) {
71
- if (out.length >= cap) return;
72
- let entries;
73
- try {
74
- entries = readdirSync(dir, { withFileTypes: true });
75
- } catch {
76
- return;
77
- }
78
- for (const e of entries) {
79
- if (out.length >= cap) return;
80
- if (e.name === "node_modules" || e.name.startsWith(".")) continue;
81
- const full = join(dir, e.name);
82
- if (e.isDirectory()) collectFiles(full, exts, out, cap);
83
- else if (exts.has(e.name.slice(e.name.lastIndexOf(".")))) out.push(full);
84
- }
85
- }
86
- //#endregion
87
5
  //#region src/adapters/claude/index.ts
88
6
  /** Claude Code adapter — the thin Claude-only shim over the portable policy core; reads the hook stdin payload and emits hookSpecificOutput responses. */
89
7
  /** Read & parse the Claude hook payload from stdin (empty object on bad input). */
@@ -176,4 +94,4 @@ function guard(input) {
176
94
  /** @deprecated use {@link guard}. Kept for back-compat. */
177
95
  const fileSizeGuard = guard;
178
96
  //#endregion
179
- export { fileSizeGuard as a, readClaudeInput as c, collectFiles as d, pathExists as f, writeText as g, spawnCapture as h, denyResponse as i, systemMessage as l, sleep as m, blockResponse as n, guard as o, readText as p, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u };
97
+ export { fileSizeGuard as a, readClaudeInput as c, denyResponse as i, systemMessage as l, blockResponse as n, guard as o, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u };
package/dist/cli/bin.mjs CHANGED
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { o as resolveStdinMaxBytes } from "../limits-DG5pl-5s.mjs";
3
- import { c as resolveTtlSec, r as loadDotenv } from "../dotenv-BLBkBTww.mjs";
3
+ import { r as resolveTtlSec } from "../ttl-Dgwg_QAv.mjs";
4
+ import { r as loadDotenv } from "../dotenv-C1LkcfW-.mjs";
4
5
  import { t as detectHarness } from "../harness-BMuLJ9lm.mjs";
5
6
  import { t as claudeHome } from "../home-state-oUGFB4ds.mjs";
6
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-DkrzC0gb.mjs";
7
+ import { f as checkStaged, m as stagedFiles, p as stagedContent, t as runPrd } from "../prd-PvK7PKWS.mjs";
7
8
  import { n as writeInitFile, t as initFor } from "../run-GHAMqcOn.mjs";
8
- import { $ as runDoctor, Bt as todayUtc, Q as notify, et as runningVersion, i as respond, t as handleHook, tt as versionBanner } from "../handle-C43gA-Pr.mjs";
9
- import { r as cursorEventContract } from "../normalize-BjG6unTj.mjs";
9
+ import { $ as runDoctor, Bt as todayUtc, I as respond, Q as notify, et as runningVersion, t as handleHook, tt as versionBanner } from "../handle-B-g9KL_9.mjs";
10
+ import { r as cursorEventContract } from "../normalize-Dy8g9Ybl.mjs";
10
11
  import { delimiter, join } from "node:path";
11
12
  import { existsSync, mkdirSync, readFileSync, readSync, readdirSync, writeFileSync } from "node:fs";
12
13
  import { homedir } from "node:os";
@@ -1626,7 +1627,8 @@ else if (cmd === "scan") {
1626
1627
  const dir = process.argv[3] ?? process.cwd();
1627
1628
  process.stdout.write(JSON.stringify(runSecurityScan(dir), null, 2) + "\n");
1628
1629
  process.exit(0);
1629
- } else if (cmd === "codex-rules") {
1630
+ } else if (cmd === "prd") process.exit(await runPrd(process.argv.slice(3), process.cwd(), process.env));
1631
+ else if (cmd === "codex-rules") {
1630
1632
  const outIdx = process.argv.indexOf("--out");
1631
1633
  const outPath = outIdx !== -1 ? process.argv[outIdx + 1] : void 0;
1632
1634
  const rules = buildCodexRules();
@@ -1,3 +1,4 @@
1
+ import { t as HarnessId } from "../types-DvXTI71X.mjs";
1
2
  //#region src/cli/run.d.ts
2
3
  /** Staged files (Added/Copied/Modified/Renamed). Uses `node:child_process` (Bun shell can hang on `git show`). */
3
4
  declare function stagedFiles(): string[];
@@ -14,4 +15,71 @@ declare function stagedContent(path: string): string;
14
15
  */
15
16
  declare function checkStaged(files: string[], read: (path: string) => string): string[];
16
17
  //#endregion
17
- export { checkStaged, stagedContent, stagedFiles };
18
+ //#region src/cli/prd/resolve.d.ts
19
+ /** Resolved `--root`/`--id` pair for a `prd` sub-command. */
20
+ interface PrdResolved {
21
+ root: string;
22
+ homeSeg: string;
23
+ id: HarnessId;
24
+ }
25
+ /** Result of {@link resolvePrdArgs}: resolved args, or a usage error (exit 2). */
26
+ type PrdResolveResult = {
27
+ ok: true;
28
+ value: PrdResolved;
29
+ } | {
30
+ ok: false;
31
+ message: string;
32
+ };
33
+ /** Read `--<name> <value>` from argv, or `undefined` when absent. */
34
+ declare function readFlag(argv: string[], name: string): string | undefined;
35
+ /** True when `--json` is present in argv. */
36
+ declare function hasJsonFlag(argv: string[]): boolean;
37
+ /** Non-flag tokens in argv, skipping known flags and their values. */
38
+ declare function positionalArgs(argv: string[]): string[];
39
+ /**
40
+ * Resolve `{root, homeSeg, id}` for a `prd` sub-command. `--id` wins
41
+ * outright; otherwise auto-detects the sole `HOME_DIR` segment under which
42
+ * `<root>/<seg>/apex/prd.json` exists.
43
+ */
44
+ declare function resolvePrdArgs(argv: string[], cwd: string): PrdResolveResult;
45
+ /**
46
+ * Shared first step of every `prd` sub-command: {@link resolvePrdArgs}, then
47
+ * (on success) `loadDotenv` the resolved harness's home `.env` + `<root>/.env`
48
+ * as a side effect on `env` — same env-loading contract as the `hook` branch
49
+ * (`bin.ts`'s `loadDotenv(id)` call).
50
+ */
51
+ declare function resolveAndLoadEnv(argv: string[], cwd: string, env?: NodeJS.ProcessEnv): PrdResolveResult;
52
+ //#endregion
53
+ //#region src/cli/prd/format.d.ts
54
+ /** Render an aligned ASCII table from a header row + data rows. */
55
+ declare function renderTable(header: string[], rows: string[][]): string;
56
+ /** Render `data` as pretty-printed JSON with a trailing newline. */
57
+ declare function renderJson(data: unknown): string;
58
+ //#endregion
59
+ //#region src/cli/prd/status.d.ts
60
+ /**
61
+ * Run `harness prd status`. Prints an aligned table (or `--json` dump of
62
+ * `{router, taskFiles, reports}`) and returns the process exit code.
63
+ */
64
+ declare function runPrdStatus(argv: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<number>;
65
+ //#endregion
66
+ //#region src/cli/prd/validate.d.ts
67
+ /**
68
+ * Run `harness prd validate`. Exit 0 on success, exit 1 on cross-check
69
+ * violations or a missing `FUSE_PRD=1`/held lock, exit 2 on usage/lookup errors.
70
+ */
71
+ declare function runPrdValidate(argv: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<number>;
72
+ //#endregion
73
+ //#region src/cli/prd/compact.d.ts
74
+ /**
75
+ * Run `harness prd compact`. Exit 0 on success (including a no-op compact),
76
+ * exit 1 when `FUSE_PRD` is unset, a sub-task is unvalidated, or the lock is
77
+ * held, exit 2 on usage/lookup errors.
78
+ */
79
+ declare function runPrdCompact(argv: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<number>;
80
+ //#endregion
81
+ //#region src/cli/prd/index.d.ts
82
+ /** Dispatch `harness prd <sub> ...rest` to the matching `run*` function. */
83
+ declare function runPrd(argv: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<number>;
84
+ //#endregion
85
+ export { PrdResolveResult, PrdResolved, checkStaged, hasJsonFlag, positionalArgs, readFlag, renderJson, renderTable, resolveAndLoadEnv, resolvePrdArgs, runPrd, runPrdCompact, runPrdStatus, runPrdValidate, stagedContent, stagedFiles };
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-DkrzC0gb.mjs";
2
- export { checkStaged, stagedContent, stagedFiles };
1
+ import { a as renderJson, c as positionalArgs, d as resolvePrdArgs, f as checkStaged, i as runPrdStatus, l as readFlag, m as stagedFiles, n as runPrdCompact, o as renderTable, p as stagedContent, r as runPrdValidate, s as hasJsonFlag, t as runPrd, u as resolveAndLoadEnv } from "../prd-PvK7PKWS.mjs";
2
+ export { checkStaged, hasJsonFlag, positionalArgs, readFlag, renderJson, renderTable, resolveAndLoadEnv, resolvePrdArgs, runPrd, runPrdCompact, runPrdStatus, runPrdValidate, stagedContent, stagedFiles };
@@ -1,5 +1,6 @@
1
1
  import { a as resolveMaxLines, c as storeBudget, i as hookBudget, l as parseEnvInt, n as DEFAULT_STDIN_MAX_BYTES, o as resolveStdinMaxBytes, r as MAX_LINES_ENV_KEY, s as splitTarget, t as DEFAULT_MAX_LINES } from "../limits-DG5pl-5s.mjs";
2
- import { c as resolveTtlSec, i as parseEnvFile, l as ttlLabel, n as envCandidates, o as DEFAULT_TTL_SEC, r as loadDotenv, s as TTL_ENV_KEY, t as HOME_DIR } from "../dotenv-BLBkBTww.mjs";
2
+ import { i as ttlLabel, n as TTL_ENV_KEY, r as resolveTtlSec, t as DEFAULT_TTL_SEC } from "../ttl-Dgwg_QAv.mjs";
3
3
  import { n as STATE_ROOT, r as projectLayout, t as STATE_GITIGNORE } from "../layout-KWoE_Mqn.mjs";
4
+ import { i as parseEnvFile, n as envCandidates, r as loadDotenv, t as HOME_DIR } from "../dotenv-C1LkcfW-.mjs";
4
5
  import "../config-la_KkjCS.mjs";
5
6
  export { DEFAULT_MAX_LINES, DEFAULT_STDIN_MAX_BYTES, DEFAULT_TTL_SEC, HOME_DIR, MAX_LINES_ENV_KEY, STATE_GITIGNORE, STATE_ROOT, TTL_ENV_KEY, envCandidates, hookBudget, loadDotenv, parseEnvFile, parseEnvInt, projectLayout, resolveMaxLines, resolveStdinMaxBytes, resolveTtlSec, splitTarget, storeBudget, ttlLabel };
@@ -1,31 +1,6 @@
1
- import { l as parseEnvInt } from "./limits-DG5pl-5s.mjs";
2
1
  import { join } from "node:path";
3
2
  import { existsSync, readFileSync } from "node:fs";
4
3
  import { homedir } from "node:os";
5
- //#region src/config/ttl.ts
6
- /**
7
- * Default enforcement-freshness window, in seconds (2 minutes). Matches the
8
- * plugin's original `FUSE_ENFORCE_TTL_SEC` default. This is the constant that
9
- * actually reaches production (via `resolveTtlSec` -> `bin.ts`); `gate.ts`'s
10
- * `DEFAULT_WINDOW_MS` is only a fallback for direct programmatic callers that
11
- * omit `windowMs` (e.g. tests) and never applies on the real CLI path.
12
- */
13
- const DEFAULT_TTL_SEC = 120;
14
- /** Default env var name carrying the TTL override. */
15
- const TTL_ENV_KEY = "FUSE_ENFORCE_TTL_SEC";
16
- /**
17
- * Resolve the enforcement TTL (seconds) from an env map.
18
- * @param env - environment map (defaults to `process.env`)
19
- * @param key - env var name (defaults to `FUSE_ENFORCE_TTL_SEC`)
20
- */
21
- function resolveTtlSec(env = process.env, key = TTL_ENV_KEY) {
22
- return parseEnvInt(env[key], 120);
23
- }
24
- /** Human label for a TTL: 120 -> "2min", 240 -> "4min", 90 -> "90s". */
25
- function ttlLabel(sec) {
26
- return sec % 60 === 0 ? `${sec / 60}min` : `${sec}s`;
27
- }
28
- //#endregion
29
4
  //#region src/config/home-dir.ts
30
5
  /**
31
6
  * Harness home-dir resolution with env overrides. `dotenv.ts`'s static
@@ -106,4 +81,4 @@ function loadDotenv(id, env = process.env, home = homedir(), cwd = process.cwd()
106
81
  for (const path of envCandidates(id, home, cwd)) for (const [k, v] of Object.entries(parseEnvFile(path))) if (env[k] === void 0) env[k] = v;
107
82
  }
108
83
  //#endregion
109
- export { harnessHome as a, resolveTtlSec as c, parseEnvFile as i, ttlLabel as l, envCandidates as n, DEFAULT_TTL_SEC as o, loadDotenv as r, TTL_ENV_KEY as s, HOME_DIR as t };
84
+ export { harnessHome as a, parseEnvFile as i, envCandidates as n, loadDotenv as r, HOME_DIR as t };