@rubytech/create-maxy-code 0.1.568 → 0.1.569

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/PLUGIN.md +4 -2
  3. package/payload/platform/plugins/admin/hooks/__tests__/quote-path-write-gate.test.sh +152 -0
  4. package/payload/platform/plugins/admin/hooks/__tests__/quote-pdf-bash-gate.test.sh +95 -0
  5. package/payload/platform/plugins/admin/hooks/__tests__/quote-render-gate.test.sh +141 -45
  6. package/payload/platform/plugins/admin/hooks/__tests__/quote-render-pdf-conformance.test.sh +114 -0
  7. package/payload/platform/plugins/admin/hooks/quote-path-write-gate.sh +137 -0
  8. package/payload/platform/plugins/admin/hooks/quote-pdf-bash-gate.sh +70 -0
  9. package/payload/platform/plugins/admin/hooks/quote-render-gate.sh +105 -37
  10. package/payload/platform/plugins/admin/hooks/quote-render-pdf-conformance.sh +178 -0
  11. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.d.ts.map +1 -1
  12. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js +50 -4
  13. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js.map +1 -1
  14. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +8 -0
  15. package/payload/platform/scripts/__tests__/mailbox-inject-registered.test.sh +5 -5
  16. package/payload/platform/scripts/__tests__/preference-hooks-registered.test.sh +3 -1
  17. package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +5 -5
  18. package/payload/platform/scripts/__tests__/quote-ownership-contract.test.sh +86 -0
  19. package/payload/platform/scripts/lib/__tests__/account-settings-reconcile.test.sh +73 -0
  20. package/payload/platform/scripts/lib/account-settings-reconcile.sh +88 -0
  21. package/payload/platform/scripts/lib/provision-account-dir.sh +11 -144
  22. package/payload/platform/scripts/setup-account.sh +13 -0
  23. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts +20 -0
  24. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js +78 -1
  26. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js.map +1 -1
  27. package/payload/platform/services/claude-session-manager/dist/index.js +87 -0
  28. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  29. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts +42 -0
  30. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts.map +1 -0
  31. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js +215 -0
  32. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js.map +1 -0
  33. package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts +108 -0
  34. package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts.map +1 -0
  35. package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js +299 -0
  36. package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js.map +1 -0
  37. package/payload/platform/templates/account-settings.json +153 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialist-preference-audit.d.ts","sourceRoot":"","sources":["../src/specialist-preference-audit.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAE3C;;;;;;;0BAO0B;AAC1B,wBAAiB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAkBpF;AAID;;;;;;;;;;;kCAWkC;AAClC,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAKzE,CAAA;AAED;;;mEAGmE;AACnE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS5D;AAED;;yCAEyC;AACzC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CASrE;AAED;;iEAEiE;AACjE,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB7D;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,QAAQ,EAAE,CAAA;CACtB;AAED;;;;;;eAMe;AACf,wBAAgB,eAAe,CAAC,CAAC,EAAE;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;CACxB,GAAG,eAAe,CAmBlB;AAED;sDACsD;AACtD,wBAAgB,uBAAuB,CAAC,CAAC,EAAE;IACzC,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,MAAM,CAKT;AAED;;;;;;;0DAO0D;AAC1D,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAGlD;AAED,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,YAAY,IAAI,SAAS,MAAM,EAAE,CAAA;IACjC;oFACgF;IAChF,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,aAAa,EAAE,CAAA;IAC5D,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACrC;sCACkC;IAClC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;CAC1C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,QAAQ,IAAI,IAAI,CAAA;CACjB;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,6BAA6B,GAClC,yBAAyB,CAyG3B"}
@@ -0,0 +1,299 @@
1
+ // Task 2469 — a specialist that CAN be reached is not a specialist that WAS.
2
+ //
3
+ // The registry reconcile in account-agent-registry.ts answers the first
4
+ // question and emits `op=agent-registry-resolution`. It was green on the
5
+ // account that filed this, and would have stayed green through the whole
6
+ // incident, because every clerk was reachable and none was reached: four
7
+ // authored clerks owned the works orders, invoices and client emails while
8
+ // content-producer produced all of them. The two questions are deliberately
9
+ // separate signals, because one cannot answer the other.
10
+ //
11
+ // Keyed on the written path rather than on the dispatch prose. A dispatch
12
+ // description is the model's own account of what it is doing, and the incident
13
+ // this closes had twelve descriptions that each read as reasonable. A path is
14
+ // a fact, and it is the same fact a write gate enforces on, so enforcement and
15
+ // audit cannot drift apart.
16
+ //
17
+ // The input is `<projectDir>/<sessionId>/subagents/agent-<agentId>.jsonl` with
18
+ // its sibling `.meta.json`. That directory is the ONLY surface that ties a
19
+ // write to a specialist: the parent transcript records every record as
20
+ // `isSidechain: false`, carries none of the subagent's tool calls, and its
21
+ // `toolUseResult.toolStats` gives aggregate counts with no paths.
22
+ //
23
+ // Shape mirrors public-surface-audit.ts: PURE parsers, selector and formatters
24
+ // plus an impure factory whose setInterval is unref'd and whose readers are
25
+ // injected.
26
+ import { closeSync, openSync, readSync } from 'node:fs';
27
+ import { StringDecoder } from 'node:string_decoder';
28
+ const TAG = '[specialist-preference]';
29
+ /** Lines of a file, read in bounded chunks rather than into one string.
30
+ *
31
+ * One session's `subagents/` directory measured 473 MB, so reading a
32
+ * transcript with `readFileSync` would put the whole thing on the heap to look
33
+ * at one field per line. A `StringDecoder` carries partial multi-byte
34
+ * characters across chunk boundaries: splitting one would corrupt the line,
35
+ * `JSON.parse` would reject it, and the write it carried would vanish from
36
+ * the audit silently. */
37
+ export function* readLinesSync(path, chunkBytes = 1 << 20) {
38
+ const fd = openSync(path, 'r');
39
+ try {
40
+ const buf = Buffer.allocUnsafe(chunkBytes);
41
+ const decoder = new StringDecoder('utf8');
42
+ let carry = '';
43
+ for (;;) {
44
+ const n = readSync(fd, buf, 0, chunkBytes, null);
45
+ if (n === 0)
46
+ break;
47
+ const parts = (carry + decoder.write(buf.subarray(0, n))).split('\n');
48
+ carry = parts.pop() ?? '';
49
+ for (const p of parts)
50
+ if (p.length > 0)
51
+ yield p;
52
+ }
53
+ carry += decoder.end();
54
+ if (carry.length > 0)
55
+ yield carry;
56
+ }
57
+ finally {
58
+ closeSync(fd);
59
+ }
60
+ }
61
+ const WRITE_TOOLS = new Set(['Write', 'Edit', 'MultiEdit', 'NotebookEdit']);
62
+ /** Artefact directory to the specialist that owns it.
63
+ *
64
+ * Every entry is a directory measured in the live job tree: `quote` (17 jobs),
65
+ * `Quotations` (5), `orders` (8), `invoices` (1). There is no valuation
66
+ * directory anywhere in that tree, so valuation-clerk deliberately has no
67
+ * entry — a guessed owner produces misroute lines nobody can act on.
68
+ *
69
+ * Two exclusions are deliberate. `pricing/` holds the internal priced
70
+ * breakdown rather than a client-facing artefact. `Suppliers Invoices` is the
71
+ * supplier's invoice to the business, not the client invoice the
72
+ * invoice-clerk issues, and the match is exact-segment so it cannot be swept
73
+ * in by the `invoices` entry. */
74
+ export const OWNED_PATHS = [
75
+ { segment: 'quote', owner: 'sitedesk:quoter' },
76
+ { segment: 'Quotations', owner: 'sitedesk:quoter' },
77
+ { segment: 'orders', owner: 'order-clerk' },
78
+ { segment: 'invoices', owner: 'invoice-clerk' },
79
+ ];
80
+ /** The specialist that owns a written path, or null when the path is not an
81
+ * owned artefact. Anchored on `jobs/<jobId>/<segment>/`, so a same-named
82
+ * directory elsewhere in the account is not swept in and a file sitting
83
+ * directly in a job directory belongs to nobody in particular. */
84
+ export function ownerForPath(filePath) {
85
+ const seg = filePath.split('/');
86
+ for (let i = 0; i + 3 < seg.length; i++) {
87
+ if (seg[i] !== 'jobs')
88
+ continue;
89
+ const bucket = seg[i + 2];
90
+ const hit = OWNED_PATHS.find((o) => o.segment === bucket);
91
+ if (hit)
92
+ return hit.owner;
93
+ }
94
+ return null;
95
+ }
96
+ /** `agentType` from a subagent's sibling meta file, or null when the file is
97
+ * unreadable, unparseable, or carries no type. Null is never read as
98
+ * compliance: see `auditTranscript`. */
99
+ export function parseAgentType(metaJson) {
100
+ if (metaJson === null)
101
+ return null;
102
+ try {
103
+ const d = JSON.parse(metaJson);
104
+ const t = d?.agentType;
105
+ return typeof t === 'string' && t.length > 0 ? t : null;
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ /** Written paths in one transcript line. A line that will not parse yields
112
+ * nothing rather than throwing: the corpus carries partial trailing writes,
113
+ * and one bad line must not abort the transcript it sits in. */
114
+ export function selectWrites(transcriptLine) {
115
+ let d;
116
+ try {
117
+ d = JSON.parse(transcriptLine);
118
+ }
119
+ catch {
120
+ return [];
121
+ }
122
+ const content = d?.message?.content;
123
+ if (!Array.isArray(content))
124
+ return [];
125
+ const out = [];
126
+ for (const b of content) {
127
+ if (!b || typeof b !== 'object')
128
+ continue;
129
+ const blk = b;
130
+ if (blk.type !== 'tool_use')
131
+ continue;
132
+ if (typeof blk.name !== 'string' || !WRITE_TOOLS.has(blk.name))
133
+ continue;
134
+ const fp = blk.input?.file_path;
135
+ if (typeof fp === 'string' && fp.length > 0)
136
+ out.push(fp);
137
+ }
138
+ return out;
139
+ }
140
+ /** One subagent run.
141
+ *
142
+ * `agentType` null means the meta file was missing or unreadable. Its
143
+ * owned-path writes are counted as unattributed rather than as compliant:
144
+ * "we could not tell who wrote this" is not "the right specialist wrote it",
145
+ * and folding the two together is how a broken reader reads as a clean
146
+ * account. */
147
+ export function auditTranscript(p) {
148
+ let ownedPathWrites = 0;
149
+ let unattributed = 0;
150
+ const misroutes = [];
151
+ for (const line of p.lines) {
152
+ for (const path of selectWrites(line)) {
153
+ const owner = ownerForPath(path);
154
+ if (owner === null)
155
+ continue;
156
+ ownedPathWrites++;
157
+ if (p.agentType === null) {
158
+ unattributed++;
159
+ continue;
160
+ }
161
+ if (p.agentType !== owner) {
162
+ misroutes.push({ session: p.session, agent: p.agentType, owner, path });
163
+ }
164
+ }
165
+ }
166
+ return { ownedPathWrites, unattributed, misroutes };
167
+ }
168
+ /** The every-tick line. Emitted including zero, so a run that found nothing is
169
+ * distinguishable from a run that did not happen. */
170
+ export function formatPreferenceSummary(p) {
171
+ return `${TAG} op=audit sessionsScanned=${p.sessionsScanned}` +
172
+ ` transcriptsScanned=${p.transcriptsScanned}` +
173
+ ` ownedPathWrites=${p.ownedPathWrites}` +
174
+ ` misrouted=${p.misrouted} unattributed=${p.unattributed}`;
175
+ }
176
+ /** One line per misroute, naming the subagent, the owner it displaced and the
177
+ * path. The displaced owner is the actionable half: "content-producer wrote
178
+ * this" says less than "content-producer wrote this instead of the quoter".
179
+ *
180
+ * The path is JSON-quoted because these paths contain spaces — the document
181
+ * that prompted this task is `Q 1879 - Woolgrove School - Yellow Class
182
+ * Kitchenette.html` — and a bare value would split into four tokens under any
183
+ * `key=value` reader, including `grep -o 'path=\S*'`. */
184
+ export function formatMisroute(p) {
185
+ return `${TAG} op=misroute session=${p.session} agent=${p.agent}` +
186
+ ` owner=${p.owner} path=${JSON.stringify(p.path)}`;
187
+ }
188
+ export function createSpecialistPreferenceAudit(deps) {
189
+ /** jsonl path -> the result of reading it at `mtimeMs`.
190
+ *
191
+ * The emitted counts are a STATE — the totals across every transcript
192
+ * currently known — not a per-tick delta. A transcript still being appended
193
+ * to is re-read when its mtime moves and its entry is REPLACED, so its
194
+ * earlier writes are counted once, not once per tick. A delta counter over
195
+ * a growing file would inflate every total it reported. */
196
+ const seen = new Map();
197
+ /** Misroutes already named, so a steady state does not re-log every tick. */
198
+ const logged = new Set();
199
+ let timer = null;
200
+ function tickOnce() {
201
+ let sessionsScanned = 0;
202
+ const live = new Set();
203
+ for (const session of deps.listSessions()) {
204
+ sessionsScanned++;
205
+ let transcripts;
206
+ try {
207
+ transcripts = deps.listTranscripts(session);
208
+ }
209
+ catch (err) {
210
+ // A directory that cannot be listed is named and skipped. Silence here
211
+ // would read as a session with no subagent activity, which is the one
212
+ // reading this audit must never produce by accident.
213
+ deps.logger(`${TAG} op=session-unreadable session=${session}` +
214
+ ` reason=${err instanceof Error ? err.message : String(err)}`);
215
+ continue;
216
+ }
217
+ for (const t of transcripts) {
218
+ live.add(t.jsonl);
219
+ const prior = seen.get(t.jsonl);
220
+ if (prior && prior.mtimeMs === t.mtimeMs)
221
+ continue;
222
+ const agentType = parseAgentType(deps.readMeta(t.meta));
223
+ let audit;
224
+ try {
225
+ audit = auditTranscript({ session, agentType, lines: deps.readLines(t.jsonl) });
226
+ }
227
+ catch (err) {
228
+ deps.logger(`${TAG} op=transcript-unreadable path=${t.jsonl}` +
229
+ ` reason=${err instanceof Error ? err.message : String(err)}`);
230
+ continue;
231
+ }
232
+ seen.set(t.jsonl, { mtimeMs: t.mtimeMs, audit });
233
+ for (const m of audit.misroutes) {
234
+ const key = `${m.session}|${m.agent}|${m.path}`;
235
+ if (logged.has(key))
236
+ continue;
237
+ deps.logger(formatMisroute(m));
238
+ logged.add(key);
239
+ }
240
+ }
241
+ }
242
+ // Drop transcripts that have gone, so the totals describe what is on disk
243
+ // now rather than accumulating across the process's whole lifetime. The
244
+ // logged-misroute keys go with them: this process runs for weeks, and a set
245
+ // that only ever grew would hold every path of every session the install
246
+ // has ever archived.
247
+ for (const path of Array.from(seen.keys()))
248
+ if (!live.has(path))
249
+ seen.delete(path);
250
+ const liveKeys = new Set();
251
+ for (const { audit } of seen.values()) {
252
+ for (const m of audit.misroutes)
253
+ liveKeys.add(`${m.session}|${m.agent}|${m.path}`);
254
+ }
255
+ for (const key of Array.from(logged))
256
+ if (!liveKeys.has(key))
257
+ logged.delete(key);
258
+ let ownedPathWrites = 0;
259
+ let misrouted = 0;
260
+ let unattributed = 0;
261
+ for (const { audit } of seen.values()) {
262
+ ownedPathWrites += audit.ownedPathWrites;
263
+ misrouted += audit.misroutes.length;
264
+ unattributed += audit.unattributed;
265
+ }
266
+ deps.logger(formatPreferenceSummary({
267
+ sessionsScanned,
268
+ transcriptsScanned: seen.size,
269
+ ownedPathWrites,
270
+ misrouted,
271
+ unattributed,
272
+ }));
273
+ }
274
+ return {
275
+ tickOnce,
276
+ start() {
277
+ if (timer)
278
+ return;
279
+ timer = setInterval(() => {
280
+ try {
281
+ tickOnce();
282
+ }
283
+ catch (err) {
284
+ deps.logger(`${TAG} op=audit-tick-failed message=${err instanceof Error ? err.message : String(err)}`);
285
+ }
286
+ }, deps.intervalMs);
287
+ if (typeof timer.unref === 'function')
288
+ timer.unref();
289
+ deps.logger(`${TAG} op=audit-started intervalMs=${deps.intervalMs}`);
290
+ },
291
+ stop() {
292
+ if (timer) {
293
+ clearInterval(timer);
294
+ timer = null;
295
+ }
296
+ },
297
+ };
298
+ }
299
+ //# sourceMappingURL=specialist-preference-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialist-preference-audit.js","sourceRoot":"","sources":["../src/specialist-preference-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ {
2
+ "permissions": {
3
+ "defaultMode": "bypassPermissions",
4
+ "allow": [],
5
+ "deny": []
6
+ },
7
+ "hooks": {
8
+ "PreToolUse": [
9
+ {
10
+ "matcher": "Write",
11
+ "hooks": [
12
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
13
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard.sh" },
14
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" }
15
+ ]
16
+ },
17
+ {
18
+ "matcher": "Edit",
19
+ "hooks": [
20
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
21
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard.sh" },
22
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" }
23
+ ]
24
+ },
25
+ {
26
+ "matcher": "MultiEdit",
27
+ "hooks": [
28
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
29
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard.sh" },
30
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" }
31
+ ]
32
+ },
33
+ {
34
+ "matcher": "NotebookEdit",
35
+ "hooks": [
36
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
37
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard.sh" },
38
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" }
39
+ ]
40
+ },
41
+ {
42
+ "matcher": "Bash",
43
+ "hooks": [
44
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
45
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard-bash-pre.sh" },
46
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-engine-gate.sh" },
47
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-pdf-bash-gate.sh" }
48
+ ]
49
+ },
50
+ {
51
+ "hooks": [
52
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
53
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" }
54
+ ]
55
+ },
56
+ {
57
+ "matcher": "WebFetch",
58
+ "hooks": [
59
+ { "type": "command", "command": "node $PLATFORM_ROOT/plugins/admin/hooks/webfetch-preflight.mjs" }
60
+ ]
61
+ },
62
+ {
63
+ "matcher": "AskUserQuestion",
64
+ "hooks": [
65
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/askuserquestion-investigate-gate.sh" },
66
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/askuserquestion-channel-carrier-gate.sh" }
67
+ ]
68
+ },
69
+ {
70
+ "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
71
+ "hooks": [
72
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-render-gate.sh" }
73
+ ]
74
+ },
75
+ {
76
+ "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
77
+ "hooks": [
78
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/preference-consult-gate.sh" }
79
+ ]
80
+ },
81
+ {
82
+ "matcher": "mcp__plugin_email_email__email-send|mcp__plugin_email_email__email-reply|mcp__plugin_email_email__email-draft-send|mcp__plugin_outlook_outlook__outlook-mail-send|mcp__plugin_outlook_outlook__outlook-mail-reply|mcp__plugin_outlook_outlook__outlook-draft-send|SendUserFile",
83
+ "hooks": [
84
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/preference-consult-gate.sh" }
85
+ ]
86
+ }
87
+ ],
88
+ "PostToolUse": [
89
+ {
90
+ "matcher": "Bash",
91
+ "hooks": [
92
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/fs-schema-guard-bash-post.sh" }
93
+ ]
94
+ },
95
+ {
96
+ "matcher": "Agent",
97
+ "hooks": [
98
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/post-tool-use-agent.sh" }
99
+ ]
100
+ },
101
+ {
102
+ "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
103
+ "hooks": [
104
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-render-pdf-conformance.sh" }
105
+ ]
106
+ },
107
+ {
108
+ "matcher": "mcp__.*__.*-(export|import)-parse$",
109
+ "hooks": [
110
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" }
111
+ ]
112
+ },
113
+ {
114
+ "matcher": "mcp__.*",
115
+ "hooks": [
116
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/mcp-tool-missing.sh" }
117
+ ]
118
+ },
119
+ {
120
+ "matcher": "Write",
121
+ "hooks": [
122
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/admin-authoring-observer.sh" }
123
+ ]
124
+ },
125
+ {
126
+ "matcher": "Edit",
127
+ "hooks": [
128
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/admin-authoring-observer.sh" }
129
+ ]
130
+ }
131
+ ],
132
+ "UserPromptSubmit": [
133
+ {
134
+ "hooks": [
135
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
136
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/prompt-optimiser-directive.sh" },
137
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/datetime-inject.sh" },
138
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/mailbox-inject.sh" },
139
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/preference-consult-directive.sh" },
140
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" }
141
+ ]
142
+ }
143
+ ],
144
+ "Stop": [
145
+ {
146
+ "hooks": [
147
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/prompt-optimiser-compliance.sh" },
148
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" }
149
+ ]
150
+ }
151
+ ]
152
+ }
153
+ }