@h-rig/core 0.0.6-alpha.176 → 0.0.6-alpha.178

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // packages/core/src/hook-materializer.ts
3
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
4
- import { dirname, resolve as resolve2 } from "path";
3
+ import { existsSync as existsSync2 } from "fs";
4
+ import { resolve as resolve2 } from "path";
5
5
 
6
6
  // packages/core/src/hook-runtime.ts
7
7
  import { appendFileSync, existsSync, mkdirSync, readFileSync, realpathSync, writeSync } from "fs";
@@ -116,18 +116,6 @@ function resolveBunCliInvocation() {
116
116
  }
117
117
 
118
118
  // packages/core/src/hook-materializer.ts
119
- var MARKER_PLUGIN = "_rigPlugin";
120
- var MARKER_HOOK_ID = "_rigHookId";
121
- function matcherToString(matcher) {
122
- if (matcher.kind === "all")
123
- return;
124
- if (matcher.kind === "tool")
125
- return matcher.name;
126
- return matcher.pattern;
127
- }
128
- function isPluginOwned(cmd) {
129
- return typeof cmd[MARKER_PLUGIN] === "string";
130
- }
131
119
  function shellQuote(value) {
132
120
  return `'${value.replaceAll("'", `'\\''`)}'`;
133
121
  }
@@ -158,124 +146,7 @@ function buildTypedHookShimCommand(pluginName, hook, projectRoot) {
158
146
  ].filter(Boolean);
159
147
  return parts.join(" ");
160
148
  }
161
- function createPiNoopSessionHookAdapter() {
162
- return {
163
- id: "pi",
164
- materialize() {
165
- return {
166
- adapterId: "pi",
167
- status: "skipped",
168
- reason: "Pi sessions do not consume Claude Code settings hooks."
169
- };
170
- }
171
- };
172
- }
173
- function createClaudeCodeSessionHookAdapter() {
174
- return {
175
- id: "claude-code",
176
- materialize(projectRoot, entries) {
177
- return writeClaudeCodeHookSettings(projectRoot, entries);
178
- }
179
- };
180
- }
181
- function defaultAgentSessionHookAdapters(env = process.env) {
182
- if (env.RIG_AGENT_SESSION_HOOK_ADAPTER === "claude-code") {
183
- return [createClaudeCodeSessionHookAdapter()];
184
- }
185
- if (env.RIG_AGENT_SESSION_HOOK_ADAPTER === "pi" || typeof env.PI_CODING_AGENT_SESSION_DIR === "string" && env.PI_CODING_AGENT_SESSION_DIR.trim().length > 0 || env.RIG_RUN_PROCESS === "1") {
186
- return [createPiNoopSessionHookAdapter()];
187
- }
188
- return [createClaudeCodeSessionHookAdapter()];
189
- }
190
- function materializeSessionHookAdapters(projectRoot, entries, adapters = [createClaudeCodeSessionHookAdapter()]) {
191
- return adapters.map((adapter) => adapter.materialize(projectRoot, entries));
192
- }
193
- function materializeHooks(projectRoot, entries) {
194
- const result = createClaudeCodeSessionHookAdapter().materialize(projectRoot, entries);
195
- return result.status === "materialized" ? result.path : resolve2(projectRoot, ".claude", "settings.json");
196
- }
197
- function applyClaudeCodeSessionHooksToSettings(existing, entries, projectRoot, options = {}) {
198
- const hooks = typeof existing.hooks === "object" && existing.hooks !== null && !Array.isArray(existing.hooks) ? existing.hooks : {};
199
- const replacePluginOwned = options.replacePluginOwned ?? true;
200
- if (replacePluginOwned) {
201
- for (const event of Object.keys(hooks)) {
202
- const groups = hooks[event] ?? [];
203
- const cleaned = [];
204
- for (const group of groups) {
205
- const operatorHooks = group.hooks.filter((h) => !isPluginOwned(h));
206
- if (operatorHooks.length > 0) {
207
- cleaned.push({ ...group, hooks: operatorHooks });
208
- }
209
- }
210
- if (cleaned.length > 0) {
211
- hooks[event] = cleaned;
212
- } else {
213
- delete hooks[event];
214
- }
215
- }
216
- }
217
- const materializedEvents = new Set;
218
- for (const { pluginName, hook, typed } of entries) {
219
- const command = hook.command ?? (typed ? buildTypedHookShimCommand(pluginName, hook, projectRoot) : undefined);
220
- if (!command) {
221
- continue;
222
- }
223
- const event = hook.event;
224
- materializedEvents.add(event);
225
- const matcherString = matcherToString(hook.matcher);
226
- const groups = hooks[event] ??= [];
227
- let group = groups.find((g) => g.matcher === matcherString);
228
- if (!group) {
229
- group = matcherString === undefined ? { hooks: [] } : { matcher: matcherString, hooks: [] };
230
- groups.push(group);
231
- }
232
- const alreadyPresent = group.hooks.some((candidate) => candidate[MARKER_PLUGIN] === pluginName && candidate[MARKER_HOOK_ID] === hook.id);
233
- if (alreadyPresent) {
234
- continue;
235
- }
236
- group.hooks.push({
237
- type: "command",
238
- command,
239
- [MARKER_PLUGIN]: pluginName,
240
- [MARKER_HOOK_ID]: hook.id
241
- });
242
- }
243
- const next = { ...existing };
244
- if (Object.keys(hooks).length > 0) {
245
- next.hooks = hooks;
246
- } else {
247
- delete next.hooks;
248
- }
249
- return { settings: next, events: [...materializedEvents].sort() };
250
- }
251
- function writeClaudeCodeHookSettings(projectRoot, entries) {
252
- const settingsPath = resolve2(projectRoot, ".claude", "settings.json");
253
- const existing = existsSync2(settingsPath) ? safeReadJson(settingsPath) : {};
254
- const { settings, events } = applyClaudeCodeSessionHooksToSettings(existing, entries, projectRoot);
255
- mkdirSync2(dirname(settingsPath), { recursive: true });
256
- writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
257
- `, "utf-8");
258
- return {
259
- adapterId: "claude-code",
260
- status: "materialized",
261
- path: settingsPath,
262
- events
263
- };
264
- }
265
- function safeReadJson(path) {
266
- try {
267
- return JSON.parse(readFileSync2(path, "utf-8"));
268
- } catch {
269
- return {};
270
- }
271
- }
272
149
  export {
273
150
  resolveHookRunnerPath,
274
- materializeSessionHookAdapters,
275
- materializeHooks,
276
- defaultAgentSessionHookAdapters,
277
- createPiNoopSessionHookAdapter,
278
- createClaudeCodeSessionHookAdapter,
279
- buildTypedHookShimCommand,
280
- applyClaudeCodeSessionHooksToSettings
151
+ buildTypedHookShimCommand
281
152
  };
@@ -151,26 +151,6 @@ function isTaskConfigEntry(value) {
151
151
  }
152
152
  return true;
153
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
154
  async function resolveTaskConfig(_projectRoot, _taskId) {
175
155
  const ctx = getContext();
176
156
  if (ctx) {
@@ -188,16 +168,6 @@ async function resolveTaskConfig(_projectRoot, _taskId) {
188
168
  }
189
169
  } catch {}
190
170
  }
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
171
  return {};
202
172
  }
203
173
  async function resolveTaskScopes(projectRoot, taskId) {
@@ -327,7 +297,7 @@ function block(hookName, message, projectRoot) {
327
297
  lines.push("");
328
298
  lines.push(`REPEATED VIOLATION (${count}x ${hookName}).`);
329
299
  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.");
300
+ lines.push("If stuck, record the failed approach in the task-state failure log and request help.");
331
301
  }
332
302
  writeSync(1, `${lines.join(`
333
303
  `)}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * hook-runner.ts — entrypoint for typed plugin hooks.
3
3
  *
4
- * The hook-materializer writes a shim command into `.claude/settings.json`
5
- * for every plugin hook that ships a typed implementation instead of a raw
6
- * command string:
4
+ * The provider-owned session-hook materializer writes a shim command into
5
+ * the active session host for every plugin hook that ships a typed
6
+ * implementation instead of a raw command string:
7
7
  *
8
8
  * <bun> <this file> --plugin <name> --hook <id> [--event <event>] [--project-root <dir>]
9
9
  *
@@ -2,7 +2,7 @@
2
2
  // packages/core/src/load-config.ts
3
3
  import { existsSync as existsSync2, mkdirSync, mkdtempSync, readFileSync as readFileSync2, readdirSync, rmSync, statSync } from "fs";
4
4
  import { isBuiltin } from "module";
5
- import { dirname, isAbsolute, join as join2, relative, resolve } from "path";
5
+ import { basename, dirname, isAbsolute, join as join2, relative, resolve } from "path";
6
6
  import { pathToFileURL } from "url";
7
7
  import { Schema as Schema3 } from "effect";
8
8
  import { RigConfig as RigConfig3 } from "@rig/contracts";
@@ -69,8 +69,11 @@ function parseDeclarativeFile(path) {
69
69
  }
70
70
  function loadDeclarativeConfig(path) {
71
71
  const data = parseDeclarativeFile(path);
72
- const standardSection = data.standard && typeof data.standard === "object" && !Array.isArray(data.standard) ? data.standard : {};
73
- const useStandard = standardSection.enabled !== false;
72
+ const standardSection = data.standard && typeof data.standard === "object" && !Array.isArray(data.standard) ? data.standard : null;
73
+ if (standardSection?.enabled !== true && standardSection?.enabled !== false) {
74
+ throw new Error(`Declarative config ${path} must explicitly set [standard] enabled = true or false.`);
75
+ }
76
+ const useStandard = standardSection.enabled === true;
74
77
  let plugins = [];
75
78
  if (useStandard) {
76
79
  const resolver = getStandardPluginsResolver();
@@ -112,19 +115,27 @@ function packageNameAndSubpath(specifier) {
112
115
  function exportTargetFromEntry(entry) {
113
116
  if (typeof entry === "string")
114
117
  return entry;
115
- if (entry && typeof entry === "object" && !Array.isArray(entry)) {
118
+ if (Array.isArray(entry)) {
119
+ for (const candidate of entry) {
120
+ const target = exportTargetFromEntry(candidate);
121
+ if (target)
122
+ return target;
123
+ }
124
+ return null;
125
+ }
126
+ if (entry && typeof entry === "object") {
116
127
  const conditions = entry;
117
- for (const key of ["bun", "import", "default", "require"]) {
118
- if (typeof conditions[key] === "string")
119
- return conditions[key];
128
+ for (const key of ["bun", "node", "import", "default", "require"]) {
129
+ const target = exportTargetFromEntry(conditions[key]);
130
+ if (target)
131
+ return target;
120
132
  }
121
133
  }
122
134
  return null;
123
135
  }
124
136
  function patternExportTarget(record, subpath) {
125
- for (const [pattern, entry] of Object.entries(record)) {
126
- if (!pattern.includes("*"))
127
- continue;
137
+ const entries = Object.entries(record).filter(([pattern]) => pattern.includes("*")).sort(([a], [b]) => b.replace("*", "").length - a.replace("*", "").length);
138
+ for (const [pattern, entry] of entries) {
128
139
  const [prefix = "", suffix = ""] = pattern.split("*");
129
140
  if (!subpath.startsWith(prefix) || !subpath.endsWith(suffix))
130
141
  continue;
@@ -149,6 +160,49 @@ function exportTargetFromPackageJson(pkg, subpath) {
149
160
  return target;
150
161
  return subpath === "." && typeof pkg.module === "string" ? pkg.module : subpath === "." && typeof pkg.main === "string" ? pkg.main : null;
151
162
  }
163
+ function patternImportTarget(record, specifier) {
164
+ for (const [pattern, entry] of Object.entries(record)) {
165
+ if (!pattern.includes("*"))
166
+ continue;
167
+ const [prefix = "", suffix = ""] = pattern.split("*");
168
+ if (!specifier.startsWith(prefix) || !specifier.endsWith(suffix))
169
+ continue;
170
+ const replacement = specifier.slice(prefix.length, specifier.length - suffix.length);
171
+ const target = exportTargetFromEntry(entry);
172
+ if (target)
173
+ return target.replace("*", replacement);
174
+ }
175
+ return null;
176
+ }
177
+ function resolvePackagePrivateImport(specifier, importer, projectRoot) {
178
+ if (!specifier.startsWith("#") || !importer || !isAbsolute(importer))
179
+ return null;
180
+ let dir = dirname(importer);
181
+ const stop = resolve(projectRoot);
182
+ while (isWithinDir(dir, stop)) {
183
+ const packageJsonPath = join2(dir, "package.json");
184
+ if (existsSync2(packageJsonPath)) {
185
+ try {
186
+ const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
187
+ const imports = pkg.imports;
188
+ if (imports && typeof imports === "object" && !Array.isArray(imports)) {
189
+ const record = imports;
190
+ const target = exportTargetFromEntry(record[specifier]) ?? patternImportTarget(record, specifier);
191
+ if (target)
192
+ return resolveModulePath(join2(dir, target));
193
+ }
194
+ } catch {
195
+ return null;
196
+ }
197
+ return null;
198
+ }
199
+ const parent = dirname(dir);
200
+ if (parent === dir)
201
+ return null;
202
+ dir = parent;
203
+ }
204
+ return null;
205
+ }
152
206
  function resolvePackageDirFromBunStore(packageName, nodeModulesDir) {
153
207
  const storeDir = join2(nodeModulesDir, ".bun");
154
208
  if (!existsSync2(storeDir))
@@ -223,8 +277,15 @@ function resolvePackageExportFromDir(packageDir, subpath) {
223
277
  if (existsSync2(packageJsonPath)) {
224
278
  try {
225
279
  const pkg = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
226
- const target = exportTargetFromPackageJson(pkg, subpath);
227
- if (target) {
280
+ const targets = [
281
+ exportTargetFromPackageJson(pkg, subpath),
282
+ ...subpath === "." ? [typeof pkg.module === "string" ? pkg.module : null, typeof pkg.main === "string" ? pkg.main : null] : []
283
+ ];
284
+ const seen = new Set;
285
+ for (const target of targets) {
286
+ if (!target || seen.has(target))
287
+ continue;
288
+ seen.add(target);
228
289
  const resolved = resolveModulePath(join2(packageDir, target));
229
290
  if (resolved)
230
291
  return resolved;
@@ -312,10 +373,17 @@ async function importConfigViaRuntimeBundleUnserialized(configPath) {
312
373
  }
313
374
  const RUNTIME_ONLY_EXTERNAL_PACKAGES = new Set(["effect", "mupdf", "fastembed", "onnxruntime-node", "markit-ai"]);
314
375
  const configDir = dirname(configPath);
376
+ const configProjectRoot = basename(configDir) === ".rig" ? dirname(configDir) : configDir;
315
377
  const UNRESOLVED_NAMESPACE = "rig-config-unresolved";
378
+ const ABSOLUTE_EXTERNAL_NAMESPACE = "rig-config-absolute-external";
316
379
  const unresolvedLocalPlugin = {
317
380
  name: "rig-config-unresolved-local",
318
381
  setup(build) {
382
+ build.onLoad({ filter: /[\\/]@oh-my-pi[\\/]pi-coding-agent[\\/]src[\\/]export[\\/]html[\\/](?:template\.css|template\.html|template\.js|tool-views\.generated\.js)$/ }, (args) => ({
383
+ loader: "js",
384
+ contents: `export default ${JSON.stringify(readFileSync2(args.path, "utf8"))};
385
+ `
386
+ }));
319
387
  build.onLoad({ filter: /\.(?:html|txt)$/ }, (args) => ({
320
388
  loader: "js",
321
389
  contents: `export default ${JSON.stringify(readFileSync2(args.path, "utf8"))};
@@ -325,32 +393,77 @@ async function importConfigViaRuntimeBundleUnserialized(configPath) {
325
393
  const directFilePath = resolvedFilePath(args.path, configDir);
326
394
  if (directFilePath)
327
395
  return { path: directFilePath };
396
+ if (args.path.startsWith("#")) {
397
+ const packagePrivatePath = resolvePackagePrivateImport(args.path, args.importer, configProjectRoot);
398
+ if (packagePrivatePath)
399
+ return { path: packagePrivatePath };
400
+ try {
401
+ const parent2 = args.importer && isAbsolute(args.importer) ? dirname(args.importer) : configProjectRoot;
402
+ const resolved = bun.resolveSync?.(args.path, parent2);
403
+ const filePath = resolvedFilePath(resolved, configProjectRoot);
404
+ if (filePath)
405
+ return { path: filePath };
406
+ } catch {}
407
+ return;
408
+ }
328
409
  const packageImport = packageNameAndSubpath(args.path);
329
- if (packageImport && (packageImport.packageName.startsWith("@rig/") || RUNTIME_ONLY_EXTERNAL_PACKAGES.has(packageImport.packageName))) {
330
- return { path: args.path, external: true };
410
+ if (packageImport?.packageName === "uhyphen" && packageImport.subpath === ".") {
411
+ const uhyphenPath = resolveProjectPackageImport("uhyphen", configProjectRoot);
412
+ if (uhyphenPath)
413
+ return { path: uhyphenPath };
331
414
  }
332
- const projectPackagePath = resolveProjectPackageImport(args.path, configDir);
415
+ if (packageImport && packageImport.packageName !== "uhyphen") {
416
+ try {
417
+ const parent2 = args.importer && isAbsolute(args.importer) ? dirname(args.importer) : configProjectRoot;
418
+ const resolved = bun.resolveSync?.(args.path, parent2);
419
+ const filePath = resolvedFilePath(resolved, configProjectRoot);
420
+ if (filePath)
421
+ return { path: filePath };
422
+ } catch {}
423
+ }
424
+ const projectPackagePath = packageImport ? resolveProjectPackageImport(args.path, configProjectRoot) : null;
333
425
  if (projectPackagePath)
334
426
  return { path: projectPackagePath };
427
+ if (packageImport && (packageImport.packageName.startsWith("@rig/") || RUNTIME_ONLY_EXTERNAL_PACKAGES.has(packageImport.packageName))) {
428
+ return { path: args.path, external: true };
429
+ }
335
430
  if (/^(?:node|bun):/.test(args.path) || isBuiltin(args.path))
336
431
  return;
337
432
  if (packageImport)
338
433
  return { path: args.path, external: true };
339
- const parentCandidates = args.path.startsWith(".") ? [args.importer && isAbsolute(args.importer) ? dirname(args.importer) : null, configDir].filter((value) => Boolean(value)) : [args.importer && isAbsolute(args.importer) ? dirname(args.importer) : configDir];
434
+ const importerDir = args.importer && isAbsolute(args.importer) ? dirname(args.importer) : null;
435
+ if (args.path.startsWith(".") && importerDir) {
436
+ const fromImporter = resolveModulePath(resolve(importerDir, args.path));
437
+ if (fromImporter)
438
+ return { path: fromImporter };
439
+ if (/[\\/]node_modules[\\/]/.test(args.importer ?? ""))
440
+ return;
441
+ }
442
+ const parentCandidates = args.path.startsWith(".") ? [importerDir, configDir].filter((value) => Boolean(value)) : [importerDir ?? configDir];
340
443
  for (const parent2 of parentCandidates) {
341
- const filePath = resolvedFilePath(resolve(parent2, args.path), configDir);
444
+ const filePath = resolvedFilePath(resolve(parent2, args.path), configProjectRoot);
342
445
  if (filePath)
343
446
  return { path: filePath };
344
447
  }
345
448
  const parent = parentCandidates[0] ?? configDir;
346
449
  try {
347
450
  const resolved = bun.resolveSync?.(args.path, parent) ?? resolve(parent, args.path);
348
- const filePath = resolvedFilePath(resolved, configDir);
451
+ const filePath = resolvedFilePath(resolved, configProjectRoot);
349
452
  if (filePath)
350
453
  return { path: filePath };
351
454
  } catch {}
352
455
  return { path: args.path, namespace: UNRESOLVED_NAMESPACE };
353
456
  });
457
+ build.onLoad({ filter: /.*/, namespace: ABSOLUTE_EXTERNAL_NAMESPACE }, (args) => {
458
+ const href = pathToFileURL(args.path).href;
459
+ return {
460
+ loader: "js",
461
+ contents: `export * from ${JSON.stringify(href)};
462
+ const mod = await import(${JSON.stringify(href)});
463
+ export default (mod && "default" in mod) ? mod.default : mod;
464
+ `
465
+ };
466
+ });
354
467
  build.onLoad({ filter: /.*/, namespace: UNRESOLVED_NAMESPACE }, (args) => ({
355
468
  loader: "js",
356
469
  contents: `module.exports = {};
@@ -362,7 +475,6 @@ throw new Error(${JSON.stringify(`Failed to bundle ${configPath}: Could not reso
362
475
  const result = await bun.build({
363
476
  entrypoints: [configPath],
364
477
  target: "bun",
365
- external: ["effect", "mupdf", "fastembed", "onnxruntime-node", "markit-ai"],
366
478
  format: "esm",
367
479
  throw: false,
368
480
  packages: "bundle",
@@ -373,7 +485,7 @@ throw new Error(${JSON.stringify(`Failed to bundle ${configPath}: Could not reso
373
485
  `);
374
486
  throw new Error(`Failed to bundle ${configPath}: ${detail || "unknown bundler error"}`);
375
487
  }
376
- const bundleParentDir = join2(configDir, ".rig", "tmp");
488
+ const bundleParentDir = join2(configProjectRoot, ".rig", "tmp");
377
489
  mkdirSync(bundleParentDir, { recursive: true });
378
490
  const dir = mkdtempSync(join2(bundleParentDir, "rig-config-bundle-"));
379
491
  try {
@@ -151,26 +151,6 @@ function isTaskConfigEntry(value) {
151
151
  }
152
152
  return true;
153
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
154
  async function resolveTaskConfig(_projectRoot, _taskId) {
175
155
  const ctx = getContext();
176
156
  if (ctx) {
@@ -188,16 +168,6 @@ async function resolveTaskConfig(_projectRoot, _taskId) {
188
168
  }
189
169
  } catch {}
190
170
  }
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
171
  return {};
202
172
  }
203
173
  async function resolveTaskScopes(projectRoot, taskId) {
@@ -327,7 +297,7 @@ function block(hookName, message, projectRoot) {
327
297
  lines.push("");
328
298
  lines.push(`REPEATED VIOLATION (${count}x ${hookName}).`);
329
299
  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.");
300
+ lines.push("If stuck, record the failed approach in the task-state failure log and request help.");
331
301
  }
332
302
  writeSync(1, `${lines.join(`
333
303
  `)}
@@ -5,7 +5,6 @@ import { dirname as dirname2, resolve as resolve2 } from "path";
5
5
 
6
6
  // packages/core/src/layout.ts
7
7
  import {
8
- RIG_ARTIFACTS_DIRNAME,
9
8
  RIG_DEFINITION_DIRNAME,
10
9
  RIG_STATE_DIRNAME
11
10
  } from "@rig/contracts";