@rubytech/create-sitedesk-code 0.1.568 → 0.1.570
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 +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +7 -5
- package/payload/platform/plugins/admin/hooks/__tests__/pdf-text-layer-inject.test.sh +177 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-path-write-gate.test.sh +152 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-pdf-bash-gate.test.sh +95 -0
- package/payload/platform/plugins/admin/hooks/__tests__/quote-render-gate.test.sh +141 -45
- package/payload/platform/plugins/admin/hooks/__tests__/quote-render-pdf-conformance.test.sh +114 -0
- package/payload/platform/plugins/admin/hooks/pdf-text-layer-inject.sh +137 -0
- package/payload/platform/plugins/admin/hooks/quote-path-write-gate.sh +137 -0
- package/payload/platform/plugins/admin/hooks/quote-pdf-bash-gate.sh +70 -0
- package/payload/platform/plugins/admin/hooks/quote-render-gate.sh +105 -37
- package/payload/platform/plugins/admin/hooks/quote-render-pdf-conformance.sh +178 -0
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js +50 -4
- package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js.map +1 -1
- package/payload/platform/plugins/admin/skills/a4-print-documents/SKILL.md +12 -1
- package/payload/platform/plugins/admin/skills/a4-print-documents/pdf-inspect.mjs +113 -0
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +14 -0
- package/payload/platform/plugins/docs/references/admin-session.md +15 -0
- package/payload/platform/scripts/__tests__/mailbox-inject-registered.test.sh +19 -43
- package/payload/platform/scripts/__tests__/preference-hooks-registered.test.sh +3 -1
- package/payload/platform/scripts/__tests__/public-prompt-gate-registered.test.sh +22 -37
- package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +12 -35
- package/payload/platform/scripts/__tests__/quote-ownership-contract.test.sh +86 -0
- package/payload/platform/scripts/lib/__tests__/account-settings-reconcile.test.sh +73 -0
- package/payload/platform/scripts/lib/account-settings-reconcile.sh +88 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +11 -144
- package/payload/platform/scripts/setup-account.sh +11 -53
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts +20 -0
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js +78 -1
- package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.d.ts +129 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.js +344 -0
- package/payload/platform/services/claude-session-manager/dist/blocked-tool-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/index.js +107 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts +42 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js +215 -0
- package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts +108 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js +299 -0
- package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js.map +1 -0
- package/payload/platform/templates/account-settings.json +159 -0
- package/payload/premium-plugins/sitedesk/agents/sitedesk--quoter.md +2 -2
- package/payload/server/server.js +750 -656
- package/payload/platform/scripts/lib/__tests__/account-settings-askgate.test.sh +0 -144
- package/payload/platform/scripts/lib/__tests__/account-settings-mailbox-inject.test.sh +0 -166
- package/payload/platform/scripts/lib/__tests__/account-settings-pdf-conformance.test.sh +0 -151
- package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +0 -109
- package/payload/platform/scripts/lib/account-settings-askgate.sh +0 -98
- package/payload/platform/scripts/lib/account-settings-mailbox-inject.sh +0 -91
- package/payload/platform/scripts/lib/account-settings-pdf-conformance.sh +0 -98
- package/payload/platform/scripts/lib/account-settings-public-surface.sh +0 -109
package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.d.ts.map
ADDED
|
@@ -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
|
package/payload/platform/services/claude-session-manager/dist/specialist-preference-audit.js.map
ADDED
|
@@ -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,159 @@
|
|
|
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
|
+
"matcher": "Read",
|
|
133
|
+
"hooks": [
|
|
134
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/pdf-text-layer-inject.sh" }
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"UserPromptSubmit": [
|
|
139
|
+
{
|
|
140
|
+
"hooks": [
|
|
141
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
|
|
142
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/prompt-optimiser-directive.sh" },
|
|
143
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/datetime-inject.sh" },
|
|
144
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/mailbox-inject.sh" },
|
|
145
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/preference-consult-directive.sh" },
|
|
146
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" }
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
"Stop": [
|
|
151
|
+
{
|
|
152
|
+
"hooks": [
|
|
153
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/prompt-optimiser-compliance.sh" },
|
|
154
|
+
{ "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" }
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: quoter
|
|
3
|
-
description: "SiteDesk quoter. Delegate when the operator wants a priced quote for a job or enquiry, whether a new quote or a reprice/revision of an existing one — measuring quantities off a supplied drawing (PDF, photo, or scan) when one is given, then capturing or applying their own pricing and quotation method (items, quantity rules, pricing rules, roll-up, documents) to produce the live quote and its A4 PDF. Not for an interim valuation on a running job (that is the valuer) or a worker timesheet (that is the payroll-clerk)."
|
|
3
|
+
description: "SiteDesk quoter. Delegate when the operator wants a priced quote for a job or enquiry, whether a new quote or a reprice/revision of an existing one — measuring quantities off a supplied drawing (PDF, photo, or scan) when one is given, then capturing or applying their own pricing and quotation method (items, quantity rules, pricing rules, roll-up, documents) to produce the live quote and its A4 PDF. Not for an interim valuation on a running job (that is the valuer) or a worker timesheet (that is the payroll-clerk). The quoter owns the client quote document entire, figures and presentation alike, including layout, cover pages, photographs, the running header, and every later correction to an issued quote."
|
|
4
4
|
summary: "Your quoter — measures a drawing into quantities, then turns the operator's own pricing method into a live priced quote and its PDF, for a new quote or a reprice."
|
|
5
5
|
model: claude-sonnet-5
|
|
6
6
|
tools: Skill, Read, Write, Edit, Bash, Glob, Grep, mcp__plugin_sitedesk-job_sitedesk-job__quote-engine-run, mcp__plugin_sitedesk-job_sitedesk-job__quote-render, mcp__plugin_browser_browser__browser-navigate, mcp__plugin_browser_browser__browser-pdf-save, mcp__plugin_email_email__email-send
|
|
@@ -15,7 +15,7 @@ Never run uncommanded git writes. `git init`, `git commit`, `git add`, `git stas
|
|
|
15
15
|
|
|
16
16
|
A message from the agent that dispatched you arrives on the platform's own dispatcher channel, and it carries the same authority as the brief that dispatched you. Verify a figure or a fact against its source on disk, never against the messenger. If you still refuse, name the refusal and its reason in what you return, so the dispatcher relays it rather than guessing.
|
|
17
17
|
|
|
18
|
-
You are the SiteDesk quoter — the owner of quote work for an independent service business (a building contractor and the like): a new priced quote, and repricing or revising an existing one. You own one deliverable: a priced quote built from the operator's own method, rendered to an A4 PDF. A reprice re-runs the same method against the job's updated payload
|
|
18
|
+
You are the SiteDesk quoter — the owner of quote work for an independent service business (a building contractor and the like): a new priced quote, and repricing or revising an existing one. You own one deliverable: a priced quote built from the operator's own method, rendered to an A4 PDF. A reprice re-runs the same method against the job's updated payload. You own the client quote document entire, its figures and its presentation alike: layout, cover pages, photographs, the running header, and every later correction to any of them. No part of a client quote document is another agent's work, and a correction to an issued quote comes back to you. When the operator hands over a drawing rather than finished measurements, you measure it first with the `takeoff` skill, then price the quantities with `quotation`. The admin agent dispatches a brief to you; you run the skills and return the result.
|
|
19
19
|
|
|
20
20
|
The engine and render scripts run only through their tools. Price a job with the `quote-engine-run` tool, which runs the operator's persisted `quoting/engine.mjs` and files the figures; produce the documents with the `quote-render` tool, which runs the persisted `quoting/render.mjs` behind the reconcile, margin-leak and link-liveness gates. Never run `quoting/engine.mjs` or `quoting/render.mjs` directly with `Bash`; that skips the gates and files no receipt.
|
|
21
21
|
|