@inerrata-corporation/errata 2.0.6-dev.2752 → 2.0.6-dev.2766
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/README.txt +6 -3
- package/errata.mjs +286 -114
- package/package.json +1 -1
- package/pass-worker.mjs +5 -0
package/README.txt
CHANGED
|
@@ -34,9 +34,12 @@ errata link flows also refresh detected Codex hooks; --skip-hooks opts out of
|
|
|
34
34
|
either automatic install. The installer preserves other config and writes its
|
|
35
35
|
Node relay into .codex/hooks/errata-relay.mjs. No curl or Bash dependency.
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
Codex desktop: open Settings > Hooks, select the project, expand each event,
|
|
38
|
+
and review/Trust its Errata hook. Use Reload hooks after installation. No
|
|
39
|
+
standalone Codex CLI is required. CLI users can use /hooks instead.
|
|
40
|
+
Restarting or reinstalling does not grant trust. Run errata doctor to check
|
|
41
|
+
activation; it discovers the Windows desktop runtime even without a CLI on PATH.
|
|
42
|
+
Respect explicitly disabled hooks ([features] hooks = false).
|
|
40
43
|
|
|
41
44
|
SessionStart injects .errata/context.md, including startup/resume/compaction.
|
|
42
45
|
UserPromptSubmit and PostToolUse inject it again only when it changes. Tool
|
package/errata.mjs
CHANGED
|
@@ -17038,6 +17038,11 @@ var init_context_file = __esm({
|
|
|
17038
17038
|
"Live agent context for this checkout \u2014 priors, open problems, the capture",
|
|
17039
17039
|
"protocol \u2014 is maintained by the errata daemon at `.errata/context.md`.",
|
|
17040
17040
|
"",
|
|
17041
|
+
"At the beginning of each task and each new user turn, read that file before",
|
|
17042
|
+
"substantive work. Use the current file in preference to an earlier snapshot.",
|
|
17043
|
+
"If it is absent, continue normally. In Codex, an `@` mention alone does not",
|
|
17044
|
+
"load the file; read it explicitly.",
|
|
17045
|
+
"",
|
|
17041
17046
|
"It is gitignored ON PURPOSE: it is this machine's runtime state, not repo",
|
|
17042
17047
|
"content. Committing it would prime your teammates with your graph.",
|
|
17043
17048
|
"",
|
|
@@ -71187,9 +71192,9 @@ var init_report_render = __esm({
|
|
|
71187
71192
|
|
|
71188
71193
|
// src/cli.ts
|
|
71189
71194
|
init_src6();
|
|
71190
|
-
import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync35, renameSync as renameSync4, statSync as
|
|
71191
|
-
import { join as
|
|
71192
|
-
import { spawn as
|
|
71195
|
+
import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync35, renameSync as renameSync4, statSync as statSync9 } from "node:fs";
|
|
71196
|
+
import { join as join41, resolve as pathResolve2 } from "node:path";
|
|
71197
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
71193
71198
|
|
|
71194
71199
|
// src/daemon.ts
|
|
71195
71200
|
import { existsSync as existsSync26, writeFileSync as writeFileSync22 } from "node:fs";
|
|
@@ -73721,6 +73726,7 @@ init_src10();
|
|
|
73721
73726
|
init_review2();
|
|
73722
73727
|
|
|
73723
73728
|
// src/turn.ts
|
|
73729
|
+
init_checkout_root();
|
|
73724
73730
|
import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync5 } from "node:fs";
|
|
73725
73731
|
import { basename as basename5, delimiter, dirname as dirname10, join as join19, normalize as normalize3 } from "node:path";
|
|
73726
73732
|
import { homedir as homedir4 } from "node:os";
|
|
@@ -74205,6 +74211,8 @@ function codexRolloutsForCwd(cwd, opts = {}) {
|
|
|
74205
74211
|
const sinceMs = opts.sinceMs ?? 0;
|
|
74206
74212
|
const limit = opts.limit ?? 25;
|
|
74207
74213
|
const out2 = [];
|
|
74214
|
+
const owner = checkoutRootOf(cwd);
|
|
74215
|
+
const owners = /* @__PURE__ */ new Map();
|
|
74208
74216
|
for (const root of codexSessionRoots(opts.env, opts.home)) {
|
|
74209
74217
|
if (!existsSync16(root)) continue;
|
|
74210
74218
|
const stack = [{ dir: root, depth: 0 }];
|
|
@@ -74231,7 +74239,14 @@ function codexRolloutsForCwd(cwd, opts = {}) {
|
|
|
74231
74239
|
if (depth < 3) continue;
|
|
74232
74240
|
if (!name2.startsWith("rollout-") || !name2.endsWith(".jsonl")) continue;
|
|
74233
74241
|
if (st.mtimeMs < sinceMs) continue;
|
|
74234
|
-
|
|
74242
|
+
const sessionCwd = readCodexRolloutCwd(full);
|
|
74243
|
+
if (sessionCwd === null) continue;
|
|
74244
|
+
let sessionOwner = owners.get(sessionCwd);
|
|
74245
|
+
if (sessionOwner === void 0) {
|
|
74246
|
+
sessionOwner = checkoutRootOf(sessionCwd);
|
|
74247
|
+
owners.set(sessionCwd, sessionOwner);
|
|
74248
|
+
}
|
|
74249
|
+
if (sessionOwner !== owner) continue;
|
|
74235
74250
|
out2.push({ path: full, sessionId: `codex:${basename5(name2, ".jsonl")}`, mtimeMs: st.mtimeMs });
|
|
74236
74251
|
}
|
|
74237
74252
|
}
|
|
@@ -79907,7 +79922,7 @@ function createWatchBreaker(deps) {
|
|
|
79907
79922
|
}
|
|
79908
79923
|
|
|
79909
79924
|
// src/engine.ts
|
|
79910
|
-
var DAEMON_VERSION = true ? "2.0.6-dev.
|
|
79925
|
+
var DAEMON_VERSION = true ? "2.0.6-dev.2766" : "2.0.0-alpha.0";
|
|
79911
79926
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
79912
79927
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
79913
79928
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -85577,6 +85592,7 @@ var SessionAffinity = class {
|
|
|
85577
85592
|
};
|
|
85578
85593
|
|
|
85579
85594
|
// src/multi.ts
|
|
85595
|
+
init_checkout_root();
|
|
85580
85596
|
var PROCESS_STARTED_AT = Date.now();
|
|
85581
85597
|
var SELF_ENTRY = process.argv[1] ? pathResolve(process.argv[1]) : "";
|
|
85582
85598
|
var LOCAL_BUILD_ENTRY = SELF_ENTRY && !isInstalledEntry(SELF_ENTRY) ? SELF_ENTRY : void 0;
|
|
@@ -86124,6 +86140,19 @@ async function startMultiDaemon(opts = {}) {
|
|
|
86124
86140
|
if (owner) break;
|
|
86125
86141
|
owner = ownerOf(records, p);
|
|
86126
86142
|
}
|
|
86143
|
+
if (!owner) {
|
|
86144
|
+
for (const p of [primary, ...others]) {
|
|
86145
|
+
if (!p) continue;
|
|
86146
|
+
const gitRoot = nearestGitRoot(p);
|
|
86147
|
+
const main2 = gitRoot ? mainCheckoutOfWorktree(gitRoot) : null;
|
|
86148
|
+
if (!main2) continue;
|
|
86149
|
+
owner = ownerOf(records, main2);
|
|
86150
|
+
if (!owner && listWorkspaceEntries().some((e) => pickOwnerRoot([e.path], main2))) {
|
|
86151
|
+
if (attachWorkspace(main2).attached) owner = ownerOf(records, main2);
|
|
86152
|
+
}
|
|
86153
|
+
if (owner) break;
|
|
86154
|
+
}
|
|
86155
|
+
}
|
|
86127
86156
|
if (!owner && others.length > 0) {
|
|
86128
86157
|
const registryRoots = listWorkspaceEntries().map((e) => e.path);
|
|
86129
86158
|
const registered = others.map((p) => pickOwnerRoot(registryRoots, p)).find((r) => r != null);
|
|
@@ -87552,9 +87581,9 @@ function deriveAuthBase(verificationUri) {
|
|
|
87552
87581
|
}
|
|
87553
87582
|
function openInBrowser(url2) {
|
|
87554
87583
|
try {
|
|
87555
|
-
void import("node:child_process").then(({ spawn:
|
|
87584
|
+
void import("node:child_process").then(({ spawn: spawn6 }) => {
|
|
87556
87585
|
const [cmd2, args2] = process.platform === "win32" ? ["cmd", ["/c", "start", "", url2]] : process.platform === "darwin" ? ["open", [url2]] : ["xdg-open", [url2]];
|
|
87557
|
-
|
|
87586
|
+
spawn6(cmd2, args2, { detached: true, stdio: "ignore" }).unref();
|
|
87558
87587
|
});
|
|
87559
87588
|
} catch {
|
|
87560
87589
|
}
|
|
@@ -87622,9 +87651,41 @@ function shouldUseOAuthLogin(flags2, env2 = process.env) {
|
|
|
87622
87651
|
|
|
87623
87652
|
// src/doctor.ts
|
|
87624
87653
|
import { spawnSync } from "node:child_process";
|
|
87654
|
+
|
|
87655
|
+
// src/codex-runtime.ts
|
|
87656
|
+
import { readdirSync as readdirSync12, statSync as statSync8 } from "node:fs";
|
|
87657
|
+
import { join as join39 } from "node:path";
|
|
87658
|
+
function resolveCodexExecutable(options = {}) {
|
|
87659
|
+
const platform = options.platform ?? process.platform;
|
|
87660
|
+
const env2 = options.env ?? process.env;
|
|
87661
|
+
if (platform !== "win32") return "codex";
|
|
87662
|
+
const fileTime = (path2) => {
|
|
87663
|
+
try {
|
|
87664
|
+
const s = statSync8(path2);
|
|
87665
|
+
return s.isFile() ? s.mtimeMs : null;
|
|
87666
|
+
} catch {
|
|
87667
|
+
return null;
|
|
87668
|
+
}
|
|
87669
|
+
};
|
|
87670
|
+
for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
|
|
87671
|
+
if (!dir.trim()) continue;
|
|
87672
|
+
const path2 = join39(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
|
|
87673
|
+
if (fileTime(path2) !== null) return path2;
|
|
87674
|
+
}
|
|
87675
|
+
if (!env2["LOCALAPPDATA"]) return "codex";
|
|
87676
|
+
const root = join39(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
|
|
87677
|
+
try {
|
|
87678
|
+
const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join39(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
|
|
87679
|
+
return candidates[0]?.path ?? "codex";
|
|
87680
|
+
} catch {
|
|
87681
|
+
return "codex";
|
|
87682
|
+
}
|
|
87683
|
+
}
|
|
87684
|
+
|
|
87685
|
+
// src/doctor.ts
|
|
87625
87686
|
function installedHarnessVersion(bin) {
|
|
87626
87687
|
try {
|
|
87627
|
-
const r = spawnSync(bin, ["--version"], { encoding: "utf8", timeout: 3e3 });
|
|
87688
|
+
const r = spawnSync(bin === "codex" ? resolveCodexExecutable() : bin, ["--version"], { encoding: "utf8", timeout: 3e3, windowsHide: true });
|
|
87628
87689
|
if (r.status !== 0 && !r.stdout) return null;
|
|
87629
87690
|
const m = /(\d+\.\d+\.\d+)/.exec(`${r.stdout ?? ""}${r.stderr ?? ""}`);
|
|
87630
87691
|
return m ? m[1] : null;
|
|
@@ -87634,6 +87695,7 @@ function installedHarnessVersion(bin) {
|
|
|
87634
87695
|
}
|
|
87635
87696
|
async function diagnoseInstallation(cfg, dependencies) {
|
|
87636
87697
|
const checks = [];
|
|
87698
|
+
if (dependencies.codexHooks) checks.push(...await dependencies.codexHooks());
|
|
87637
87699
|
const profileName = cfg.activeInstallationProfile;
|
|
87638
87700
|
const profile = profileName ? cfg.installationProfiles[profileName] : void 0;
|
|
87639
87701
|
checks.push(
|
|
@@ -87727,75 +87789,14 @@ async function diagnoseInstallation(cfg, dependencies) {
|
|
|
87727
87789
|
};
|
|
87728
87790
|
}
|
|
87729
87791
|
|
|
87730
|
-
// src/
|
|
87731
|
-
|
|
87732
|
-
|
|
87733
|
-
}
|
|
87734
|
-
function targetLabel(context) {
|
|
87735
|
-
const target = context.default_write_target;
|
|
87736
|
-
if (!target) return "read-only";
|
|
87737
|
-
if (target.visibility === "public") return "public graph";
|
|
87738
|
-
if (target.visibility === "org") return `organization graph (${target.org_id})`;
|
|
87739
|
-
return `private Team graph (${target.team_id})`;
|
|
87740
|
-
}
|
|
87741
|
-
function formatWhoami(response, localProfile) {
|
|
87742
|
-
const { context, identity } = response;
|
|
87743
|
-
return [
|
|
87744
|
-
`inErrata context \u2014 ${context.profile_name ?? localProfile ?? "unbound credential"}`,
|
|
87745
|
-
` workspace: ${context.workspace_kind} \xB7 ${context.org_id}`,
|
|
87746
|
-
` team: ${context.team_id ?? "(none)"}`,
|
|
87747
|
-
` agent: ${context.agent_id ?? "(default identity)"}`,
|
|
87748
|
-
` installation: ${context.installation_id ?? "(unbound)"}`,
|
|
87749
|
-
` environment: ${context.environment} \xB7 ${context.client_kind}`,
|
|
87750
|
-
` reads: ${context.read_visibilities.join(" + ")}`,
|
|
87751
|
-
` contributes: ${targetLabel(context)}`,
|
|
87752
|
-
` policy: ${context.policy_version ?? "(legacy)"}`,
|
|
87753
|
-
` credential: ${identity.credential_type} \xB7 ${identity.credential_id}`,
|
|
87754
|
-
` actor: ${identity.actor_type} \xB7 ${identity.actor_id}`
|
|
87755
|
-
];
|
|
87756
|
-
}
|
|
87792
|
+
// src/codex-doctor.ts
|
|
87793
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
87794
|
+
import { createInterface } from "node:readline";
|
|
87757
87795
|
|
|
87758
|
-
// src/
|
|
87759
|
-
|
|
87760
|
-
|
|
87761
|
-
}
|
|
87762
|
-
function nextMomentumThreshold(args2) {
|
|
87763
|
-
const { current, consumed, landmarkFlips, floor, cap } = args2;
|
|
87764
|
-
const next = landmarkFlips > 0 ? Math.min(current, Math.round(consumed / 2)) : Math.max(current, Math.round(consumed * 1.5));
|
|
87765
|
-
return Math.max(floor, Math.min(cap, next));
|
|
87766
|
-
}
|
|
87767
|
-
var DEFAULT_CONSOLIDATION_POLICY = {
|
|
87768
|
-
baseFloorMs: 6e4,
|
|
87769
|
-
dutyFactor: 20,
|
|
87770
|
-
// ≤5% worst-case duty at any graph size (crater guard)
|
|
87771
|
-
momentumThreshold: 500,
|
|
87772
|
-
// POLICY freshness bound — the gate never demands less
|
|
87773
|
-
momentumRatio: 0.01,
|
|
87774
|
-
// cold-start PRIOR only; calibration replaces it after the first pass
|
|
87775
|
-
momentumRatioCap: 0.05,
|
|
87776
|
-
// POLICY staleness bound — refresh by 5% churn no matter what
|
|
87777
|
-
quiescenceMs: 6e4
|
|
87778
|
-
// sim preferred 60s over 90s (fresher, esp. heavy-code)
|
|
87779
|
-
};
|
|
87780
|
-
function numEnv5(env2, key, fallback) {
|
|
87781
|
-
const raw2 = env2[key];
|
|
87782
|
-
if (raw2 == null || raw2.trim() === "") return fallback;
|
|
87783
|
-
const n = Number(raw2);
|
|
87784
|
-
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
87785
|
-
}
|
|
87786
|
-
function consolidationPolicyFromEnv(env2 = process.env) {
|
|
87787
|
-
return {
|
|
87788
|
-
baseFloorMs: numEnv5(env2, "ERRATA_CONSOLIDATE_BASE_FLOOR_MS", DEFAULT_CONSOLIDATION_POLICY.baseFloorMs),
|
|
87789
|
-
dutyFactor: numEnv5(env2, "ERRATA_CONSOLIDATE_DUTY_FACTOR", DEFAULT_CONSOLIDATION_POLICY.dutyFactor),
|
|
87790
|
-
momentumThreshold: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM", DEFAULT_CONSOLIDATION_POLICY.momentumThreshold),
|
|
87791
|
-
momentumRatio: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO", DEFAULT_CONSOLIDATION_POLICY.momentumRatio),
|
|
87792
|
-
momentumRatioCap: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO_CAP", DEFAULT_CONSOLIDATION_POLICY.momentumRatioCap),
|
|
87793
|
-
quiescenceMs: numEnv5(env2, "ERRATA_CONSOLIDATE_QUIESCENCE_MS", DEFAULT_CONSOLIDATION_POLICY.quiescenceMs)
|
|
87794
|
-
};
|
|
87795
|
-
}
|
|
87796
|
-
function consolidationGapMs(lastPassMs, policy) {
|
|
87797
|
-
return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
|
|
87798
|
-
}
|
|
87796
|
+
// src/codex-hooks.ts
|
|
87797
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "node:fs";
|
|
87798
|
+
import { homedir as homedir7 } from "node:os";
|
|
87799
|
+
import { join as join40 } from "node:path";
|
|
87799
87800
|
|
|
87800
87801
|
// src/hook-commands.ts
|
|
87801
87802
|
function hookCurlCommand(port, path2 = "/api/hook") {
|
|
@@ -87819,17 +87820,12 @@ function buildCodexHooksToml(port, options) {
|
|
|
87819
87820
|
};
|
|
87820
87821
|
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid hook port");
|
|
87821
87822
|
const command = quote(options.nodePath) + " " + quote(options.relayPath) + " " + port;
|
|
87822
|
-
const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse"].map(
|
|
87823
|
-
(event) => "[[hooks." + event + "]]\n" + (
|
|
87823
|
+
const handlers = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop"].map(
|
|
87824
|
+
(event) => "[[hooks." + event + "]]\n" + (["UserPromptSubmit", "Stop"].includes(event) ? "" : 'matcher = ".*"\n') + "\n[[hooks." + event + '.hooks]]\ntype = "command"\ncommand = ' + JSON.stringify(command) + "\ntimeout = 10\nadditionalContextLimit = 5000\n"
|
|
87824
87825
|
);
|
|
87825
87826
|
return CODEX_HOOKS_BEGIN + "\n" + handlers.join("\n") + CODEX_HOOKS_END + "\n";
|
|
87826
87827
|
}
|
|
87827
87828
|
|
|
87828
|
-
// src/codex-hooks.ts
|
|
87829
|
-
import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "node:fs";
|
|
87830
|
-
import { homedir as homedir7 } from "node:os";
|
|
87831
|
-
import { join as join39 } from "node:path";
|
|
87832
|
-
|
|
87833
87829
|
// src/codex-hook-relay.ts
|
|
87834
87830
|
var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
|
|
87835
87831
|
import { readFileSync } from 'node:fs';
|
|
@@ -87853,7 +87849,8 @@ try {
|
|
|
87853
87849
|
} catch { /* An unavailable daemon must never block the agent. */ }
|
|
87854
87850
|
};
|
|
87855
87851
|
if (event === 'PreToolUse' || event === 'PostToolUse') await post('hook', true);
|
|
87856
|
-
|
|
87852
|
+
// Stop sees the final assistant message, including turns with no tools.
|
|
87853
|
+
if (event === 'PostToolUse' || event === 'Stop') await post('turn');
|
|
87857
87854
|
if (['SessionStart', 'UserPromptSubmit', 'PostToolUse'].includes(event)) {
|
|
87858
87855
|
// Run after capture, so changes already rendered by the daemon arrive now.
|
|
87859
87856
|
// Background extraction finishing later arrives at the next tool boundary.
|
|
@@ -87868,8 +87865,9 @@ try {
|
|
|
87868
87865
|
`;
|
|
87869
87866
|
|
|
87870
87867
|
// src/codex-hooks.ts
|
|
87871
|
-
|
|
87872
|
-
|
|
87868
|
+
var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
|
|
87869
|
+
function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join40(homedir7(), ".codex")) {
|
|
87870
|
+
return existsSync33(join40(root, ".codex")) || existsSync33(codexHome);
|
|
87873
87871
|
}
|
|
87874
87872
|
function replaceCodexHooks(existing, block) {
|
|
87875
87873
|
const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
|
|
@@ -87885,17 +87883,176 @@ function replaceCodexHooks(existing, block) {
|
|
|
87885
87883
|
return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
|
|
87886
87884
|
}
|
|
87887
87885
|
function writeCodexHooks(root, port, nodePath = process.execPath) {
|
|
87888
|
-
const dir =
|
|
87889
|
-
const file2 =
|
|
87890
|
-
const relay =
|
|
87886
|
+
const dir = join40(root, ".codex");
|
|
87887
|
+
const file2 = join40(dir, "config.toml");
|
|
87888
|
+
const relay = join40(dir, "hooks", "errata-relay.mjs");
|
|
87891
87889
|
const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
|
|
87892
87890
|
const final = replaceCodexHooks(existsSync33(file2) ? readFileSync34(file2, "utf8") : "", block);
|
|
87893
|
-
mkdirSync9(
|
|
87891
|
+
mkdirSync9(join40(dir, "hooks"), { recursive: true });
|
|
87894
87892
|
writeFileSync25(relay, CODEX_RELAY_SOURCE, "utf8");
|
|
87895
87893
|
writeFileSync25(file2, final, "utf8");
|
|
87896
87894
|
return file2;
|
|
87897
87895
|
}
|
|
87898
87896
|
|
|
87897
|
+
// src/codex-doctor.ts
|
|
87898
|
+
function readCodexHookState(cwd, options = {}) {
|
|
87899
|
+
return new Promise((resolve7, reject) => {
|
|
87900
|
+
const child = spawn4(options.bin ?? resolveCodexExecutable(), options.args ?? ["app-server", "--stdio"], {
|
|
87901
|
+
cwd,
|
|
87902
|
+
windowsHide: true,
|
|
87903
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
87904
|
+
});
|
|
87905
|
+
const lines = createInterface({ input: child.stdout });
|
|
87906
|
+
let settled = false;
|
|
87907
|
+
let size = 0;
|
|
87908
|
+
let hooks;
|
|
87909
|
+
let features;
|
|
87910
|
+
const finish = (error48) => {
|
|
87911
|
+
if (settled) return;
|
|
87912
|
+
settled = true;
|
|
87913
|
+
clearTimeout(timer);
|
|
87914
|
+
lines.close();
|
|
87915
|
+
child.kill();
|
|
87916
|
+
if (error48) reject(error48);
|
|
87917
|
+
else resolve7({ ...hooks, features });
|
|
87918
|
+
};
|
|
87919
|
+
const timer = setTimeout(() => finish(new Error("Codex hook inspection timed out")), options.timeoutMs ?? 1e4);
|
|
87920
|
+
const send = (id, method, params) => {
|
|
87921
|
+
child.stdin.write(JSON.stringify({ id, method, params }) + "\n");
|
|
87922
|
+
};
|
|
87923
|
+
child.on("error", () => finish(new Error(`Codex could not be started for hook inspection. ${CODEX_HOOK_REVIEW_HELP}`)));
|
|
87924
|
+
child.on("exit", () => finish(new Error("Codex exited before returning its hook state")));
|
|
87925
|
+
child.stdin.on("error", () => finish(new Error("Codex hook inspection connection closed")));
|
|
87926
|
+
child.stderr.resume();
|
|
87927
|
+
child.stdout.on("data", (chunk) => {
|
|
87928
|
+
size += chunk.length;
|
|
87929
|
+
if (size > 2e6) finish(new Error("Codex hook inspection exceeded its response budget"));
|
|
87930
|
+
});
|
|
87931
|
+
lines.on("line", (line) => {
|
|
87932
|
+
if (settled) return;
|
|
87933
|
+
let message2;
|
|
87934
|
+
try {
|
|
87935
|
+
message2 = JSON.parse(line);
|
|
87936
|
+
} catch {
|
|
87937
|
+
return;
|
|
87938
|
+
}
|
|
87939
|
+
if (![1, 2, 3].includes(message2.id)) return;
|
|
87940
|
+
if (message2.error) return finish(new Error(`Codex does not support hook inspection. ${CODEX_HOOK_REVIEW_HELP}`));
|
|
87941
|
+
if (message2.id === 1) {
|
|
87942
|
+
child.stdin.write(JSON.stringify({ method: "initialized" }) + "\n");
|
|
87943
|
+
send(2, "hooks/list", { cwds: [cwd] });
|
|
87944
|
+
send(3, "config/read", { cwd, includeLayers: false });
|
|
87945
|
+
} else if (message2.id === 2) {
|
|
87946
|
+
const entry = message2.result?.data?.[0];
|
|
87947
|
+
if (!Array.isArray(entry?.hooks)) return finish(new Error("Codex returned no hook inspection result"));
|
|
87948
|
+
hooks = { hooks: entry.hooks, errors: entry.errors };
|
|
87949
|
+
} else {
|
|
87950
|
+
if (!message2.result?.config) return finish(new Error("Codex returned no effective configuration"));
|
|
87951
|
+
features = message2.result.config.features ?? {};
|
|
87952
|
+
}
|
|
87953
|
+
if (hooks && features) finish();
|
|
87954
|
+
});
|
|
87955
|
+
send(1, "initialize", {
|
|
87956
|
+
clientInfo: { name: "errata_doctor", version: "1.0.0" },
|
|
87957
|
+
capabilities: { experimentalApi: true }
|
|
87958
|
+
});
|
|
87959
|
+
});
|
|
87960
|
+
}
|
|
87961
|
+
function assessCodexHooks(state) {
|
|
87962
|
+
const check2 = (status, detail) => [{ id: "codex_hooks", status, detail }];
|
|
87963
|
+
if (state.errors?.length) return check2("fail", `Codex could not load hook configuration. ${CODEX_HOOK_REVIEW_HELP}`);
|
|
87964
|
+
if ((state.features?.hooks ?? state.features?.codex_hooks) === false) {
|
|
87965
|
+
return check2("fail", "Codex hooks are explicitly disabled; left unchanged");
|
|
87966
|
+
}
|
|
87967
|
+
const hooks = state.hooks.filter((h) => h.command?.includes("errata-relay.mjs"));
|
|
87968
|
+
const required2 = ["sessionStart", "userPromptSubmit", "preToolUse", "postToolUse", "stop"];
|
|
87969
|
+
const missing = required2.filter((event) => !hooks.some((h) => h.eventName === event));
|
|
87970
|
+
const checks = [];
|
|
87971
|
+
if (missing.length) checks.push(...check2("fail", `Errata hooks missing or outdated in this checkout (${missing.join(", ")}); run errata install-hooks codex here`));
|
|
87972
|
+
if (hooks.some((h) => !h.enabled)) checks.push(...check2("fail", `Errata hooks are disabled in Codex; left unchanged. ${CODEX_HOOK_REVIEW_HELP}`));
|
|
87973
|
+
if (hooks.some((h) => !["trusted", "managed"].includes(h.trustStatus))) {
|
|
87974
|
+
checks.push(...check2("fail", `Errata hooks need review/trust before they can run; project trust is separate. ${CODEX_HOOK_REVIEW_HELP}`));
|
|
87975
|
+
}
|
|
87976
|
+
return checks.length ? checks : check2("pass", "Codex discovers enabled, trusted Errata hooks; verify live context and capture in a session");
|
|
87977
|
+
}
|
|
87978
|
+
async function diagnoseCodexHooks(cwd) {
|
|
87979
|
+
try {
|
|
87980
|
+
return assessCodexHooks(await readCodexHookState(cwd));
|
|
87981
|
+
} catch (error48) {
|
|
87982
|
+
return [{ id: "codex_hooks", status: "fail", detail: error48 instanceof Error ? error48.message : "Cannot verify Codex hooks" }];
|
|
87983
|
+
}
|
|
87984
|
+
}
|
|
87985
|
+
|
|
87986
|
+
// src/whoami.ts
|
|
87987
|
+
async function resolveWhoami(client, actingHandle) {
|
|
87988
|
+
return actingHandle ? client.contextAs(actingHandle) : client.context();
|
|
87989
|
+
}
|
|
87990
|
+
function targetLabel(context) {
|
|
87991
|
+
const target = context.default_write_target;
|
|
87992
|
+
if (!target) return "read-only";
|
|
87993
|
+
if (target.visibility === "public") return "public graph";
|
|
87994
|
+
if (target.visibility === "org") return `organization graph (${target.org_id})`;
|
|
87995
|
+
return `private Team graph (${target.team_id})`;
|
|
87996
|
+
}
|
|
87997
|
+
function formatWhoami(response, localProfile) {
|
|
87998
|
+
const { context, identity } = response;
|
|
87999
|
+
return [
|
|
88000
|
+
`inErrata context \u2014 ${context.profile_name ?? localProfile ?? "unbound credential"}`,
|
|
88001
|
+
` workspace: ${context.workspace_kind} \xB7 ${context.org_id}`,
|
|
88002
|
+
` team: ${context.team_id ?? "(none)"}`,
|
|
88003
|
+
` agent: ${context.agent_id ?? "(default identity)"}`,
|
|
88004
|
+
` installation: ${context.installation_id ?? "(unbound)"}`,
|
|
88005
|
+
` environment: ${context.environment} \xB7 ${context.client_kind}`,
|
|
88006
|
+
` reads: ${context.read_visibilities.join(" + ")}`,
|
|
88007
|
+
` contributes: ${targetLabel(context)}`,
|
|
88008
|
+
` policy: ${context.policy_version ?? "(legacy)"}`,
|
|
88009
|
+
` credential: ${identity.credential_type} \xB7 ${identity.credential_id}`,
|
|
88010
|
+
` actor: ${identity.actor_type} \xB7 ${identity.actor_id}`
|
|
88011
|
+
];
|
|
88012
|
+
}
|
|
88013
|
+
|
|
88014
|
+
// src/consolidation-trigger.ts
|
|
88015
|
+
function effectiveMomentumThreshold(policy, liveNodes) {
|
|
88016
|
+
return Math.max(policy.momentumThreshold, Math.ceil(liveNodes * policy.momentumRatio));
|
|
88017
|
+
}
|
|
88018
|
+
function nextMomentumThreshold(args2) {
|
|
88019
|
+
const { current, consumed, landmarkFlips, floor, cap } = args2;
|
|
88020
|
+
const next = landmarkFlips > 0 ? Math.min(current, Math.round(consumed / 2)) : Math.max(current, Math.round(consumed * 1.5));
|
|
88021
|
+
return Math.max(floor, Math.min(cap, next));
|
|
88022
|
+
}
|
|
88023
|
+
var DEFAULT_CONSOLIDATION_POLICY = {
|
|
88024
|
+
baseFloorMs: 6e4,
|
|
88025
|
+
dutyFactor: 20,
|
|
88026
|
+
// ≤5% worst-case duty at any graph size (crater guard)
|
|
88027
|
+
momentumThreshold: 500,
|
|
88028
|
+
// POLICY freshness bound — the gate never demands less
|
|
88029
|
+
momentumRatio: 0.01,
|
|
88030
|
+
// cold-start PRIOR only; calibration replaces it after the first pass
|
|
88031
|
+
momentumRatioCap: 0.05,
|
|
88032
|
+
// POLICY staleness bound — refresh by 5% churn no matter what
|
|
88033
|
+
quiescenceMs: 6e4
|
|
88034
|
+
// sim preferred 60s over 90s (fresher, esp. heavy-code)
|
|
88035
|
+
};
|
|
88036
|
+
function numEnv5(env2, key, fallback) {
|
|
88037
|
+
const raw2 = env2[key];
|
|
88038
|
+
if (raw2 == null || raw2.trim() === "") return fallback;
|
|
88039
|
+
const n = Number(raw2);
|
|
88040
|
+
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
88041
|
+
}
|
|
88042
|
+
function consolidationPolicyFromEnv(env2 = process.env) {
|
|
88043
|
+
return {
|
|
88044
|
+
baseFloorMs: numEnv5(env2, "ERRATA_CONSOLIDATE_BASE_FLOOR_MS", DEFAULT_CONSOLIDATION_POLICY.baseFloorMs),
|
|
88045
|
+
dutyFactor: numEnv5(env2, "ERRATA_CONSOLIDATE_DUTY_FACTOR", DEFAULT_CONSOLIDATION_POLICY.dutyFactor),
|
|
88046
|
+
momentumThreshold: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM", DEFAULT_CONSOLIDATION_POLICY.momentumThreshold),
|
|
88047
|
+
momentumRatio: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO", DEFAULT_CONSOLIDATION_POLICY.momentumRatio),
|
|
88048
|
+
momentumRatioCap: numEnv5(env2, "ERRATA_CONSOLIDATE_MOMENTUM_RATIO_CAP", DEFAULT_CONSOLIDATION_POLICY.momentumRatioCap),
|
|
88049
|
+
quiescenceMs: numEnv5(env2, "ERRATA_CONSOLIDATE_QUIESCENCE_MS", DEFAULT_CONSOLIDATION_POLICY.quiescenceMs)
|
|
88050
|
+
};
|
|
88051
|
+
}
|
|
88052
|
+
function consolidationGapMs(lastPassMs, policy) {
|
|
88053
|
+
return Math.max(policy.baseFloorMs, lastPassMs * policy.dutyFactor);
|
|
88054
|
+
}
|
|
88055
|
+
|
|
87899
88056
|
// src/opencode-plugin.ts
|
|
87900
88057
|
var OPENCODE_PLUGIN_MARKER = "// @inerrata opencode plugin \u2014 errata-managed (errata install-hooks opencode)";
|
|
87901
88058
|
var OPENCODE_D1_CONTRACT = "Behavioral contract: (1) On ANY error, call search() BEFORE debugging \u2014 costs ~400 tokens vs 5,000\u201350,000 cold. (2) After solving non-trivial problems, contribute back: if your harness emits typed nodes (canonicalId + label + attrs), use ingest \u2014 the typed door; otherwise call contribute(), the prose fallback. (3) Before web search, try search() first \u2014 graph is 2\u201315\xD7 cheaper. (4) At session end, review what you solved and contribute anything novel.";
|
|
@@ -88302,13 +88459,13 @@ async function cmdInit() {
|
|
|
88302
88459
|
console.log("");
|
|
88303
88460
|
console.log("installing harness hooks...");
|
|
88304
88461
|
const { existsSync: existsSync35 } = await import("node:fs");
|
|
88305
|
-
const { join:
|
|
88462
|
+
const { join: join42 } = await import("node:path");
|
|
88306
88463
|
try {
|
|
88307
88464
|
await installClaudeHooks(port);
|
|
88308
88465
|
} catch (err2) {
|
|
88309
88466
|
console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
|
|
88310
88467
|
}
|
|
88311
|
-
if (existsSync35(
|
|
88468
|
+
if (existsSync35(join42(ROOT, ".cursor"))) {
|
|
88312
88469
|
try {
|
|
88313
88470
|
await installCursorMcpConfig();
|
|
88314
88471
|
} catch (err2) {
|
|
@@ -88752,6 +88909,7 @@ async function cmdWhoami(args2) {
|
|
|
88752
88909
|
async function cmdDoctor(args2) {
|
|
88753
88910
|
const cfg = loadConfig();
|
|
88754
88911
|
const report = await diagnoseInstallation(cfg, {
|
|
88912
|
+
...hasCodexConfig(process.cwd()) ? { codexHooks: () => diagnoseCodexHooks(process.cwd()) } : {},
|
|
88755
88913
|
inspect: () => inspectCloudEndpoint(cfg.cloudUrl),
|
|
88756
88914
|
authenticate: async () => {
|
|
88757
88915
|
const me = await authedCloudClient(cfg).me();
|
|
@@ -90135,8 +90293,8 @@ async function cmdReport(args2) {
|
|
|
90135
90293
|
const outDir = workspacePaths(ROOT).configDir;
|
|
90136
90294
|
mkdirSync10(outDir, { recursive: true });
|
|
90137
90295
|
const files = renderReport2(data, { includeFutureVerbs });
|
|
90138
|
-
for (const f of files) writeFileSync26(
|
|
90139
|
-
const indexPath =
|
|
90296
|
+
for (const f of files) writeFileSync26(join41(outDir, f.name), f.html, "utf8");
|
|
90297
|
+
const indexPath = join41(outDir, "report.html");
|
|
90140
90298
|
console.log(`report \u2192 ${indexPath}`);
|
|
90141
90299
|
console.log(
|
|
90142
90300
|
` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
|
|
@@ -90191,13 +90349,13 @@ function spawnDaemonDetached(options = {}) {
|
|
|
90191
90349
|
try {
|
|
90192
90350
|
const logPath = daemonLogPath();
|
|
90193
90351
|
try {
|
|
90194
|
-
if (
|
|
90352
|
+
if (statSync9(logPath).size > 5 * 1024 * 1024) renameSync4(logPath, `${logPath}.1`);
|
|
90195
90353
|
} catch {
|
|
90196
90354
|
}
|
|
90197
90355
|
out2 = openSync2(logPath, "a");
|
|
90198
90356
|
} catch {
|
|
90199
90357
|
}
|
|
90200
|
-
|
|
90358
|
+
spawn5(cmd2, args2, {
|
|
90201
90359
|
detached: true,
|
|
90202
90360
|
stdio: ["ignore", out2, out2],
|
|
90203
90361
|
windowsHide: true,
|
|
@@ -90257,10 +90415,10 @@ async function cmdInstallHooks(args2) {
|
|
|
90257
90415
|
}
|
|
90258
90416
|
async function installOpencodePlugin(port) {
|
|
90259
90417
|
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync26 } = await import("node:fs");
|
|
90260
|
-
const { join:
|
|
90261
|
-
const dir =
|
|
90418
|
+
const { join: join42 } = await import("node:path");
|
|
90419
|
+
const dir = join42(ROOT, ".opencode", "plugin");
|
|
90262
90420
|
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
90263
|
-
const file2 =
|
|
90421
|
+
const file2 = join42(dir, "inerrata.js");
|
|
90264
90422
|
if (existsSync35(file2)) {
|
|
90265
90423
|
const head2 = readFileSync36(file2, "utf8").split("\n")[0] ?? "";
|
|
90266
90424
|
if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
|
|
@@ -90269,7 +90427,7 @@ async function installOpencodePlugin(port) {
|
|
|
90269
90427
|
}
|
|
90270
90428
|
}
|
|
90271
90429
|
writeFileSync26(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
|
|
90272
|
-
const cfgFile =
|
|
90430
|
+
const cfgFile = join42(ROOT, "opencode.json");
|
|
90273
90431
|
let cfg = { $schema: "https://opencode.ai/config.json" };
|
|
90274
90432
|
if (existsSync35(cfgFile)) {
|
|
90275
90433
|
try {
|
|
@@ -90305,10 +90463,10 @@ function errataMcpInvocation() {
|
|
|
90305
90463
|
}
|
|
90306
90464
|
async function installClaudeHooks(port) {
|
|
90307
90465
|
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync26 } = await import("node:fs");
|
|
90308
|
-
const { join:
|
|
90309
|
-
const dir =
|
|
90466
|
+
const { join: join42 } = await import("node:path");
|
|
90467
|
+
const dir = join42(ROOT, ".claude");
|
|
90310
90468
|
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
90311
|
-
const file2 =
|
|
90469
|
+
const file2 = join42(dir, "settings.json");
|
|
90312
90470
|
let settings = {};
|
|
90313
90471
|
if (existsSync35(file2)) {
|
|
90314
90472
|
try {
|
|
@@ -90361,7 +90519,7 @@ async function installClaudeHooks(port) {
|
|
|
90361
90519
|
writeFileSync26(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
90362
90520
|
console.log(`installed Claude Code hooks \u2192 ${file2}`);
|
|
90363
90521
|
await installClaudeMcpConfig();
|
|
90364
|
-
const claudeMd =
|
|
90522
|
+
const claudeMd = join42(ROOT, "CLAUDE.md");
|
|
90365
90523
|
const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
|
|
90366
90524
|
if (recall.kind === "collision") {
|
|
90367
90525
|
console.warn(
|
|
@@ -90374,8 +90532,8 @@ async function installClaudeHooks(port) {
|
|
|
90374
90532
|
}
|
|
90375
90533
|
async function installClaudeMcpConfig() {
|
|
90376
90534
|
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync26 } = await import("node:fs");
|
|
90377
|
-
const { join:
|
|
90378
|
-
const file2 =
|
|
90535
|
+
const { join: join42, dirname: dirname13 } = await import("node:path");
|
|
90536
|
+
const file2 = join42(ROOT, ".mcp.json");
|
|
90379
90537
|
const dir = dirname13(file2);
|
|
90380
90538
|
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
90381
90539
|
let cfg = {};
|
|
@@ -90396,10 +90554,10 @@ async function installClaudeMcpConfig() {
|
|
|
90396
90554
|
}
|
|
90397
90555
|
async function installCursorMcpConfig() {
|
|
90398
90556
|
const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync36, writeFileSync: writeFileSync26 } = await import("node:fs");
|
|
90399
|
-
const { join:
|
|
90400
|
-
const dir =
|
|
90557
|
+
const { join: join42 } = await import("node:path");
|
|
90558
|
+
const dir = join42(ROOT, ".cursor");
|
|
90401
90559
|
if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
|
|
90402
|
-
const file2 =
|
|
90560
|
+
const file2 = join42(dir, "mcp.json");
|
|
90403
90561
|
let cfg = {};
|
|
90404
90562
|
if (existsSync35(file2)) {
|
|
90405
90563
|
try {
|
|
@@ -90419,12 +90577,26 @@ async function installCursorMcpConfig() {
|
|
|
90419
90577
|
console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
|
|
90420
90578
|
}
|
|
90421
90579
|
async function installCodexHooks(port) {
|
|
90422
|
-
const
|
|
90580
|
+
const gitRoot = nearestGitRoot(process.cwd());
|
|
90581
|
+
const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
|
|
90582
|
+
const file2 = writeCodexHooks(hookRoot, port);
|
|
90583
|
+
const instructions = writeManagedBlock(join41(hookRoot, "AGENTS.md"), {
|
|
90584
|
+
body: AGENTS_POINTER_BODY,
|
|
90585
|
+
stable: true
|
|
90586
|
+
});
|
|
90423
90587
|
console.log(`installed Codex hooks \u2192 ${file2}`);
|
|
90588
|
+
if (instructions.kind === "collision") {
|
|
90589
|
+
console.warn(" AGENTS.md's Errata block was edited; preserved it. Add an explicit instruction to read .errata/context.md each turn.");
|
|
90590
|
+
} else {
|
|
90591
|
+
console.log(" AGENTS.md now tells Codex to read live context at the start of each turn.");
|
|
90592
|
+
}
|
|
90424
90593
|
console.log(" Context loads on SessionStart/UserPromptSubmit and refreshes after tools when changed.");
|
|
90425
|
-
console.log(" Tool capture
|
|
90426
|
-
console.log(
|
|
90427
|
-
console.log("
|
|
90594
|
+
console.log(" Tool and final-reply capture are configured; hooks must be trusted before they run.");
|
|
90595
|
+
console.log(` ${CODEX_HOOK_REVIEW_HELP}`);
|
|
90596
|
+
console.log(" Use Reload hooks in that screen after installation. Restarting alone does not grant trust.");
|
|
90597
|
+
console.log(" No standalone Codex CLI is required for desktop setup.");
|
|
90598
|
+
console.log(" Run `errata doctor` here to check hook discovery and trust; installation alone is not activation.");
|
|
90599
|
+
console.log(" Respect an explicit [features] hooks = false setting (older builds use codex_hooks).");
|
|
90428
90600
|
console.log(" Older Codex versions may not support every event; update if hooks do not fire.");
|
|
90429
90601
|
}
|
|
90430
90602
|
async function refreshLinkedCodexHooks(args2) {
|
|
@@ -90812,7 +90984,7 @@ async function cmdDash(args2) {
|
|
|
90812
90984
|
await yieldToLoop2();
|
|
90813
90985
|
try {
|
|
90814
90986
|
const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
|
|
90815
|
-
const res = bleedRules(
|
|
90987
|
+
const res = bleedRules(join41(r.root, ".claude", "rules"), items);
|
|
90816
90988
|
if (res.written || res.pruned) {
|
|
90817
90989
|
console.log(
|
|
90818
90990
|
`[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
|
package/package.json
CHANGED
package/pass-worker.mjs
CHANGED
|
@@ -27255,6 +27255,11 @@ var AGENTS_POINTER_BODY = [
|
|
|
27255
27255
|
"Live agent context for this checkout \u2014 priors, open problems, the capture",
|
|
27256
27256
|
"protocol \u2014 is maintained by the errata daemon at `.errata/context.md`.",
|
|
27257
27257
|
"",
|
|
27258
|
+
"At the beginning of each task and each new user turn, read that file before",
|
|
27259
|
+
"substantive work. Use the current file in preference to an earlier snapshot.",
|
|
27260
|
+
"If it is absent, continue normally. In Codex, an `@` mention alone does not",
|
|
27261
|
+
"load the file; read it explicitly.",
|
|
27262
|
+
"",
|
|
27258
27263
|
"It is gitignored ON PURPOSE: it is this machine's runtime state, not repo",
|
|
27259
27264
|
"content. Committing it would prime your teammates with your graph.",
|
|
27260
27265
|
"",
|