@webpieces/ai-hook-rules 0.4.710 → 0.4.712
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/package.json +2 -2
- package/src/adapters/detect-ai.d.ts +5 -4
- package/src/adapters/detect-ai.js +5 -4
- package/src/adapters/detect-ai.js.map +1 -1
- package/src/adapters/hook-core.js +9 -3
- package/src/adapters/hook-core.js.map +1 -1
- package/src/bin/codex-guard-presence.d.ts +86 -0
- package/src/bin/codex-guard-presence.js +150 -0
- package/src/bin/codex-guard-presence.js.map +1 -0
- package/src/bin/codex-trust.d.ts +99 -0
- package/src/bin/codex-trust.js +199 -0
- package/src/bin/codex-trust.js.map +1 -0
- package/src/bin/hook-registration.d.ts +200 -43
- package/src/bin/hook-registration.js +218 -89
- package/src/bin/hook-registration.js.map +1 -1
- package/src/bin/l0-allowlist.d.ts +0 -30
- package/src/bin/l0-allowlist.js +9 -67
- package/src/bin/l0-allowlist.js.map +1 -1
- package/src/bin/l0-decide.d.ts +43 -0
- package/src/bin/l0-decide.js +90 -0
- package/src/bin/l0-decide.js.map +1 -0
- package/src/bin/l0-ignored-tools.d.ts +38 -0
- package/src/bin/l0-ignored-tools.js +44 -0
- package/src/bin/l0-ignored-tools.js.map +1 -0
- package/src/bin/setup-config.d.ts +19 -0
- package/src/bin/setup-config.js +370 -0
- package/src/bin/setup-config.js.map +1 -0
- package/src/bin/setup.d.ts +56 -21
- package/src/bin/setup.js +125 -370
- package/src/bin/setup.js.map +1 -1
- package/src/bin/shim-audit-log.js +10 -1
- package/src/bin/shim-audit-log.js.map +1 -1
- package/src/bin/shim-deny-reason.js +4 -4
- package/src/bin/shim-deny-reason.js.map +1 -1
- package/src/bin/shim.d.ts +2 -0
- package/src/bin/shim.js +21 -1
- package/src/bin/shim.js.map +1 -1
- package/src/bin/upgrade-shim.d.ts +1 -1
- package/src/bin/upgrade-shim.js +12 -8
- package/src/bin/upgrade-shim.js.map +1 -1
- package/src/core/agent-event.d.ts +16 -0
- package/src/core/agent-event.js +17 -1
- package/src/core/agent-event.js.map +1 -1
- package/src/core/ai-type-context.d.ts +36 -0
- package/src/core/ai-type-context.js +45 -0
- package/src/core/ai-type-context.js.map +1 -0
- package/src/core/decision-log.js +9 -0
- package/src/core/decision-log.js.map +1 -1
- package/src/core/l0-matrix.js +14 -6
- package/src/core/l0-matrix.js.map +1 -1
- package/src/core/l0-tooling-doc.d.ts +3 -2
- package/src/core/l0-tooling-doc.js +22 -10
- package/src/core/l0-tooling-doc.js.map +1 -1
- package/src/core/rejection-log.js +5 -1
- package/src/core/rejection-log.js.map +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.js +4 -1
- package/src/index.js.map +1 -1
- package/templates/ai-hook.sh +15 -1
|
@@ -1,10 +1,19 @@
|
|
|
1
|
+
import { AiType } from '../core/agent-event';
|
|
1
2
|
/**
|
|
2
|
-
* THE INSTALLED HOOK SURFACE — two hooks,
|
|
3
|
+
* THE INSTALLED HOOK SURFACE — two hooks per harness, all ABSOLUTE, and the ONE place their spelling is
|
|
4
|
+
* defined. See `HarnessRegistration` below, which is what makes "per harness" data rather than four
|
|
5
|
+
* module constants that were only ever true of Claude Code.
|
|
3
6
|
*
|
|
4
7
|
* ─── ONE GOVERNOR: the MAIN tree judges every tree ─────────────────────────────────────────────────
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
9
|
+
* Claude Code — .claude/settings.json
|
|
10
|
+
* H1 sh "$CLAUDE_PROJECT_DIR/.claude/webpieces/ai-hook.sh" wp-ai-guards-hook Write|…|Bash|Read
|
|
11
|
+
* H2 sh "$CLAUDE_PROJECT_DIR/.claude/webpieces/ai-hook.sh" wp-ai-rules-hook Write|Edit|MultiEdit
|
|
12
|
+
* Codex — .codex/hooks.json (the SAME `hooks.PreToolUse` JSON shape, measured)
|
|
13
|
+
* H1 sh "$PWD/.claude/webpieces/ai-hook.sh" wp-ai-guards-hook Bash|apply_patch
|
|
14
|
+
* H2 sh "$PWD/.claude/webpieces/ai-hook.sh" wp-ai-rules-hook apply_patch
|
|
15
|
+
*
|
|
16
|
+
* ONE shim file serves all four: `.claude/` there is a path, not a claim about who is calling.
|
|
8
17
|
*
|
|
9
18
|
* This REPLACES a three-hook form in which these two were RELATIVE (`sh ".claude/webpieces/ai-hook.sh"`)
|
|
10
19
|
* and a third hook, L-1 `guarantee-root.sh`, existed solely to guarantee that relative path resolved.
|
|
@@ -81,6 +90,12 @@ export interface HookEntry {
|
|
|
81
90
|
matcher: string;
|
|
82
91
|
hooks: HookCommand[];
|
|
83
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* One settings file as webpieces reads it. MEASURED: Codex's `.codex/hooks.json` uses the IDENTICAL
|
|
95
|
+
* `hooks.PreToolUse[].hooks[].command` shape, so one reader, one writer and one repair serve both files
|
|
96
|
+
* — the difference between the harnesses is entirely in the VALUES (matcher, shim anchor), which is what
|
|
97
|
+
* `HarnessRegistration` carries. The `env` block below is Claude Code's alone.
|
|
98
|
+
*/
|
|
84
99
|
export interface ClaudeSettings {
|
|
85
100
|
hooks?: {
|
|
86
101
|
PreToolUse?: HookEntry[];
|
|
@@ -90,34 +105,147 @@ export interface ClaudeSettings {
|
|
|
90
105
|
}
|
|
91
106
|
export declare const RULES_BIN = "wp-ai-rules-hook";
|
|
92
107
|
export declare const GUARDS_BIN = "wp-ai-guards-hook";
|
|
93
|
-
export declare const RULES_MATCHER = "Write|Edit|MultiEdit";
|
|
94
|
-
export declare const GUARDS_MATCHER = "Write|Edit|MultiEdit|Bash|Read";
|
|
95
108
|
/**
|
|
96
|
-
*
|
|
109
|
+
* ONE HARNESS'S registration surface — where its hooks live, what they match, and how they name the
|
|
110
|
+
* shim. Data-only → a class, per CLAUDE.md.
|
|
97
111
|
*
|
|
98
|
-
*
|
|
112
|
+
* ─── Why this exists ──────────────────────────────────────────────────────────────────────────────
|
|
113
|
+
* The matchers and the shim command used to be four module constants written for Claude Code alone.
|
|
114
|
+
* Applied to Codex they are wrong in both halves, and the way they are wrong is SILENT:
|
|
99
115
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* prescription, and a measured hard deadlock where L-1 told a worktree-isolated agent to `cd` to the
|
|
108
|
-
* primary clone — which the harness refuses for an isolated agent.
|
|
116
|
+
* - MATCHER. Codex's file-editing tool is `apply_patch` (MEASURED, codex-cli 0.151.0). A matcher of
|
|
117
|
+
* `Write|Edit|MultiEdit` matches it never, so every file rule is unreachable while the settings file
|
|
118
|
+
* looks perfectly installed. Its shell tool IS called `Bash` — Codex reuses Claude's name — which is
|
|
119
|
+
* the trap: half the matcher works, so the hooks appear to be running.
|
|
120
|
+
* - ANCHOR. `$CLAUDE_PROJECT_DIR` does not exist in a Codex hook's environment (measured: 46 vars, no
|
|
121
|
+
* such key), so the command expands to `sh "/.claude/webpieces/ai-hook.sh"`, which dies — and per the
|
|
122
|
+
* hooks protocol a non-2 non-zero exit is a NON-BLOCKING error, i.e. a silent unguarded allow.
|
|
109
123
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
124
|
+
* Both halves of that were live in real repos, written by a Codex Desktop sync that transliterated the
|
|
125
|
+
* Claude setup. Making the registration per-harness DATA is what stops a future harness inheriting a
|
|
126
|
+
* matcher that was never true for it.
|
|
113
127
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
128
|
+
* ─── ONE SHIM, both harnesses ─────────────────────────────────────────────────────────────────────
|
|
129
|
+
* `SHIM_MARKER` is shared deliberately: `.claude/webpieces/ai-hook.sh` is the single fail-closed entry
|
|
130
|
+
* point, and moving or duplicating it would double the L0 allowlist regexes, the drift surfaces and the
|
|
131
|
+
* cures. The `.claude/` prefix is a path, not a claim about which agent is calling.
|
|
117
132
|
*/
|
|
118
|
-
export declare
|
|
119
|
-
|
|
120
|
-
|
|
133
|
+
export declare class HarnessRegistration {
|
|
134
|
+
readonly aiType: AiType;
|
|
135
|
+
/** How the installer and the drift report name this harness to a human. */
|
|
136
|
+
readonly label: string;
|
|
137
|
+
/** Which tool names the RULES hook (code-style, file-scoped) must see. */
|
|
138
|
+
readonly rulesMatcher: string;
|
|
139
|
+
/**
|
|
140
|
+
* Which tool names the GUARDS hook must see. Wider than the rules matcher by the shell tool and,
|
|
141
|
+
* for Claude Code, by `Read` — Read carries no guard, but the guards hook owns the
|
|
142
|
+
* per-invocation audit log, so matching it records every file the AI opens (log-and-allow fast
|
|
143
|
+
* path in hook-core.ts; a Read is never blocked). Codex has no Read tool at all: a read arrives
|
|
144
|
+
* as `Bash` running a pager, which the shell matcher already covers and read-parity synthesizes.
|
|
145
|
+
*/
|
|
146
|
+
readonly guardsMatcher: string;
|
|
147
|
+
/** The settings files this harness's hooks can be installed into, relative to the repo root. */
|
|
148
|
+
readonly settingsFiles: readonly string[];
|
|
149
|
+
/**
|
|
150
|
+
* THE PREFIX THE SHIM PATH IS ANCHORED ON, and the reason each harness needs its own.
|
|
151
|
+
*
|
|
152
|
+
* **BYTE-STABILITY IS A HARD CONSTRAINT ON THE CODEX VALUE.** Codex trusts a hook entry
|
|
153
|
+
* TOFU — `~/.codex/config.toml` records a `trusted_hash` per entry — so ANY change to these bytes
|
|
154
|
+
* invalidates that trust and re-prompts the human, whose third option is `Continue without
|
|
155
|
+
* trusting (hooks won't run)`: one keystroke to a silently unguarded session. Changing this
|
|
156
|
+
* string is therefore never a cosmetic edit. The hash is NOT reproducible from outside Codex
|
|
157
|
+
* (16 encodings tried against a file we authored), so the installer can never repair trust for
|
|
158
|
+
* itself — see ./codex-trust.ts, which REPORTS and never writes.
|
|
159
|
+
*/
|
|
160
|
+
readonly shimAnchor: string;
|
|
161
|
+
/**
|
|
162
|
+
* True when this harness's settings file also carries the managed `env` block. Claude Code's
|
|
163
|
+
* settings `env` is inherited by every subagent, which is what makes it the right home for the
|
|
164
|
+
* Bash-cwd pin (see managed-env.ts). Codex has no equivalent surface — and needs none: its cwd
|
|
165
|
+
* is MEASURED not to drift at all (`cd x && pwd` prints x, the next call is back at the repo
|
|
166
|
+
* root, for the coordinator and for subagents alike).
|
|
167
|
+
*/
|
|
168
|
+
readonly managesEnv: boolean;
|
|
169
|
+
/** What `managedSurfaceDrift()` calls this harness's registration when it has moved. */
|
|
170
|
+
readonly registrationSurface: string;
|
|
171
|
+
constructor(aiType: AiType,
|
|
172
|
+
/** How the installer and the drift report name this harness to a human. */
|
|
173
|
+
label: string,
|
|
174
|
+
/** Which tool names the RULES hook (code-style, file-scoped) must see. */
|
|
175
|
+
rulesMatcher: string,
|
|
176
|
+
/**
|
|
177
|
+
* Which tool names the GUARDS hook must see. Wider than the rules matcher by the shell tool and,
|
|
178
|
+
* for Claude Code, by `Read` — Read carries no guard, but the guards hook owns the
|
|
179
|
+
* per-invocation audit log, so matching it records every file the AI opens (log-and-allow fast
|
|
180
|
+
* path in hook-core.ts; a Read is never blocked). Codex has no Read tool at all: a read arrives
|
|
181
|
+
* as `Bash` running a pager, which the shell matcher already covers and read-parity synthesizes.
|
|
182
|
+
*/
|
|
183
|
+
guardsMatcher: string,
|
|
184
|
+
/** The settings files this harness's hooks can be installed into, relative to the repo root. */
|
|
185
|
+
settingsFiles: readonly string[],
|
|
186
|
+
/**
|
|
187
|
+
* THE PREFIX THE SHIM PATH IS ANCHORED ON, and the reason each harness needs its own.
|
|
188
|
+
*
|
|
189
|
+
* **BYTE-STABILITY IS A HARD CONSTRAINT ON THE CODEX VALUE.** Codex trusts a hook entry
|
|
190
|
+
* TOFU — `~/.codex/config.toml` records a `trusted_hash` per entry — so ANY change to these bytes
|
|
191
|
+
* invalidates that trust and re-prompts the human, whose third option is `Continue without
|
|
192
|
+
* trusting (hooks won't run)`: one keystroke to a silently unguarded session. Changing this
|
|
193
|
+
* string is therefore never a cosmetic edit. The hash is NOT reproducible from outside Codex
|
|
194
|
+
* (16 encodings tried against a file we authored), so the installer can never repair trust for
|
|
195
|
+
* itself — see ./codex-trust.ts, which REPORTS and never writes.
|
|
196
|
+
*/
|
|
197
|
+
shimAnchor: string,
|
|
198
|
+
/**
|
|
199
|
+
* True when this harness's settings file also carries the managed `env` block. Claude Code's
|
|
200
|
+
* settings `env` is inherited by every subagent, which is what makes it the right home for the
|
|
201
|
+
* Bash-cwd pin (see managed-env.ts). Codex has no equivalent surface — and needs none: its cwd
|
|
202
|
+
* is MEASURED not to drift at all (`cd x && pwd` prints x, the next call is back at the repo
|
|
203
|
+
* root, for the coordinator and for subagents alike).
|
|
204
|
+
*/
|
|
205
|
+
managesEnv: boolean,
|
|
206
|
+
/** What `managedSurfaceDrift()` calls this harness's registration when it has moved. */
|
|
207
|
+
registrationSurface: string);
|
|
208
|
+
/** Which matcher one guard bin registers under. */
|
|
209
|
+
matcherFor(bin: string): string;
|
|
210
|
+
/**
|
|
211
|
+
* The guard-hook command — `sh "<anchor>/.claude/webpieces/ai-hook.sh" <bin>`.
|
|
212
|
+
*
|
|
213
|
+
* ABSOLUTE, in both harnesses. Claude's anchor replaced a RELATIVE spelling and that reversal is
|
|
214
|
+
* documented at length in this file's header: relative resolves only at a tree root, a hook that
|
|
215
|
+
* cannot resolve exits 127, and per the hooks reference that is a NON-BLOCKING error — a silent
|
|
216
|
+
* unguarded allow. It also cost an entire guard layer (L-1) whose only job was to police the `cd`
|
|
217
|
+
* that made the relative path resolvable.
|
|
218
|
+
*
|
|
219
|
+
* Invoked via `sh <file>` rather than executed directly so a missing executable bit on the
|
|
220
|
+
* checked-in shim (fresh clone, a filesystem that drops the bit, git core.fileMode quirks) can never
|
|
221
|
+
* break the hook with a raw `Permission denied` on every tool call. Quoted to survive spaces.
|
|
222
|
+
*/
|
|
223
|
+
shimCommand(bin: string): string;
|
|
224
|
+
/** The registration entry for one guard bin under this harness. */
|
|
225
|
+
entryFor(bin: string): HookRegistrationEntry;
|
|
226
|
+
/** This harness's settings files under one repo root, absolute. */
|
|
227
|
+
settingsPaths(projectRoot: string): readonly string[];
|
|
228
|
+
}
|
|
229
|
+
export declare const CLAUDE_REGISTRATION: HarnessRegistration;
|
|
230
|
+
/**
|
|
231
|
+
* Codex's registration, every value of it MEASURED against codex-cli 0.151.0 rather than assumed.
|
|
232
|
+
*
|
|
233
|
+
* `$PWD` is the anchor because there is no project-dir variable to use and none is needed: the payload
|
|
234
|
+
* `cwd` and the hook process's own `PWD` are both the repo root on EVERY call — for the coordinator and
|
|
235
|
+
* for subagents — and a `cd` inside one command never survives into the next. That was measured, not
|
|
236
|
+
* hoped for, and it is the same effect Claude Code gets from the managed
|
|
237
|
+
* `CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR` env entry. See `shimAnchor` for why these exact bytes are
|
|
238
|
+
* not free to change.
|
|
239
|
+
*/
|
|
240
|
+
export declare const CODEX_REGISTRATION: HarnessRegistration;
|
|
241
|
+
/**
|
|
242
|
+
* Every harness webpieces arms, in installer order.
|
|
243
|
+
*
|
|
244
|
+
* The drift check, the repair and the installer all iterate THIS, so a harness cannot be armed by the
|
|
245
|
+
* installer and then left unvalidated — which is exactly the state `.codex/hooks.json` was in before it
|
|
246
|
+
* was a managed surface: written by something else, silently wrong, and invisible to every check.
|
|
247
|
+
*/
|
|
248
|
+
export declare const HARNESS_REGISTRATIONS: readonly HarnessRegistration[];
|
|
121
249
|
/**
|
|
122
250
|
* True when this PreToolUse command is one webpieces owns — in ANY spelling it has ever shipped.
|
|
123
251
|
*
|
|
@@ -145,7 +273,7 @@ export declare function registeredBins(settings: ClaudeSettings): readonly strin
|
|
|
145
273
|
* whenever the GUARDS bin was present; it is retired, and a settings file still carrying it is STALE —
|
|
146
274
|
* `repairRegistration()` removes it via isManagedCommand()'s legacy marker.
|
|
147
275
|
*/
|
|
148
|
-
export declare function expectedEntries(bins: readonly string[]): readonly HookRegistrationEntry[];
|
|
276
|
+
export declare function expectedEntries(harness: HarnessRegistration, bins: readonly string[]): readonly HookRegistrationEntry[];
|
|
149
277
|
/**
|
|
150
278
|
* True when a settings file registers webpieces hooks in a shape this release does not expect: a
|
|
151
279
|
* RELATIVE shim command, a leftover guarantee-root entry, a stray duplicate, or a wrong matcher.
|
|
@@ -153,7 +281,7 @@ export declare function expectedEntries(bins: readonly string[]): readonly HookR
|
|
|
153
281
|
* Compared as a SET, not a sequence: Claude Code runs all matching hooks in parallel, so array order
|
|
154
282
|
* carries no meaning and reordering must not read as drift.
|
|
155
283
|
*/
|
|
156
|
-
export declare function registrationStale(settings: ClaudeSettings): boolean;
|
|
284
|
+
export declare function registrationStale(harness: HarnessRegistration, settings: ClaudeSettings): boolean;
|
|
157
285
|
/** Drop every webpieces-managed PreToolUse command; returns true if anything was removed. */
|
|
158
286
|
export declare function dropManagedEntries(settings: ClaudeSettings): boolean;
|
|
159
287
|
/** Append one PreToolUse entry. */
|
|
@@ -199,14 +327,28 @@ export declare function applyManagedEnv(settings: ClaudeSettings): boolean;
|
|
|
199
327
|
* have been reported as drifted by fault S and then left unrepaired by its own prescribed cure. A cure
|
|
200
328
|
* that skips half the surface is the failure mode `upgrade-shim.ts`'s header exists to prevent.
|
|
201
329
|
*/
|
|
202
|
-
export declare function repairRegistration(settings: ClaudeSettings): boolean;
|
|
203
|
-
/** The two project settings files the installer can write. */
|
|
204
|
-
export declare function projectSettingsPaths(projectRoot: string): readonly string[];
|
|
330
|
+
export declare function repairRegistration(harness: HarnessRegistration, settings: ClaudeSettings): boolean;
|
|
205
331
|
export declare function readSettings(settingsPath: string): ClaudeSettings;
|
|
206
332
|
export declare function writeSettings(settingsPath: string, settings: ClaudeSettings): void;
|
|
207
|
-
/**
|
|
208
|
-
|
|
209
|
-
|
|
333
|
+
/**
|
|
334
|
+
* True when any settings file ONE HARNESS owns under `root` carries a stale registration.
|
|
335
|
+
*
|
|
336
|
+
* Per harness, not per repo, so the drift report can NAME which one moved — `.claude/settings.json` and
|
|
337
|
+
* `.codex/hooks.json` have different cures, and a fault that says only "the registration is stale" sends
|
|
338
|
+
* the reader to the wrong file half the time.
|
|
339
|
+
*
|
|
340
|
+
* A file that does not exist, or exists and registers no webpieces hooks, is never judged (see
|
|
341
|
+
* `registrationStale`). That is what keeps a repo which has never armed Codex from suddenly faulting on
|
|
342
|
+
* a `.codex/hooks.json` it does not have.
|
|
343
|
+
*/
|
|
344
|
+
export declare function registrationStaleAt(harness: HarnessRegistration, root: string | null): boolean;
|
|
345
|
+
/**
|
|
346
|
+
* True when either Claude project settings file under `root` is missing the managed `env` entry.
|
|
347
|
+
*
|
|
348
|
+
* CLAUDE-ONLY by construction, and stated as such rather than looped over the harnesses: `env` is a
|
|
349
|
+
* Claude Code settings surface, Codex has no equivalent, and Codex's cwd is measured not to drift, which
|
|
350
|
+
* is the whole thing the entry is for. See HarnessRegistration.managesEnv.
|
|
351
|
+
*/
|
|
210
352
|
export declare function envStaleAt(root: string | null): boolean;
|
|
211
353
|
/**
|
|
212
354
|
* WHAT was rewritten in ONE settings file. Data-only → a class, per CLAUDE.md.
|
|
@@ -221,24 +363,39 @@ export declare class SettingsRepair {
|
|
|
221
363
|
readonly env: boolean;
|
|
222
364
|
constructor(settingsPath: string, registration: boolean, env: boolean);
|
|
223
365
|
}
|
|
224
|
-
/**
|
|
366
|
+
/**
|
|
367
|
+
* Rewrite every stale settings file under `root`, for EVERY harness; returns what changed, per file.
|
|
368
|
+
*
|
|
369
|
+
* Existing files only — this never CREATES a registration. Arming a harness is the installer's decision
|
|
370
|
+
* (`wp-install-ai-hooks`); this is the cure for one that has already been armed and has drifted, so a
|
|
371
|
+
* repo that has never armed Codex is left exactly as it was.
|
|
372
|
+
*/
|
|
225
373
|
export declare function repairRegistrationAt(root: string): readonly SettingsRepair[];
|
|
226
374
|
/**
|
|
227
|
-
* The
|
|
375
|
+
* The names the drift check reports, so a deny can say WHICH surface moved.
|
|
376
|
+
*
|
|
377
|
+
* There were four, then three, and there are now FOUR again — but the fourth is not the one that was
|
|
378
|
+
* deleted. `GUARANTEE_ROOT_SURFACE` went with L-1 itself: an absolutely-registered shim resolves from
|
|
379
|
+
* any cwd, so there is no launch guarantee left to police and no second .sh file to keep byte-locked. A
|
|
380
|
+
* settings file still carrying the retired H1 entry is not its own surface — it is ordinary REGISTRATION
|
|
381
|
+
* drift, which `registrationStaleAt()` reports and `repairRegistration()` fixes by removing it.
|
|
382
|
+
*
|
|
383
|
+
* The new fourth is `.codex/hooks.json`, and it is here because of what happened while it was NOT a
|
|
384
|
+
* managed surface: something else wrote it, with a matcher that matched no Codex file tool and a shim
|
|
385
|
+
* path anchored on a variable Codex does not set, and no check in this package could see it. A file the
|
|
386
|
+
* guards depend on and nothing validates is the exact shape of that incident.
|
|
228
387
|
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* byte-locked. A settings file still carrying the retired H1 entry is not its own surface any more —
|
|
232
|
-
* it is ordinary REGISTRATION drift, which `registrationStaleAt()` already reports and
|
|
233
|
-
* `repairRegistration()` already fixes by removing it.
|
|
388
|
+
* Each harness's registration surface is its own name, from HarnessRegistration.registrationSurface, so
|
|
389
|
+
* the deny sends the reader to the file that actually moved.
|
|
234
390
|
*/
|
|
235
391
|
export declare const SHIM_SURFACE = ".claude/webpieces/ai-hook.sh";
|
|
236
|
-
export declare const REGISTRATION_SURFACE
|
|
392
|
+
export declare const REGISTRATION_SURFACE: string;
|
|
393
|
+
export declare const CODEX_REGISTRATION_SURFACE: string;
|
|
237
394
|
export declare const ENV_SURFACE = ".claude/settings.json env.CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR";
|
|
238
395
|
/**
|
|
239
|
-
* WHICH of the
|
|
396
|
+
* WHICH of the managed surfaces disagree with this release — the input to fault S.
|
|
240
397
|
*
|
|
241
|
-
* All
|
|
398
|
+
* All of them are checked against the SAME root, resolved from the RUNNING MODULE (governingShimRoot),
|
|
242
399
|
* never from cwd and never from `$CLAUDE_PROJECT_DIR`: the files we compare and the renderers we
|
|
243
400
|
* compare them TO must come from one install, or the check straddles two trees and can never converge.
|
|
244
401
|
*/
|