@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
@@ -70,151 +70,18 @@ provision_account_dir() {
70
70
  [ -d "$ACCOUNT_DIR/.git" ] || git init -q "$ACCOUNT_DIR"
71
71
 
72
72
  # --- project-level .claude/settings.json (hooks; no allowlist) -------------
73
+ # The hook set is data, not a heredoc: platform/templates/account-settings.json
74
+ # is copied verbatim (every $PLATFORM_ROOT in it is a literal Claude Code
75
+ # resolves at hook-run time, so no substitution is needed). Keeping it as a
76
+ # file is what lets account-settings-reconcile.sh converge accounts that
77
+ # already exist, which this writer alone never could — it runs at provision
78
+ # time, and the upgrade path re-provisions the house account and no other.
73
79
  local ACCOUNT_SETTINGS="$ACCOUNT_DIR/.claude/settings.json"
74
- local HOOKS_PATH="\$PLATFORM_ROOT/plugins/admin/hooks"
75
- cat > "$ACCOUNT_SETTINGS" << SETTINGS_EOF
76
- {
77
- "permissions": {
78
- "defaultMode": "bypassPermissions",
79
- "allow": [],
80
- "deny": []
81
- },
82
- "hooks": {
83
- "PreToolUse": [
84
- {
85
- "matcher": "Write",
86
- "hooks": [
87
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
88
- { "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
89
- ]
90
- },
91
- {
92
- "matcher": "Edit",
93
- "hooks": [
94
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
95
- { "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
96
- ]
97
- },
98
- {
99
- "matcher": "NotebookEdit",
100
- "hooks": [
101
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
102
- { "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard.sh" }
103
- ]
104
- },
105
- {
106
- "matcher": "Bash",
107
- "hooks": [
108
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
109
- { "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard-bash-pre.sh" },
110
- { "type": "command", "command": "bash $HOOKS_PATH/quote-engine-gate.sh" }
111
- ]
112
- },
113
- {
114
- "hooks": [
115
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
116
- { "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
117
- ]
118
- },
119
- {
120
- "matcher": "WebFetch",
121
- "hooks": [
122
- { "type": "command", "command": "node $HOOKS_PATH/webfetch-preflight.mjs" }
123
- ]
124
- },
125
- {
126
- "matcher": "AskUserQuestion",
127
- "hooks": [
128
- { "type": "command", "command": "bash $HOOKS_PATH/askuserquestion-investigate-gate.sh" },
129
- { "type": "command", "command": "bash $HOOKS_PATH/askuserquestion-channel-carrier-gate.sh" }
130
- ]
131
- },
132
- {
133
- "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
134
- "hooks": [
135
- { "type": "command", "command": "bash $HOOKS_PATH/quote-render-gate.sh" }
136
- ]
137
- },
138
- {
139
- "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
140
- "hooks": [
141
- { "type": "command", "command": "bash $HOOKS_PATH/preference-consult-gate.sh" }
142
- ]
143
- },
144
- {
145
- "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",
146
- "hooks": [
147
- { "type": "command", "command": "bash $HOOKS_PATH/preference-consult-gate.sh" }
148
- ]
149
- }
150
- ],
151
- "PostToolUse": [
152
- {
153
- "matcher": "Bash",
154
- "hooks": [
155
- { "type": "command", "command": "bash $HOOKS_PATH/fs-schema-guard-bash-post.sh" }
156
- ]
157
- },
158
- {
159
- "matcher": "Agent",
160
- "hooks": [
161
- { "type": "command", "command": "bash $HOOKS_PATH/post-tool-use-agent.sh" }
162
- ]
163
- },
164
- {
165
- "matcher": "mcp__plugin_browser_browser__browser-pdf-save",
166
- "hooks": [
167
- { "type": "command", "command": "bash $HOOKS_PATH/quote-render-pdf-conformance.sh" }
168
- ]
169
- },
170
- {
171
- "matcher": "mcp__.*__.*-(export|import)-parse$",
172
- "hooks": [
173
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" }
174
- ]
175
- },
176
- {
177
- "matcher": "mcp__.*",
178
- "hooks": [
179
- { "type": "command", "command": "bash $HOOKS_PATH/mcp-tool-missing.sh" }
180
- ]
181
- },
182
- {
183
- "matcher": "Write",
184
- "hooks": [
185
- { "type": "command", "command": "bash $HOOKS_PATH/admin-authoring-observer.sh" }
186
- ]
187
- },
188
- {
189
- "matcher": "Edit",
190
- "hooks": [
191
- { "type": "command", "command": "bash $HOOKS_PATH/admin-authoring-observer.sh" }
192
- ]
193
- }
194
- ],
195
- "UserPromptSubmit": [
196
- {
197
- "hooks": [
198
- { "type": "command", "command": "bash $HOOKS_PATH/archive-ingest-surface-gate.sh" },
199
- { "type": "command", "command": "bash $HOOKS_PATH/prompt-optimiser-directive.sh" },
200
- { "type": "command", "command": "bash $HOOKS_PATH/datetime-inject.sh" },
201
- { "type": "command", "command": "bash $HOOKS_PATH/mailbox-inject.sh" },
202
- { "type": "command", "command": "bash $HOOKS_PATH/preference-consult-directive.sh" },
203
- { "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
204
- ]
205
- }
206
- ],
207
- "Stop": [
208
- {
209
- "hooks": [
210
- { "type": "command", "command": "bash $HOOKS_PATH/prompt-optimiser-compliance.sh" },
211
- { "type": "command", "command": "bash $HOOKS_PATH/public-tool-surface.sh" }
212
- ]
213
- }
214
- ]
215
- }
216
- }
217
- SETTINGS_EOF
80
+ if [ -f "$TEMPLATES_DIR/account-settings.json" ]; then
81
+ cp "$TEMPLATES_DIR/account-settings.json" "$ACCOUNT_SETTINGS"
82
+ else
83
+ echo " [acct-settings] WARNING: template missing at $TEMPLATES_DIR/account-settings.json — settings.json not written" >&2
84
+ fi
218
85
 
219
86
  # --- agent identities + specialist plugin templates ------------------------
220
87
  cp "$TEMPLATES_DIR/agents/admin/IDENTITY.md" "$ACCOUNT_DIR/agents/admin/IDENTITY.md"
@@ -119,3 +119,16 @@ reconcile_all_accounts_mailbox_inject "$ACCOUNTS_DIR"
119
119
  # under a one-tool allowlist. Reconcile every account on every install.
120
120
  # Idempotent; logs one [backfill-2339] line per account.
121
121
  reconcile_all_accounts_public_surface "$ACCOUNTS_DIR"
122
+
123
+ # ------------------------------------------------------------------
124
+ # 8. Converge the whole hook set on every account
125
+ # ------------------------------------------------------------------
126
+ # Steps 3 to 7 each retrofit one hook, and each was written after that hook was
127
+ # found missing on a live account. provision_account_dir writes the full set,
128
+ # but only at provision time, and this script re-provisions the house account
129
+ # and no other — so every future hook repeats the same fault. This step
130
+ # converges each account's settings against the shipped template instead, and
131
+ # states the divergence count on every run including zero. A hook added to
132
+ # platform/templates/account-settings.json needs no backfill of its own.
133
+ . "$SCRIPT_DIR/lib/account-settings-reconcile.sh"
134
+ reconcile_all_accounts_settings "$ACCOUNTS_DIR"
@@ -10,6 +10,26 @@
10
10
  * into `op=account-agent-registry error`. Exported for its own unit test: the
11
11
  * propagation half cannot be provoked through the filesystem from outside. */
12
12
  export declare function ignoringRaceWith(code: 'EEXIST' | 'ENOENT', act: () => void): void;
13
+ /** What the CLI will be able to dispatch from the registry we just wrote.
14
+ *
15
+ * Task 2469 — the mirror is keyed on filename and dispatch is keyed on the
16
+ * frontmatter `name`, so `synced=<N>` cannot answer "can this be reached?".
17
+ * A card with no name, and two cards claiming one name, both mirror cleanly
18
+ * and neither dispatches; a specialist that is never dispatched never fails,
19
+ * so no transition log anywhere carries it. Only a state reconcile sees it.
20
+ *
21
+ * Measured over the registry rather than the source directory, because the
22
+ * registry is the directory the CLI reads: where an operator's own regular
23
+ * file sits at a card's name, that file is what resolves, and it is that file
24
+ * this must report on.
25
+ *
26
+ * Exported for its own unit test and for callers that want the state without
27
+ * re-running a sync. */
28
+ export declare function resolveRegistryNames(registryDir: string): {
29
+ resolvable: number;
30
+ unnamed: string[];
31
+ dupeNames: string[];
32
+ };
13
33
  /** Mirror `<accountDir>/specialists/agents/*.md` into
14
34
  * `<accountDir>/.claude/agents/` as symlinks, and remove every registry
15
35
  * symlink the source no longer has. Emits exactly one line:
@@ -1 +1 @@
1
- {"version":3,"file":"account-agent-registry.d.ts","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;+EAU+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,IAAI,CAOjF;AAED;;;;+EAI+E;AAC/E,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAmF9F"}
1
+ {"version":3,"file":"account-agent-registry.d.ts","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"AA6BA;;;;;;;;;;+EAU+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,IAAI,CAOjF;AA6BD;;;;;;;;;;;;;;yBAcyB;AACzB,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG;IACzD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB,CAsBA;AAED;;;;+EAI+E;AAC/E,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAgG9F"}
@@ -23,7 +23,7 @@
23
23
  // It never throws. A registry that cannot be written is a specialist that
24
24
  // cannot be dispatched, which is the state before this module existed; a spawn
25
25
  // that dies instead is strictly worse.
26
- import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, symlinkSync, unlinkSync } from 'node:fs';
26
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, readlinkSync, symlinkSync, unlinkSync } from 'node:fs';
27
27
  import { dirname, join, resolve } from 'node:path';
28
28
  /** Two spawns in the same account sync concurrently — an admin session and a
29
29
  * channel session are routine — and they write identical content. Whoever
@@ -46,6 +46,72 @@ export function ignoringRaceWith(code, act) {
46
46
  throw err;
47
47
  }
48
48
  }
49
+ /** The `name:` value from a card's frontmatter, or null. CRLF-tolerant and
50
+ * quote-stripping, matching the reader in `specialist-roster.ts` and the one
51
+ * in the roster census, so every surface agrees on what a card is called. A
52
+ * card that cannot be read — a dangling link, a directory at a `.md` path,
53
+ * EACCES — yields null rather than throwing, because "we could not tell" and
54
+ * "it does not resolve" are the same answer to the dispatcher. */
55
+ function readFrontmatterName(file) {
56
+ let raw;
57
+ try {
58
+ raw = readFileSync(file, 'utf8');
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
64
+ if (!fm)
65
+ return null;
66
+ const m = fm[1].match(/^name:\s*(.*?)\r?$/m);
67
+ if (!m)
68
+ return null;
69
+ let value = m[1].trim();
70
+ if ((value.startsWith('"') && value.endsWith('"')) ||
71
+ (value.startsWith("'") && value.endsWith("'"))) {
72
+ value = value.slice(1, -1);
73
+ }
74
+ return value || null;
75
+ }
76
+ /** What the CLI will be able to dispatch from the registry we just wrote.
77
+ *
78
+ * Task 2469 — the mirror is keyed on filename and dispatch is keyed on the
79
+ * frontmatter `name`, so `synced=<N>` cannot answer "can this be reached?".
80
+ * A card with no name, and two cards claiming one name, both mirror cleanly
81
+ * and neither dispatches; a specialist that is never dispatched never fails,
82
+ * so no transition log anywhere carries it. Only a state reconcile sees it.
83
+ *
84
+ * Measured over the registry rather than the source directory, because the
85
+ * registry is the directory the CLI reads: where an operator's own regular
86
+ * file sits at a card's name, that file is what resolves, and it is that file
87
+ * this must report on.
88
+ *
89
+ * Exported for its own unit test and for callers that want the state without
90
+ * re-running a sync. */
91
+ export function resolveRegistryNames(registryDir) {
92
+ let entries;
93
+ try {
94
+ entries = readdirSync(registryDir).filter((n) => n.endsWith('.md')).sort();
95
+ }
96
+ catch {
97
+ return { resolvable: 0, unnamed: [], dupeNames: [] };
98
+ }
99
+ const claims = new Map();
100
+ const unnamed = [];
101
+ for (const file of entries) {
102
+ const name = readFrontmatterName(join(registryDir, file));
103
+ if (name === null) {
104
+ unnamed.push(file);
105
+ continue;
106
+ }
107
+ claims.set(name, (claims.get(name) ?? 0) + 1);
108
+ }
109
+ const dupeNames = Array.from(claims.entries())
110
+ .filter(([, n]) => n > 1)
111
+ .map(([name]) => name)
112
+ .sort();
113
+ return { resolvable: claims.size, unnamed, dupeNames };
114
+ }
49
115
  /** Mirror `<accountDir>/specialists/agents/*.md` into
50
116
  * `<accountDir>/.claude/agents/` as symlinks, and remove every registry
51
117
  * symlink the source no longer has. Emits exactly one line:
@@ -138,6 +204,17 @@ export function syncAccountAgentRegistry(accountDir, log) {
138
204
  pruned++;
139
205
  }
140
206
  log(`op=account-agent-registry synced=${synced} pruned=${pruned} collisions=${collisions.join(',')}`);
207
+ // Task 2469 — a second line, not three more fields on the first. That one
208
+ // is a transition record: what this spawn changed. This is a state
209
+ // reconcile: what is reachable now. Emitted every spawn including zero, so
210
+ // an account with no specialists is distinguishable from a reconcile that
211
+ // did not run. On the error path below it is deliberately absent — after a
212
+ // failed sync the reachable set is unknown, and reporting zero would assert
213
+ // something this never measured.
214
+ const resolution = resolveRegistryNames(registryDir);
215
+ log(`op=agent-registry-resolution resolvable=${resolution.resolvable}` +
216
+ ` unnamed=${resolution.unnamed.join(',')}` +
217
+ ` dupeNames=${resolution.dupeNames.join(',')}`);
141
218
  }
142
219
  catch (err) {
143
220
  log(`op=account-agent-registry error reason=${err instanceof Error ? err.message : String(err)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"account-agent-registry.js","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"account-agent-registry.js","sourceRoot":"","sources":["../src/account-agent-registry.ts"],"names":[],"mappings":"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"}
@@ -48,9 +48,11 @@ import { createPassiveIntakeAudit } from './passive-intake-audit.js';
48
48
  import { createPassiveDispatchPrune } from './passive-dispatch-prune.js';
49
49
  import { createXacctCensus } from './cross-account-census.js';
50
50
  import { createAccountDirSchemaReconcile } from './account-dir-schema-reconcile.js';
51
+ import { createQuoteDeliveryReconcile } from './quote-delivery-reconcile.js';
51
52
  import { createSessionCapAudit } from './session-cap-audit.js';
52
53
  import { createSkillStalenessAudit, collectPlatformSkillMtimes, collectPremiumSkillMtimes, resolveEnabledPlugins, buildLiveSessionRefs, parseProcStartMs, } from './skill-staleness-audit.js';
53
54
  import { createPublicSurfaceAudit, parseMcpLogServerName } from './public-surface-audit.js';
55
+ import { createSpecialistPreferenceAudit, readLinesSync } from './specialist-preference-audit.js';
54
56
  import { projectsDirForCwd, sessionsDir, jsonlPathForSessionId, slugForExistingJsonl, jsonlPathForSlug, sidecarPathForSlug } from './jsonl-path.js';
55
57
  import { readSidecar } from './session-sidecar.js';
56
58
  import { runSystemPromptSelfTest, runIdentityDriftAssertion, runIdentityForbiddenTokenCheck } from './system-prompt.js';
@@ -885,6 +887,76 @@ async function main() {
885
887
  },
886
888
  });
887
889
  publicSurfaceAudit.start();
890
+ // Task 2469 — the second question about a specialist. The registry reconcile
891
+ // beside the spawn answers whether one CAN be reached; this answers whether
892
+ // it WAS. Both were needed: four authored clerks owned the works orders,
893
+ // invoices and client emails on a live account while content-producer
894
+ // produced all of them, and every reachability signal read green throughout.
895
+ //
896
+ // `<projectDir>/<sessionId>/subagents/` is the only surface that ties a write
897
+ // to a specialist — the parent transcript carries none of a subagent's tool
898
+ // calls — so the walk is over that directory across every account on the
899
+ // install. 300s rather than the 60s beside it: this reads transcripts, and
900
+ // the mtime guard means a steady state costs one stat per file.
901
+ const preferenceProjectsRoot = dirname(projectsDirForCwd(config.spawnCwd));
902
+ /** sessionId -> its `subagents/` directory, rebuilt by `listSessions` at the
903
+ * top of every tick. Held here rather than in the audit because resolving a
904
+ * session id to a path is install layout, which is this file's business. */
905
+ const subagentDirs = new Map();
906
+ const specialistPreferenceAudit = createSpecialistPreferenceAudit({
907
+ intervalMs: 300_000,
908
+ logger: log,
909
+ listSessions: () => {
910
+ subagentDirs.clear();
911
+ let accountProjectDirs;
912
+ try {
913
+ accountProjectDirs = readdirSync(preferenceProjectsRoot);
914
+ }
915
+ catch {
916
+ return [];
917
+ }
918
+ for (const projectDir of accountProjectDirs) {
919
+ const abs = join(preferenceProjectsRoot, projectDir);
920
+ let sessions;
921
+ try {
922
+ sessions = readdirSync(abs);
923
+ }
924
+ catch {
925
+ continue;
926
+ }
927
+ for (const sessionId of sessions) {
928
+ const dir = join(abs, sessionId, 'subagents');
929
+ if (existsSync(dir))
930
+ subagentDirs.set(sessionId, dir);
931
+ }
932
+ }
933
+ return Array.from(subagentDirs.keys());
934
+ },
935
+ listTranscripts: (sessionId) => {
936
+ const dir = subagentDirs.get(sessionId);
937
+ if (!dir)
938
+ return [];
939
+ // A throw here is caught by the audit, which names the session rather
940
+ // than losing the whole run to one unreadable directory.
941
+ return readdirSync(dir)
942
+ .filter((f) => f.startsWith('agent-') && f.endsWith('.jsonl'))
943
+ .map((f) => ({
944
+ jsonl: join(dir, f),
945
+ meta: join(dir, `${f.slice(0, -'.jsonl'.length)}.meta.json`),
946
+ mtimeMs: statSync(join(dir, f)).mtimeMs,
947
+ }));
948
+ },
949
+ readMeta: (path) => {
950
+ try {
951
+ return readFileSync(path, 'utf8');
952
+ }
953
+ catch {
954
+ return null;
955
+ }
956
+ },
957
+ readLines: (path) => readLinesSync(path),
958
+ });
959
+ specialistPreferenceAudit.start();
888
960
  // Task 2285 — standing audit for public-agent knowledge curation. A
889
961
  // `knowledgeKeywords` subscription nobody asked for is dormant until matching
890
962
  // content lands, and a KNOWLEDGE.md that grows after deployment emits nothing
@@ -1053,6 +1125,21 @@ async function main() {
1053
1125
  intervalMs: 300_000,
1054
1126
  });
1055
1127
  schemaReconcile.start();
1128
+ // Task 2467 — standing reconcile of delivered client quotes against their
1129
+ // render receipts. The three PreToolUse quote gates refuse the print, the
1130
+ // Bash conversion and the write, but all three fail open on an uninspectable
1131
+ // envelope and none can see a delivery route nobody enumerated. This pass is
1132
+ // the backstop, and it is the only instrument that can see the failure at
1133
+ // all: on 2026-08-05 a hand-authored client quote was printed and emailed
1134
+ // while the bypass counter for that day sat at zero, so no transition log
1135
+ // could have shown it. Emits one line per unreconciled document plus one
1136
+ // summary per run, zero count included. Purely filesystem — no Neo4j.
1137
+ const quoteReconcile = createQuoteDeliveryReconcile({
1138
+ accountsDir: dirname(config.accountDir),
1139
+ logger: log,
1140
+ intervalMs: 900_000,
1141
+ });
1142
+ quoteReconcile.start();
1056
1143
  // Task 183 — recorder JSONL tail. Posts [recorder-session-init] and
1057
1144
  // [recorder-turn] lines for every database-operator specialist spawn,
1058
1145
  // routed through the platform UI's /api/admin/log-ingest loopback