@h-rig/core 0.0.6-alpha.164 → 0.0.6-alpha.165

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.
@@ -313,8 +313,8 @@ function loadDeclarativeConfig(path) {
313
313
  }
314
314
 
315
315
  // packages/core/src/load-config.ts
316
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
317
- var JSON_NAMES = ["rig.config.json"];
316
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
317
+ var JSON_NAMES = [".rig/rig.config.json"];
318
318
  function isModuleResolutionError(error) {
319
319
  const message = error instanceof Error ? error.message : String(error);
320
320
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -649,7 +649,7 @@ async function loadConfig(cwd) {
649
649
  return decodeExplicitPluginConfig(raw);
650
650
  }
651
651
  }
652
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
652
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
653
653
  }
654
654
  function decodeExplicitPluginConfig(raw) {
655
655
  const withDefaults = applyConfigDefaults(raw);
@@ -662,10 +662,19 @@ function decodeExplicitPluginConfig(raw) {
662
662
  }
663
663
 
664
664
  // packages/core/src/project-plugins.ts
665
- var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
665
+ var TS_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts"];
666
+ var JSON_CONFIG_FILENAMES = ["rig.config.json"];
666
667
  function findProjectConfigPath(projectRoot) {
667
- for (const name of RIG_CONFIG_FILENAMES) {
668
- const path = resolve2(projectRoot, name);
668
+ for (const name of TS_CONFIG_FILENAMES) {
669
+ const path = resolve2(projectRoot, ".rig", name);
670
+ if (existsSync3(path))
671
+ return path;
672
+ }
673
+ const declarativePath = findDeclarativeConfigPath(projectRoot);
674
+ if (declarativePath)
675
+ return declarativePath;
676
+ for (const name of JSON_CONFIG_FILENAMES) {
677
+ const path = resolve2(projectRoot, ".rig", name);
669
678
  if (existsSync3(path))
670
679
  return path;
671
680
  }
@@ -0,0 +1 @@
1
+ export { createDefaultKernel, createDefaultKernelPlugin, createPlacementTransportPlugin, } from "@rig/kernel-seed/default-kernel";
@@ -0,0 +1,12 @@
1
+ // @bun
2
+ // packages/core/src/default-kernel.ts
3
+ import {
4
+ createDefaultKernel,
5
+ createDefaultKernelPlugin,
6
+ createPlacementTransportPlugin
7
+ } from "@rig/kernel-seed/default-kernel";
8
+ export {
9
+ createPlacementTransportPlugin,
10
+ createDefaultKernelPlugin,
11
+ createDefaultKernel
12
+ };
@@ -1,12 +1,16 @@
1
1
  // @bun
2
2
  // packages/core/src/hook-materializer.ts
3
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
3
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
4
4
  import { dirname, resolve as resolve2 } from "path";
5
5
 
6
6
  // packages/core/src/hook-runtime.ts
7
- import { existsSync, readFileSync, realpathSync, writeSync } from "fs";
7
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, writeSync } from "fs";
8
8
  import { resolve } from "path";
9
9
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME } from "@rig/contracts";
10
+ function bunRuntime() {
11
+ const runtime = globalThis;
12
+ return runtime.Bun;
13
+ }
10
14
  function normalizeBuildConfig(value) {
11
15
  if (!value || typeof value !== "object" || Array.isArray(value)) {
12
16
  return {};
@@ -30,7 +34,11 @@ function readBuildConfigForCoreHooks() {
30
34
  var BUILD_CONFIG = readBuildConfigForCoreHooks();
31
35
  var BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
32
36
  var BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
37
+ var BAKED_STATE_DIR = BUILD_CONFIG.AGENT_STATE_DIR ?? "";
33
38
  var BAKED_BUN_PATH = BUILD_CONFIG.AGENT_BUN_PATH ?? "";
39
+ var BAKED_TASK_CONFIG = BUILD_CONFIG.AGENT_TASK_CONFIG ?? "";
40
+ var BAKED_POLICY_CONTENT = BUILD_CONFIG.AGENT_POLICY_CONTENT ?? "";
41
+ var BAKED_TASK_SCOPES = BUILD_CONFIG.AGENT_TASK_SCOPES ?? "";
34
42
  function normalizeExecutablePath(candidate) {
35
43
  if (!candidate) {
36
44
  return "";
@@ -54,8 +62,7 @@ function resolveBunBinaryPath() {
54
62
  if (explicit) {
55
63
  return explicit;
56
64
  }
57
- const bunGlobal = globalThis.Bun;
58
- const bunWhich = bunGlobal?.which?.("bun");
65
+ const bunWhich = bunRuntime()?.which?.("bun");
59
66
  const pathBun = normalizeExecutablePath(bunWhich?.trim());
60
67
  if (pathBun && !looksLikeRuntimeGateway(pathBun)) {
61
68
  return pathBun;
@@ -245,7 +252,7 @@ function writeClaudeCodeHookSettings(projectRoot, entries) {
245
252
  const settingsPath = resolve2(projectRoot, ".claude", "settings.json");
246
253
  const existing = existsSync2(settingsPath) ? safeReadJson(settingsPath) : {};
247
254
  const { settings, events } = applyClaudeCodeSessionHooksToSettings(existing, entries, projectRoot);
248
- mkdirSync(dirname(settingsPath), { recursive: true });
255
+ mkdirSync2(dirname(settingsPath), { recursive: true });
249
256
  writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
250
257
  `, "utf-8");
251
258
  return {
@@ -0,0 +1,2 @@
1
+ export type { HookInput, ParsedHookInput, TypedHookOptions } from "./hook-runtime";
2
+ export { BAKED_BUN_PATH, BAKED_POLICY_CONTENT, BAKED_PROJECT_ROOT, BAKED_STATE_DIR, BAKED_TASK_CONFIG, BAKED_TASK_ID, BAKED_TASK_SCOPES, block, buildPluginHookContext, escapeRegExp, extractToolFilePaths, hookResultToProtocol, isTestFilePath, readHookInput, resolveBunCli, resolveBunCliInvocation, resolvePolicyContent, resolveProjectRoot, resolveTaskConfig, resolveTaskIdForHook, resolveTaskScopes, runTypedHook, } from "./hook-runtime";
@@ -0,0 +1,462 @@
1
+ // @bun
2
+ // packages/core/src/hook-runtime.ts
3
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, writeSync } from "fs";
4
+ import { resolve } from "path";
5
+ import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME } from "@rig/contracts";
6
+ function bunRuntime() {
7
+ const runtime = globalThis;
8
+ return runtime.Bun;
9
+ }
10
+ function normalizeBuildConfig(value) {
11
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
12
+ return {};
13
+ }
14
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
15
+ }
16
+ function readBuildConfigForCoreHooks() {
17
+ if (typeof __RIG_BUILD_CONFIG__ !== "undefined") {
18
+ return normalizeBuildConfig(__RIG_BUILD_CONFIG__);
19
+ }
20
+ const raw = process.env.RIG_BUILD_CONFIG_JSON?.trim();
21
+ if (!raw) {
22
+ return {};
23
+ }
24
+ try {
25
+ return normalizeBuildConfig(JSON.parse(raw));
26
+ } catch {
27
+ return {};
28
+ }
29
+ }
30
+ var BUILD_CONFIG = readBuildConfigForCoreHooks();
31
+ var BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
32
+ var BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
33
+ var BAKED_STATE_DIR = BUILD_CONFIG.AGENT_STATE_DIR ?? "";
34
+ var BAKED_BUN_PATH = BUILD_CONFIG.AGENT_BUN_PATH ?? "";
35
+ var BAKED_TASK_CONFIG = BUILD_CONFIG.AGENT_TASK_CONFIG ?? "";
36
+ var BAKED_POLICY_CONTENT = BUILD_CONFIG.AGENT_POLICY_CONTENT ?? "";
37
+ var BAKED_TASK_SCOPES = BUILD_CONFIG.AGENT_TASK_SCOPES ?? "";
38
+ var RUNTIME_CONTEXT_ENV = "RIG_RUNTIME_CONTEXT_FILE";
39
+ function isPlainObject(value) {
40
+ return typeof value === "object" && value !== null && !Array.isArray(value);
41
+ }
42
+ function isStringArray(value) {
43
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
44
+ }
45
+ function loadHookContextFromEnv() {
46
+ const contextFile = process.env[RUNTIME_CONTEXT_ENV]?.trim();
47
+ let filePath = contextFile || "";
48
+ if (!filePath) {
49
+ let current = resolve(process.cwd());
50
+ while (true) {
51
+ const candidate = resolve(current, "runtime-context.json");
52
+ if (existsSync(candidate)) {
53
+ filePath = candidate;
54
+ break;
55
+ }
56
+ const parent = resolve(current, "..");
57
+ if (parent === current) {
58
+ break;
59
+ }
60
+ current = parent;
61
+ }
62
+ }
63
+ if (!filePath || !existsSync(filePath)) {
64
+ return null;
65
+ }
66
+ try {
67
+ const raw = JSON.parse(readFileSync(filePath, "utf-8"));
68
+ if (!isPlainObject(raw)) {
69
+ return null;
70
+ }
71
+ const taskId = typeof raw.taskId === "string" ? raw.taskId : "";
72
+ const role = typeof raw.role === "string" ? raw.role : "";
73
+ const scopes = isStringArray(raw.scopes) ? raw.scopes : [];
74
+ const validation = isStringArray(raw.validation) ? raw.validation : [];
75
+ const hostProjectRoot = typeof raw.hostProjectRoot === "string" ? raw.hostProjectRoot : undefined;
76
+ const monorepoMainRoot = typeof raw.monorepoMainRoot === "string" ? raw.monorepoMainRoot : undefined;
77
+ const stateDir = typeof raw.stateDir === "string" ? raw.stateDir : "";
78
+ const policyFile = typeof raw.policyFile === "string" ? raw.policyFile : "";
79
+ if (!taskId || !stateDir) {
80
+ return null;
81
+ }
82
+ return {
83
+ taskId,
84
+ role,
85
+ scopes,
86
+ validation,
87
+ hostProjectRoot,
88
+ monorepoMainRoot,
89
+ stateDir,
90
+ policyFile
91
+ };
92
+ } catch {
93
+ return null;
94
+ }
95
+ }
96
+ var cachedContext;
97
+ function getContext() {
98
+ if (cachedContext !== undefined) {
99
+ return cachedContext;
100
+ }
101
+ cachedContext = loadHookContextFromEnv();
102
+ return cachedContext;
103
+ }
104
+ function resolveProjectRoot() {
105
+ const ctx = getContext();
106
+ if (ctx?.hostProjectRoot)
107
+ return ctx.hostProjectRoot;
108
+ if (BAKED_PROJECT_ROOT) {
109
+ return BAKED_PROJECT_ROOT;
110
+ }
111
+ if (process.env.PROJECT_RIG_ROOT) {
112
+ return process.env.PROJECT_RIG_ROOT;
113
+ }
114
+ const candidates = [process.cwd(), resolve(import.meta.dirname, "../..")];
115
+ for (const candidate of candidates) {
116
+ if (existsSync(resolve(candidate, RIG_DEFINITION_DIRNAME)) || existsSync(resolve(candidate, RIG_STATE_DIRNAME))) {
117
+ return candidate;
118
+ }
119
+ }
120
+ return resolve(import.meta.dirname, "../..");
121
+ }
122
+ function resolveTaskIdForHook(_projectRoot) {
123
+ const ctx = getContext();
124
+ if (ctx)
125
+ return ctx.taskId;
126
+ if (BAKED_TASK_ID) {
127
+ return BAKED_TASK_ID;
128
+ }
129
+ const fromEnv = (process.env.RIG_TASK_ID || "").trim();
130
+ if (fromEnv) {
131
+ return fromEnv;
132
+ }
133
+ const runtimeId = (process.env.RIG_TASK_RUNTIME_ID || "").trim();
134
+ if (runtimeId.startsWith("task-") && runtimeId.length > "task-".length) {
135
+ return runtimeId.slice("task-".length);
136
+ }
137
+ return "";
138
+ }
139
+ function isTaskConfigEntry(value) {
140
+ if (!isPlainObject(value)) {
141
+ return false;
142
+ }
143
+ if ("role" in value && value.role !== undefined && typeof value.role !== "string") {
144
+ return false;
145
+ }
146
+ if ("scope" in value && value.scope !== undefined && !isStringArray(value.scope)) {
147
+ return false;
148
+ }
149
+ if ("validation" in value && value.validation !== undefined && !isStringArray(value.validation)) {
150
+ return false;
151
+ }
152
+ return true;
153
+ }
154
+ async function readTaskConfigFromDisk(configPath) {
155
+ if (!existsSync(configPath)) {
156
+ return null;
157
+ }
158
+ try {
159
+ const bunFile = bunRuntime()?.file;
160
+ const content = bunFile ? await bunFile(configPath).json() : JSON.parse(readFileSync(configPath, "utf-8"));
161
+ return isPlainObject(content) ? content : null;
162
+ } catch {
163
+ return null;
164
+ }
165
+ }
166
+ function taskConfigCandidates(ctx) {
167
+ const taskWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
168
+ return [
169
+ ctx?.monorepoMainRoot ? resolve(ctx.monorepoMainRoot, ".rig", "task-config.json") : "",
170
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
171
+ taskWorkspace ? resolve(taskWorkspace, ".rig", "task-config.json") : ""
172
+ ].filter(Boolean);
173
+ }
174
+ async function resolveTaskConfig(_projectRoot, _taskId) {
175
+ const ctx = getContext();
176
+ if (ctx) {
177
+ return {
178
+ scope: ctx.scopes,
179
+ validation: ctx.validation,
180
+ role: ctx.role
181
+ };
182
+ }
183
+ if (BAKED_TASK_CONFIG) {
184
+ try {
185
+ const parsed = JSON.parse(BAKED_TASK_CONFIG);
186
+ if (isTaskConfigEntry(parsed) && Object.keys(parsed).length > 0) {
187
+ return parsed;
188
+ }
189
+ } catch {}
190
+ }
191
+ for (const configPath of taskConfigCandidates(ctx)) {
192
+ const config = await readTaskConfigFromDisk(configPath);
193
+ if (!config) {
194
+ continue;
195
+ }
196
+ const taskEntry = config[_taskId];
197
+ if (isTaskConfigEntry(taskEntry)) {
198
+ return taskEntry;
199
+ }
200
+ }
201
+ return {};
202
+ }
203
+ async function resolveTaskScopes(projectRoot, taskId) {
204
+ const ctx = getContext();
205
+ if (ctx && ctx.scopes.length > 0)
206
+ return ctx.scopes;
207
+ if (BAKED_TASK_SCOPES) {
208
+ try {
209
+ const parsed = JSON.parse(BAKED_TASK_SCOPES);
210
+ if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((item) => typeof item === "string")) {
211
+ return parsed;
212
+ }
213
+ } catch {}
214
+ }
215
+ return (await resolveTaskConfig(projectRoot, taskId)).scope || [];
216
+ }
217
+ function resolvePolicyContent(projectRoot) {
218
+ const ctx = getContext();
219
+ if (ctx?.policyFile && existsSync(ctx.policyFile)) {
220
+ return readFileSync(ctx.policyFile, "utf-8");
221
+ }
222
+ if (BAKED_POLICY_CONTENT)
223
+ return BAKED_POLICY_CONTENT;
224
+ const policyPath = resolve(projectRoot, "rig/policy/policy.json");
225
+ if (existsSync(policyPath))
226
+ return readFileSync(policyPath, "utf-8");
227
+ return "{}";
228
+ }
229
+ async function readHookInput() {
230
+ let text = "";
231
+ const inputFile = process.env.RIG_HOOK_INPUT_FILE?.trim();
232
+ if (inputFile) {
233
+ text = readFileSync(inputFile, "utf-8");
234
+ } else {
235
+ try {
236
+ text = readFileSync("/dev/stdin", "utf-8");
237
+ } catch {
238
+ text = readFileSync(0, "utf-8");
239
+ }
240
+ }
241
+ if (!text.trim()) {
242
+ return { input: {}, valid: true, hadPayload: false };
243
+ }
244
+ try {
245
+ return {
246
+ input: JSON.parse(text),
247
+ valid: true,
248
+ hadPayload: true
249
+ };
250
+ } catch {
251
+ return { input: {}, valid: false, hadPayload: true };
252
+ }
253
+ }
254
+ function extractToolFilePaths(toolName, input) {
255
+ const paths = [];
256
+ const add = (value) => {
257
+ if (typeof value === "string" && value.trim()) {
258
+ paths.push(value.trim());
259
+ }
260
+ };
261
+ if (toolName === "Read" || toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") {
262
+ add(input.file_path);
263
+ add(input.path);
264
+ } else if (toolName === "Glob") {
265
+ add(input.path);
266
+ } else if (toolName === "Grep") {
267
+ add(input.path);
268
+ } else {
269
+ add(input.file_path);
270
+ add(input.path);
271
+ }
272
+ return paths;
273
+ }
274
+ function isTestFilePath(path) {
275
+ return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(path) || /\/(__tests__|tests|test)\//.test(path);
276
+ }
277
+ function buildPluginHookContext(parsed, opts) {
278
+ const toolName = parsed.input.tool_name;
279
+ const toolInput = parsed.input.tool_input ?? {};
280
+ return {
281
+ event: opts.event,
282
+ toolName,
283
+ toolInput,
284
+ filePaths: toolName ? extractToolFilePaths(toolName, toolInput) : [],
285
+ projectRoot: opts.projectRoot,
286
+ taskId: opts.taskId
287
+ };
288
+ }
289
+ function hookResultToProtocol(result) {
290
+ if (result.decision === "block") {
291
+ const lines = [`BLOCKED: ${result.reason ?? "blocked by plugin hook"}`];
292
+ if (result.systemMessage) {
293
+ lines.push(result.systemMessage);
294
+ }
295
+ return { exitCode: 1, stdout: `${lines.join(`
296
+ `)}
297
+ ` };
298
+ }
299
+ return {
300
+ exitCode: 0,
301
+ stdout: result.systemMessage ? `${result.systemMessage}
302
+ ` : ""
303
+ };
304
+ }
305
+ function escapeRegExp(value) {
306
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
307
+ }
308
+ function block(hookName, message, projectRoot) {
309
+ const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
310
+ const stateDir = BAKED_STATE_DIR || (runtimeWorkspace ? resolve(runtimeWorkspace, ".rig", "state") : resolve(projectRoot, ".rig", "state"));
311
+ mkdirSync(stateDir, { recursive: true });
312
+ const tripLog = resolve(stateDir, "hook_trips.log");
313
+ let count = 0;
314
+ if (existsSync(tripLog)) {
315
+ const content = readFileSync(tripLog, "utf-8");
316
+ count = (content.match(new RegExp(`^${escapeRegExp(hookName)}\\s`, "gm")) || []).length;
317
+ }
318
+ appendFileSync(tripLog, `${hookName} ${new Date().toISOString()}
319
+ `, "utf-8");
320
+ count += 1;
321
+ const lines = [
322
+ `BLOCKED: ${message}`,
323
+ "",
324
+ "Re-read CLAUDE.md safety rules before your next action."
325
+ ];
326
+ if (count >= 3) {
327
+ lines.push("");
328
+ lines.push(`REPEATED VIOLATION (${count}x ${hookName}).`);
329
+ lines.push("STOP. Read the FULL CLAUDE.md from top to bottom.");
330
+ lines.push("If stuck, write the problem to .rig/state/failed_approaches.md and request help.");
331
+ }
332
+ writeSync(1, `${lines.join(`
333
+ `)}
334
+ `);
335
+ process.exit(1);
336
+ }
337
+ function normalizeExecutablePath(candidate) {
338
+ if (!candidate) {
339
+ return "";
340
+ }
341
+ const normalized = resolve(candidate);
342
+ if (!existsSync(normalized)) {
343
+ return "";
344
+ }
345
+ try {
346
+ return realpathSync(normalized);
347
+ } catch {
348
+ return normalized;
349
+ }
350
+ }
351
+ function looksLikeRuntimeGateway(candidate) {
352
+ const normalized = resolve(candidate).replace(/\\/g, "/");
353
+ return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
354
+ }
355
+ function resolveBunBinaryPath() {
356
+ const explicit = normalizeExecutablePath(process.env.RIG_BUN_PATH?.trim());
357
+ if (explicit) {
358
+ return explicit;
359
+ }
360
+ const bunWhich = bunRuntime()?.which?.("bun");
361
+ const pathBun = normalizeExecutablePath(bunWhich?.trim());
362
+ if (pathBun && !looksLikeRuntimeGateway(pathBun)) {
363
+ return pathBun;
364
+ }
365
+ const home = process.env.HOME?.trim();
366
+ const fallbackCandidates = [
367
+ home ? resolve(home, ".bun/bin/bun") : "",
368
+ "/opt/homebrew/bin/bun",
369
+ "/usr/local/bin/bun",
370
+ "/usr/bin/bun"
371
+ ];
372
+ for (const candidate of fallbackCandidates) {
373
+ const normalized = normalizeExecutablePath(candidate);
374
+ if (normalized) {
375
+ return normalized;
376
+ }
377
+ }
378
+ const execPath = normalizeExecutablePath(process.execPath?.trim());
379
+ if (execPath && !looksLikeRuntimeGateway(execPath)) {
380
+ return execPath;
381
+ }
382
+ throw new Error("bun not found in PATH");
383
+ }
384
+ function resolveBunCli() {
385
+ return resolveBunCliInvocation().command;
386
+ }
387
+ function resolveBunCliInvocation() {
388
+ if (BAKED_BUN_PATH) {
389
+ return {
390
+ command: BAKED_BUN_PATH,
391
+ env: {}
392
+ };
393
+ }
394
+ if (process.env.RIG_BUN_PATH?.trim()) {
395
+ return {
396
+ command: process.env.RIG_BUN_PATH.trim(),
397
+ env: {}
398
+ };
399
+ }
400
+ try {
401
+ const systemBun = resolveBunBinaryPath();
402
+ return {
403
+ command: systemBun,
404
+ env: {}
405
+ };
406
+ } catch {}
407
+ if (process.execPath?.trim()) {
408
+ return {
409
+ command: process.execPath,
410
+ env: { BUN_BE_BUN: "1" }
411
+ };
412
+ }
413
+ return { command: "bun", env: {} };
414
+ }
415
+ async function runTypedHook(fn, opts) {
416
+ const parsed = await readHookInput();
417
+ const projectRoot = opts.projectRoot ?? resolveProjectRoot();
418
+ const taskId = opts.taskId ?? resolveTaskIdForHook(projectRoot);
419
+ const ctx = buildPluginHookContext(parsed, {
420
+ event: opts.event,
421
+ projectRoot,
422
+ taskId
423
+ });
424
+ let result;
425
+ try {
426
+ result = await fn(ctx);
427
+ } catch (err) {
428
+ const message = err instanceof Error ? err.message : String(err);
429
+ writeSync(2, `[rig hook] typed hook threw: ${message}
430
+ `);
431
+ process.exit(0);
432
+ }
433
+ const { exitCode, stdout } = hookResultToProtocol(result);
434
+ if (stdout) {
435
+ writeSync(1, stdout);
436
+ }
437
+ process.exit(exitCode);
438
+ }
439
+ export {
440
+ runTypedHook,
441
+ resolveTaskScopes,
442
+ resolveTaskIdForHook,
443
+ resolveTaskConfig,
444
+ resolveProjectRoot,
445
+ resolvePolicyContent,
446
+ resolveBunCliInvocation,
447
+ resolveBunCli,
448
+ readHookInput,
449
+ isTestFilePath,
450
+ hookResultToProtocol,
451
+ extractToolFilePaths,
452
+ escapeRegExp,
453
+ buildPluginHookContext,
454
+ block,
455
+ BAKED_TASK_SCOPES,
456
+ BAKED_TASK_ID,
457
+ BAKED_TASK_CONFIG,
458
+ BAKED_STATE_DIR,
459
+ BAKED_PROJECT_ROOT,
460
+ BAKED_POLICY_CONTENT,
461
+ BAKED_BUN_PATH
462
+ };
@@ -90,8 +90,8 @@ function loadDeclarativeConfig(path) {
90
90
  }
91
91
 
92
92
  // packages/core/src/load-config.ts
93
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
94
- var JSON_NAMES = ["rig.config.json"];
93
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
94
+ var JSON_NAMES = [".rig/rig.config.json"];
95
95
  function isModuleResolutionError(error) {
96
96
  const message = error instanceof Error ? error.message : String(error);
97
97
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -426,7 +426,7 @@ async function loadConfig(cwd) {
426
426
  return decodeExplicitPluginConfig(raw);
427
427
  }
428
428
  }
429
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
429
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
430
430
  }
431
431
  function decodeExplicitPluginConfig(raw) {
432
432
  const withDefaults = applyConfigDefaults(raw);
@@ -439,7 +439,7 @@ function decodeExplicitPluginConfig(raw) {
439
439
  }
440
440
 
441
441
  // packages/core/src/hook-runtime.ts
442
- import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync, writeSync } from "fs";
442
+ import { appendFileSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync, writeSync } from "fs";
443
443
  import { resolve as resolve2 } from "path";
444
444
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME } from "@rig/contracts";
445
445
  function normalizeBuildConfig(value) {
@@ -465,7 +465,11 @@ function readBuildConfigForCoreHooks() {
465
465
  var BUILD_CONFIG = readBuildConfigForCoreHooks();
466
466
  var BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
467
467
  var BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
468
+ var BAKED_STATE_DIR = BUILD_CONFIG.AGENT_STATE_DIR ?? "";
468
469
  var BAKED_BUN_PATH = BUILD_CONFIG.AGENT_BUN_PATH ?? "";
470
+ var BAKED_TASK_CONFIG = BUILD_CONFIG.AGENT_TASK_CONFIG ?? "";
471
+ var BAKED_POLICY_CONTENT = BUILD_CONFIG.AGENT_POLICY_CONTENT ?? "";
472
+ var BAKED_TASK_SCOPES = BUILD_CONFIG.AGENT_TASK_SCOPES ?? "";
469
473
  var RUNTIME_CONTEXT_ENV = "RIG_RUNTIME_CONTEXT_FILE";
470
474
  function isPlainObject(value) {
471
475
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1,9 +1,50 @@
1
- import { type HookEvent, type HookImplementation } from "@rig/contracts";
1
+ import { type HookContext as PluginHookContext, type HookEvent, type HookImplementation, type HookResult } from "@rig/contracts";
2
+ export type HookInput = {
3
+ tool_name?: string;
4
+ tool_input?: Record<string, unknown>;
5
+ command?: string;
6
+ };
7
+ export type ParsedHookInput = {
8
+ input: HookInput;
9
+ valid: boolean;
10
+ hadPayload: boolean;
11
+ };
2
12
  export interface TypedHookOptions {
3
13
  readonly event: HookEvent;
4
14
  readonly projectRoot?: string;
5
15
  readonly taskId?: string;
6
16
  }
17
+ export declare const BAKED_PROJECT_ROOT: string;
18
+ export declare const BAKED_TASK_ID: string;
19
+ export declare const BAKED_STATE_DIR: string;
20
+ export declare const BAKED_BUN_PATH: string;
21
+ export declare const BAKED_TASK_CONFIG: string;
22
+ export declare const BAKED_POLICY_CONTENT: string;
23
+ export declare const BAKED_TASK_SCOPES: string;
24
+ export declare function resolveProjectRoot(): string;
25
+ export declare function resolveTaskIdForHook(_projectRoot: string): string;
26
+ export declare function resolveTaskConfig(_projectRoot: string, _taskId: string): Promise<{
27
+ scope?: string[];
28
+ validation?: string[];
29
+ role?: string;
30
+ }>;
31
+ export declare function resolveTaskScopes(projectRoot: string, taskId: string): Promise<string[]>;
32
+ export declare function resolvePolicyContent(projectRoot: string): string;
33
+ export declare function readHookInput(): Promise<ParsedHookInput>;
34
+ export declare function extractToolFilePaths(toolName: string, input: Record<string, unknown>): string[];
35
+ export declare function isTestFilePath(path: string): boolean;
36
+ export declare function buildPluginHookContext(parsed: ParsedHookInput, opts: {
37
+ event: HookEvent;
38
+ projectRoot: string;
39
+ taskId: string;
40
+ }): PluginHookContext;
41
+ export declare function hookResultToProtocol(result: HookResult): {
42
+ exitCode: 0 | 1;
43
+ stdout: string;
44
+ };
45
+ export declare function escapeRegExp(value: string): string;
46
+ export declare function block(hookName: string, message: string, projectRoot: string): never;
47
+ export declare function resolveBunCli(): string;
7
48
  export declare function resolveBunCliInvocation(): {
8
49
  command: string;
9
50
  env: Record<string, string>;
@@ -1,8 +1,12 @@
1
1
  // @bun
2
2
  // packages/core/src/hook-runtime.ts
3
- import { existsSync, readFileSync, realpathSync, writeSync } from "fs";
3
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, writeSync } from "fs";
4
4
  import { resolve } from "path";
5
5
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME } from "@rig/contracts";
6
+ function bunRuntime() {
7
+ const runtime = globalThis;
8
+ return runtime.Bun;
9
+ }
6
10
  function normalizeBuildConfig(value) {
7
11
  if (!value || typeof value !== "object" || Array.isArray(value)) {
8
12
  return {};
@@ -26,7 +30,11 @@ function readBuildConfigForCoreHooks() {
26
30
  var BUILD_CONFIG = readBuildConfigForCoreHooks();
27
31
  var BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
28
32
  var BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
33
+ var BAKED_STATE_DIR = BUILD_CONFIG.AGENT_STATE_DIR ?? "";
29
34
  var BAKED_BUN_PATH = BUILD_CONFIG.AGENT_BUN_PATH ?? "";
35
+ var BAKED_TASK_CONFIG = BUILD_CONFIG.AGENT_TASK_CONFIG ?? "";
36
+ var BAKED_POLICY_CONTENT = BUILD_CONFIG.AGENT_POLICY_CONTENT ?? "";
37
+ var BAKED_TASK_SCOPES = BUILD_CONFIG.AGENT_TASK_SCOPES ?? "";
30
38
  var RUNTIME_CONTEXT_ENV = "RIG_RUNTIME_CONTEXT_FILE";
31
39
  function isPlainObject(value) {
32
40
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -128,6 +136,96 @@ function resolveTaskIdForHook(_projectRoot) {
128
136
  }
129
137
  return "";
130
138
  }
139
+ function isTaskConfigEntry(value) {
140
+ if (!isPlainObject(value)) {
141
+ return false;
142
+ }
143
+ if ("role" in value && value.role !== undefined && typeof value.role !== "string") {
144
+ return false;
145
+ }
146
+ if ("scope" in value && value.scope !== undefined && !isStringArray(value.scope)) {
147
+ return false;
148
+ }
149
+ if ("validation" in value && value.validation !== undefined && !isStringArray(value.validation)) {
150
+ return false;
151
+ }
152
+ return true;
153
+ }
154
+ async function readTaskConfigFromDisk(configPath) {
155
+ if (!existsSync(configPath)) {
156
+ return null;
157
+ }
158
+ try {
159
+ const bunFile = bunRuntime()?.file;
160
+ const content = bunFile ? await bunFile(configPath).json() : JSON.parse(readFileSync(configPath, "utf-8"));
161
+ return isPlainObject(content) ? content : null;
162
+ } catch {
163
+ return null;
164
+ }
165
+ }
166
+ function taskConfigCandidates(ctx) {
167
+ const taskWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
168
+ return [
169
+ ctx?.monorepoMainRoot ? resolve(ctx.monorepoMainRoot, ".rig", "task-config.json") : "",
170
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
171
+ taskWorkspace ? resolve(taskWorkspace, ".rig", "task-config.json") : ""
172
+ ].filter(Boolean);
173
+ }
174
+ async function resolveTaskConfig(_projectRoot, _taskId) {
175
+ const ctx = getContext();
176
+ if (ctx) {
177
+ return {
178
+ scope: ctx.scopes,
179
+ validation: ctx.validation,
180
+ role: ctx.role
181
+ };
182
+ }
183
+ if (BAKED_TASK_CONFIG) {
184
+ try {
185
+ const parsed = JSON.parse(BAKED_TASK_CONFIG);
186
+ if (isTaskConfigEntry(parsed) && Object.keys(parsed).length > 0) {
187
+ return parsed;
188
+ }
189
+ } catch {}
190
+ }
191
+ for (const configPath of taskConfigCandidates(ctx)) {
192
+ const config = await readTaskConfigFromDisk(configPath);
193
+ if (!config) {
194
+ continue;
195
+ }
196
+ const taskEntry = config[_taskId];
197
+ if (isTaskConfigEntry(taskEntry)) {
198
+ return taskEntry;
199
+ }
200
+ }
201
+ return {};
202
+ }
203
+ async function resolveTaskScopes(projectRoot, taskId) {
204
+ const ctx = getContext();
205
+ if (ctx && ctx.scopes.length > 0)
206
+ return ctx.scopes;
207
+ if (BAKED_TASK_SCOPES) {
208
+ try {
209
+ const parsed = JSON.parse(BAKED_TASK_SCOPES);
210
+ if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((item) => typeof item === "string")) {
211
+ return parsed;
212
+ }
213
+ } catch {}
214
+ }
215
+ return (await resolveTaskConfig(projectRoot, taskId)).scope || [];
216
+ }
217
+ function resolvePolicyContent(projectRoot) {
218
+ const ctx = getContext();
219
+ if (ctx?.policyFile && existsSync(ctx.policyFile)) {
220
+ return readFileSync(ctx.policyFile, "utf-8");
221
+ }
222
+ if (BAKED_POLICY_CONTENT)
223
+ return BAKED_POLICY_CONTENT;
224
+ const policyPath = resolve(projectRoot, "rig/policy/policy.json");
225
+ if (existsSync(policyPath))
226
+ return readFileSync(policyPath, "utf-8");
227
+ return "{}";
228
+ }
131
229
  async function readHookInput() {
132
230
  let text = "";
133
231
  const inputFile = process.env.RIG_HOOK_INPUT_FILE?.trim();
@@ -173,6 +271,9 @@ function extractToolFilePaths(toolName, input) {
173
271
  }
174
272
  return paths;
175
273
  }
274
+ function isTestFilePath(path) {
275
+ return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(path) || /\/(__tests__|tests|test)\//.test(path);
276
+ }
176
277
  function buildPluginHookContext(parsed, opts) {
177
278
  const toolName = parsed.input.tool_name;
178
279
  const toolInput = parsed.input.tool_input ?? {};
@@ -201,6 +302,38 @@ function hookResultToProtocol(result) {
201
302
  ` : ""
202
303
  };
203
304
  }
305
+ function escapeRegExp(value) {
306
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
307
+ }
308
+ function block(hookName, message, projectRoot) {
309
+ const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
310
+ const stateDir = BAKED_STATE_DIR || (runtimeWorkspace ? resolve(runtimeWorkspace, ".rig", "state") : resolve(projectRoot, ".rig", "state"));
311
+ mkdirSync(stateDir, { recursive: true });
312
+ const tripLog = resolve(stateDir, "hook_trips.log");
313
+ let count = 0;
314
+ if (existsSync(tripLog)) {
315
+ const content = readFileSync(tripLog, "utf-8");
316
+ count = (content.match(new RegExp(`^${escapeRegExp(hookName)}\\s`, "gm")) || []).length;
317
+ }
318
+ appendFileSync(tripLog, `${hookName} ${new Date().toISOString()}
319
+ `, "utf-8");
320
+ count += 1;
321
+ const lines = [
322
+ `BLOCKED: ${message}`,
323
+ "",
324
+ "Re-read CLAUDE.md safety rules before your next action."
325
+ ];
326
+ if (count >= 3) {
327
+ lines.push("");
328
+ lines.push(`REPEATED VIOLATION (${count}x ${hookName}).`);
329
+ lines.push("STOP. Read the FULL CLAUDE.md from top to bottom.");
330
+ lines.push("If stuck, write the problem to .rig/state/failed_approaches.md and request help.");
331
+ }
332
+ writeSync(1, `${lines.join(`
333
+ `)}
334
+ `);
335
+ process.exit(1);
336
+ }
204
337
  function normalizeExecutablePath(candidate) {
205
338
  if (!candidate) {
206
339
  return "";
@@ -224,8 +357,7 @@ function resolveBunBinaryPath() {
224
357
  if (explicit) {
225
358
  return explicit;
226
359
  }
227
- const bunGlobal = globalThis.Bun;
228
- const bunWhich = bunGlobal?.which?.("bun");
360
+ const bunWhich = bunRuntime()?.which?.("bun");
229
361
  const pathBun = normalizeExecutablePath(bunWhich?.trim());
230
362
  if (pathBun && !looksLikeRuntimeGateway(pathBun)) {
231
363
  return pathBun;
@@ -249,6 +381,9 @@ function resolveBunBinaryPath() {
249
381
  }
250
382
  throw new Error("bun not found in PATH");
251
383
  }
384
+ function resolveBunCli() {
385
+ return resolveBunCliInvocation().command;
386
+ }
252
387
  function resolveBunCliInvocation() {
253
388
  if (BAKED_BUN_PATH) {
254
389
  return {
@@ -303,5 +438,25 @@ async function runTypedHook(fn, opts) {
303
438
  }
304
439
  export {
305
440
  runTypedHook,
306
- resolveBunCliInvocation
441
+ resolveTaskScopes,
442
+ resolveTaskIdForHook,
443
+ resolveTaskConfig,
444
+ resolveProjectRoot,
445
+ resolvePolicyContent,
446
+ resolveBunCliInvocation,
447
+ resolveBunCli,
448
+ readHookInput,
449
+ isTestFilePath,
450
+ hookResultToProtocol,
451
+ extractToolFilePaths,
452
+ escapeRegExp,
453
+ buildPluginHookContext,
454
+ block,
455
+ BAKED_TASK_SCOPES,
456
+ BAKED_TASK_ID,
457
+ BAKED_TASK_CONFIG,
458
+ BAKED_STATE_DIR,
459
+ BAKED_PROJECT_ROOT,
460
+ BAKED_POLICY_CONTENT,
461
+ BAKED_BUN_PATH
307
462
  };
@@ -0,0 +1,2 @@
1
+ export { bootDefaultKernelIntoProcess, getProcessKernel, } from "@rig/kernel-seed/boot-default";
2
+ export type { DefaultKernelBootRecord } from "@rig/kernel-seed/boot-default";
@@ -0,0 +1,10 @@
1
+ // @bun
2
+ // packages/core/src/kernel-boot.ts
3
+ import {
4
+ bootDefaultKernelIntoProcess,
5
+ getProcessKernel
6
+ } from "@rig/kernel-seed/boot-default";
7
+ export {
8
+ getProcessKernel,
9
+ bootDefaultKernelIntoProcess
10
+ };
@@ -1,6 +1,6 @@
1
1
  import type { JournalCapability, TransportCapability } from "@rig/contracts";
2
- import { type DefaultKernelBootRecord } from "@rig/kernel-seed/boot-default";
3
- import type { CapabilityProviderPlugin } from "@rig/kernel-seed/plugin-abi";
2
+ import { type DefaultKernelBootRecord } from "./kernel-boot";
3
+ import type { CapabilityProviderPlugin } from "./kernel-plugin-abi";
4
4
  export type HydrationResult = {
5
5
  readonly projectRoot: string;
6
6
  readonly dotenvLoaded: boolean;
@@ -2,8 +2,19 @@
2
2
  // packages/core/src/kernel-entrypoint.ts
3
3
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
4
4
  import { resolve as resolve2 } from "path";
5
- import { bootDefaultKernelIntoProcess } from "@rig/kernel-seed/boot-default";
6
- import { createPlacementTransportPlugin } from "@rig/kernel-seed/default-kernel";
5
+
6
+ // packages/core/src/kernel-boot.ts
7
+ import {
8
+ bootDefaultKernelIntoProcess,
9
+ getProcessKernel
10
+ } from "@rig/kernel-seed/boot-default";
11
+
12
+ // packages/core/src/default-kernel.ts
13
+ import {
14
+ createDefaultKernel,
15
+ createDefaultKernelPlugin,
16
+ createPlacementTransportPlugin
17
+ } from "@rig/kernel-seed/default-kernel";
7
18
 
8
19
  // packages/core/src/config-env.ts
9
20
  function applyConfigEnv(config, env = process.env) {
@@ -114,8 +125,8 @@ function loadDeclarativeConfig(path) {
114
125
  }
115
126
 
116
127
  // packages/core/src/load-config.ts
117
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
118
- var JSON_NAMES = ["rig.config.json"];
128
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
129
+ var JSON_NAMES = [".rig/rig.config.json"];
119
130
  function isModuleResolutionError(error) {
120
131
  const message = error instanceof Error ? error.message : String(error);
121
132
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -450,7 +461,7 @@ async function loadConfig(cwd) {
450
461
  return decodeExplicitPluginConfig(raw);
451
462
  }
452
463
  }
453
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
464
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
454
465
  }
455
466
  function decodeExplicitPluginConfig(raw) {
456
467
  const withDefaults = applyConfigDefaults(raw);
@@ -0,0 +1 @@
1
+ export type { CapabilityProviderPlugin } from "@rig/kernel-seed/plugin-abi";
@@ -0,0 +1 @@
1
+ // @bun
@@ -0,0 +1,2 @@
1
+ export { resolveKernelStages } from "@rig/kernel-seed/resolver";
2
+ export type { KernelStageResolverResult } from "@rig/kernel-seed/resolver";
@@ -0,0 +1,6 @@
1
+ // @bun
2
+ // packages/core/src/kernel-resolver.ts
3
+ import { resolveKernelStages } from "@rig/kernel-seed/resolver";
4
+ export {
5
+ resolveKernelStages
6
+ };
@@ -45,7 +45,7 @@ function resolveNearestRigProjectRoot(startDir) {
45
45
  const hasDefinition = existsSync2(resolve2(current, RIG_DEFINITION_DIRNAME));
46
46
  const hasState = existsSync2(resolve2(current, RIG_STATE_DIRNAME));
47
47
  const hasTaskConfig = existsSync2(resolve2(current, RIG_STATE_DIRNAME, "task-config.json"));
48
- const hasConfig = existsSync2(resolve2(current, "rig.config.ts")) || existsSync2(resolve2(current, "rig.config.json"));
48
+ const hasConfig = existsSync2(resolve2(current, ".rig", "rig.config.ts")) || existsSync2(resolve2(current, ".rig", "rig.config.json"));
49
49
  const hasGit = existsSync2(resolve2(current, ".git"));
50
50
  const hasControlPlane = existsSync2(resolve2(current, "packages", "cli", "bin", "rig.ts")) || existsSync2(resolve2(current, "packages", "server"));
51
51
  if ((hasDefinition || hasState || hasConfig) && weakMarkerCandidate === null) {
@@ -90,8 +90,8 @@ function loadDeclarativeConfig(path) {
90
90
  }
91
91
 
92
92
  // packages/core/src/load-config.ts
93
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
94
- var JSON_NAMES = ["rig.config.json"];
93
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
94
+ var JSON_NAMES = [".rig/rig.config.json"];
95
95
  function isModuleResolutionError(error) {
96
96
  const message = error instanceof Error ? error.message : String(error);
97
97
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -426,7 +426,7 @@ async function loadConfig(cwd) {
426
426
  return decodeExplicitPluginConfig(raw);
427
427
  }
428
428
  }
429
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
429
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
430
430
  }
431
431
  function decodeExplicitPluginConfig(raw) {
432
432
  const withDefaults = applyConfigDefaults(raw);
@@ -94,8 +94,8 @@ function loadDeclarativeConfig(path) {
94
94
  }
95
95
 
96
96
  // packages/core/src/load-config.ts
97
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
98
- var JSON_NAMES = ["rig.config.json"];
97
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
98
+ var JSON_NAMES = [".rig/rig.config.json"];
99
99
  function isModuleResolutionError(error) {
100
100
  const message = error instanceof Error ? error.message : String(error);
101
101
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -430,7 +430,7 @@ async function loadConfig(cwd) {
430
430
  return decodeExplicitPluginConfig(raw);
431
431
  }
432
432
  }
433
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
433
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
434
434
  }
435
435
  function decodeExplicitPluginConfig(raw) {
436
436
  const withDefaults = applyConfigDefaults(raw);
@@ -313,8 +313,8 @@ function loadDeclarativeConfig(path) {
313
313
  }
314
314
 
315
315
  // packages/core/src/load-config.ts
316
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
317
- var JSON_NAMES = ["rig.config.json"];
316
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
317
+ var JSON_NAMES = [".rig/rig.config.json"];
318
318
  function isModuleResolutionError(error) {
319
319
  const message = error instanceof Error ? error.message : String(error);
320
320
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -649,7 +649,7 @@ async function loadConfig(cwd) {
649
649
  return decodeExplicitPluginConfig(raw);
650
650
  }
651
651
  }
652
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
652
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
653
653
  }
654
654
  function decodeExplicitPluginConfig(raw) {
655
655
  const withDefaults = applyConfigDefaults(raw);
@@ -662,10 +662,19 @@ function decodeExplicitPluginConfig(raw) {
662
662
  }
663
663
 
664
664
  // packages/core/src/project-plugins.ts
665
- var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
665
+ var TS_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts"];
666
+ var JSON_CONFIG_FILENAMES = ["rig.config.json"];
666
667
  function findProjectConfigPath(projectRoot) {
667
- for (const name of RIG_CONFIG_FILENAMES) {
668
- const path = resolve2(projectRoot, name);
668
+ for (const name of TS_CONFIG_FILENAMES) {
669
+ const path = resolve2(projectRoot, ".rig", name);
670
+ if (existsSync3(path))
671
+ return path;
672
+ }
673
+ const declarativePath = findDeclarativeConfigPath(projectRoot);
674
+ if (declarativePath)
675
+ return declarativePath;
676
+ for (const name of JSON_CONFIG_FILENAMES) {
677
+ const path = resolve2(projectRoot, ".rig", name);
669
678
  if (existsSync3(path))
670
679
  return path;
671
680
  }
@@ -937,13 +946,17 @@ function setScopeRules(rules) {
937
946
  }
938
947
 
939
948
  // packages/core/src/hook-materializer.ts
940
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync } from "fs";
949
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync } from "fs";
941
950
  import { dirname as dirname2, resolve as resolve4 } from "path";
942
951
 
943
952
  // packages/core/src/hook-runtime.ts
944
- import { existsSync as existsSync5, readFileSync as readFileSync3, realpathSync, writeSync } from "fs";
953
+ import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync3, realpathSync, writeSync } from "fs";
945
954
  import { resolve as resolve3 } from "path";
946
955
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME } from "@rig/contracts";
956
+ function bunRuntime() {
957
+ const runtime = globalThis;
958
+ return runtime.Bun;
959
+ }
947
960
  function normalizeBuildConfig(value) {
948
961
  if (!value || typeof value !== "object" || Array.isArray(value)) {
949
962
  return {};
@@ -967,7 +980,11 @@ function readBuildConfigForCoreHooks() {
967
980
  var BUILD_CONFIG = readBuildConfigForCoreHooks();
968
981
  var BAKED_PROJECT_ROOT = BUILD_CONFIG.AGENT_PROJECT_ROOT ?? "";
969
982
  var BAKED_TASK_ID = BUILD_CONFIG.AGENT_TASK_ID ?? "";
983
+ var BAKED_STATE_DIR = BUILD_CONFIG.AGENT_STATE_DIR ?? "";
970
984
  var BAKED_BUN_PATH = BUILD_CONFIG.AGENT_BUN_PATH ?? "";
985
+ var BAKED_TASK_CONFIG = BUILD_CONFIG.AGENT_TASK_CONFIG ?? "";
986
+ var BAKED_POLICY_CONTENT = BUILD_CONFIG.AGENT_POLICY_CONTENT ?? "";
987
+ var BAKED_TASK_SCOPES = BUILD_CONFIG.AGENT_TASK_SCOPES ?? "";
971
988
  function normalizeExecutablePath(candidate) {
972
989
  if (!candidate) {
973
990
  return "";
@@ -991,8 +1008,7 @@ function resolveBunBinaryPath() {
991
1008
  if (explicit) {
992
1009
  return explicit;
993
1010
  }
994
- const bunGlobal = globalThis.Bun;
995
- const bunWhich = bunGlobal?.which?.("bun");
1011
+ const bunWhich = bunRuntime()?.which?.("bun");
996
1012
  const pathBun = normalizeExecutablePath(bunWhich?.trim());
997
1013
  if (pathBun && !looksLikeRuntimeGateway(pathBun)) {
998
1014
  return pathBun;
@@ -1178,7 +1194,7 @@ function writeClaudeCodeHookSettings(projectRoot, entries) {
1178
1194
  const settingsPath = resolve4(projectRoot, ".claude", "settings.json");
1179
1195
  const existing = existsSync6(settingsPath) ? safeReadJson(settingsPath) : {};
1180
1196
  const { settings, events } = applyClaudeCodeSessionHooksToSettings(existing, entries, projectRoot);
1181
- mkdirSync2(dirname2(settingsPath), { recursive: true });
1197
+ mkdirSync3(dirname2(settingsPath), { recursive: true });
1182
1198
  writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
1183
1199
  `, "utf-8");
1184
1200
  return {
@@ -1208,7 +1224,7 @@ async function buildPluginHostContext(projectRoot) {
1208
1224
  ({ config, host: pluginHost } = await resolvePluginHost(projectRoot));
1209
1225
  } catch (err) {
1210
1226
  const msg = err instanceof Error ? err.message : String(err);
1211
- if (msg.includes("no rig.config")) {
1227
+ if (msg.includes("no .rig/rig.config") || msg.includes("no rig.config")) {
1212
1228
  return null;
1213
1229
  }
1214
1230
  throw err;
@@ -313,8 +313,8 @@ function loadDeclarativeConfig(path) {
313
313
  }
314
314
 
315
315
  // packages/core/src/load-config.ts
316
- var TS_NAMES = ["rig.config.ts", "rig.config.mts"];
317
- var JSON_NAMES = ["rig.config.json"];
316
+ var TS_NAMES = [".rig/rig.config.ts", ".rig/rig.config.mts"];
317
+ var JSON_NAMES = [".rig/rig.config.json"];
318
318
  function isModuleResolutionError(error) {
319
319
  const message = error instanceof Error ? error.message : String(error);
320
320
  return message.includes("Cannot find module") || message.includes("Could not resolve");
@@ -649,7 +649,7 @@ async function loadConfig(cwd) {
649
649
  return decodeExplicitPluginConfig(raw);
650
650
  }
651
651
  }
652
- throw new Error(`no rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
652
+ throw new Error(`no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ${cwd}`);
653
653
  }
654
654
  function decodeExplicitPluginConfig(raw) {
655
655
  const withDefaults = applyConfigDefaults(raw);
@@ -662,17 +662,27 @@ function decodeExplicitPluginConfig(raw) {
662
662
  }
663
663
 
664
664
  // packages/core/src/project-plugins.ts
665
- var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
665
+ var TS_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts"];
666
+ var JSON_CONFIG_FILENAMES = ["rig.config.json"];
667
+ var MISSING_CONFIG_PREFIX = "no .rig/rig.config.{ts,mts,json} or .rig/rigfig.{toml,json} found in ";
666
668
  function findProjectConfigPath(projectRoot) {
667
- for (const name of RIG_CONFIG_FILENAMES) {
668
- const path = resolve2(projectRoot, name);
669
+ for (const name of TS_CONFIG_FILENAMES) {
670
+ const path = resolve2(projectRoot, ".rig", name);
671
+ if (existsSync3(path))
672
+ return path;
673
+ }
674
+ const declarativePath = findDeclarativeConfigPath(projectRoot);
675
+ if (declarativePath)
676
+ return declarativePath;
677
+ for (const name of JSON_CONFIG_FILENAMES) {
678
+ const path = resolve2(projectRoot, ".rig", name);
669
679
  if (existsSync3(path))
670
680
  return path;
671
681
  }
672
682
  return null;
673
683
  }
674
684
  function isMissingProjectConfigError(error) {
675
- return error instanceof Error && error.message.startsWith("no rig.config.{ts,mts,json} found in ");
685
+ return error instanceof Error && (error.message.startsWith(MISSING_CONFIG_PREFIX) || error.message.startsWith("no rig.config.{ts,mts,json} found in "));
676
686
  }
677
687
  async function loadProjectPluginSet(projectRootOrOptions, maybeOptions = {}) {
678
688
  const projectRoot = typeof projectRootOrOptions === "string" ? projectRootOrOptions : projectRootOrOptions.projectRoot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/core",
3
- "version": "0.0.6-alpha.164",
3
+ "version": "0.0.6-alpha.165",
4
4
  "type": "module",
5
5
  "description": "Config and plugin composition library for Rig's OMP extension ecosystem; not a product host/runtime.",
6
6
  "license": "UNLICENSED",
@@ -53,6 +53,22 @@
53
53
  "types": "./dist/src/kernel-entrypoint.d.ts",
54
54
  "import": "./dist/src/kernel-entrypoint.js"
55
55
  },
56
+ "./kernel-boot": {
57
+ "types": "./dist/src/kernel-boot.d.ts",
58
+ "import": "./dist/src/kernel-boot.js"
59
+ },
60
+ "./default-kernel": {
61
+ "types": "./dist/src/default-kernel.d.ts",
62
+ "import": "./dist/src/default-kernel.js"
63
+ },
64
+ "./kernel-resolver": {
65
+ "types": "./dist/src/kernel-resolver.d.ts",
66
+ "import": "./dist/src/kernel-resolver.js"
67
+ },
68
+ "./kernel-plugin-abi": {
69
+ "types": "./dist/src/kernel-plugin-abi.d.ts",
70
+ "import": "./dist/src/kernel-plugin-abi.js"
71
+ },
56
72
  "./setup-version": {
57
73
  "types": "./dist/src/setup-version.d.ts",
58
74
  "import": "./dist/src/setup-version.js"
@@ -113,6 +129,10 @@
113
129
  "types": "./dist/src/hook-runner.d.ts",
114
130
  "import": "./dist/src/hook-runner.js"
115
131
  },
132
+ "./hook-protocol": {
133
+ "types": "./dist/src/hook-protocol.d.ts",
134
+ "import": "./dist/src/hook-protocol.js"
135
+ },
116
136
  "./plugin-host-registries": {
117
137
  "types": "./dist/src/plugin-host-registries.d.ts",
118
138
  "import": "./dist/src/plugin-host-registries.js"
@@ -165,8 +185,8 @@
165
185
  "module": "./dist/src/index.js",
166
186
  "types": "./dist/src/index.d.ts",
167
187
  "dependencies": {
168
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.164",
169
- "@rig/kernel-seed": "npm:@h-rig/kernel-seed@0.0.6-alpha.164",
188
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.165",
189
+ "@rig/kernel-seed": "npm:@h-rig/kernel-seed@0.0.6-alpha.165",
170
190
  "effect": "4.0.0-beta.90",
171
191
  "smol-toml": "^1.6.0"
172
192
  }