@rubytech/create-sitedesk-code 0.1.573 → 0.1.574

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 (129) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/admins-write/__tests__/index.test.ts +97 -0
  3. package/payload/platform/lib/admins-write/dist/index.d.ts +12 -0
  4. package/payload/platform/lib/admins-write/dist/index.d.ts.map +1 -1
  5. package/payload/platform/lib/admins-write/dist/index.js +27 -5
  6. package/payload/platform/lib/admins-write/dist/index.js.map +1 -1
  7. package/payload/platform/lib/admins-write/src/index.ts +35 -5
  8. package/payload/platform/lib/admins-write/vitest.config.ts +14 -0
  9. package/payload/platform/lib/dispatch-read/dist/session.d.ts.map +1 -1
  10. package/payload/platform/lib/dispatch-read/dist/session.js +19 -4
  11. package/payload/platform/lib/dispatch-read/dist/session.js.map +1 -1
  12. package/payload/platform/lib/dispatch-read/src/__tests__/session.test.ts +91 -0
  13. package/payload/platform/lib/dispatch-read/src/session.ts +25 -6
  14. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  15. package/payload/platform/plugins/admin/PLUGIN.md +8 -3
  16. package/payload/platform/plugins/admin/hooks/__tests__/html-structure-gate.test.sh +264 -0
  17. package/payload/platform/plugins/admin/hooks/__tests__/quote-render-pdf-conformance.test.sh +122 -24
  18. package/payload/platform/plugins/admin/hooks/__tests__/specialist-dispatch-gate.test.sh +158 -0
  19. package/payload/platform/plugins/admin/hooks/html-structure-gate.sh +165 -0
  20. package/payload/platform/plugins/admin/hooks/quote-render-pdf-conformance.sh +111 -19
  21. package/payload/platform/plugins/admin/hooks/specialist-dispatch-gate.sh +159 -0
  22. package/payload/platform/plugins/admin/mcp/dist/admin-bind-classify.d.ts +27 -0
  23. package/payload/platform/plugins/admin/mcp/dist/admin-bind-classify.d.ts.map +1 -0
  24. package/payload/platform/plugins/admin/mcp/dist/admin-bind-classify.js +29 -0
  25. package/payload/platform/plugins/admin/mcp/dist/admin-bind-classify.js.map +1 -0
  26. package/payload/platform/plugins/admin/mcp/dist/binding-validate.d.ts +11 -0
  27. package/payload/platform/plugins/admin/mcp/dist/binding-validate.d.ts.map +1 -0
  28. package/payload/platform/plugins/admin/mcp/dist/binding-validate.js +20 -0
  29. package/payload/platform/plugins/admin/mcp/dist/binding-validate.js.map +1 -0
  30. package/payload/platform/plugins/admin/mcp/dist/index.js +133 -1
  31. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  32. package/payload/platform/plugins/admin/skills/admin-user-management/SKILL.md +32 -2
  33. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +157 -46
  34. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +8 -0
  35. package/payload/platform/plugins/docs/references/admin-ui.md +71 -31
  36. package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +38 -13
  37. package/payload/platform/plugins/docs/references/internals.md +6 -0
  38. package/payload/platform/plugins/docs/references/outlook-guide.md +31 -1
  39. package/payload/platform/plugins/docs/references/troubleshooting.md +10 -0
  40. package/payload/platform/plugins/outlook/PLUGIN.md +3 -1
  41. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger-write-sites.test.d.ts +2 -0
  42. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger-write-sites.test.d.ts.map +1 -0
  43. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger-write-sites.test.js +177 -0
  44. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger-write-sites.test.js.map +1 -0
  45. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger.test.d.ts +2 -0
  46. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger.test.d.ts.map +1 -0
  47. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger.test.js +130 -0
  48. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-ledger.test.js.map +1 -0
  49. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-reconcile.test.d.ts +2 -0
  50. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-reconcile.test.d.ts.map +1 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-reconcile.test.js +162 -0
  52. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-reconcile.test.js.map +1 -0
  53. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-state-fields.test.d.ts +2 -0
  54. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-state-fields.test.d.ts.map +1 -0
  55. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-state-fields.test.js +168 -0
  56. package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-state-fields.test.js.map +1 -0
  57. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-ledger.d.ts +64 -0
  58. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-ledger.d.ts.map +1 -0
  59. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-ledger.js +110 -0
  60. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-ledger.js.map +1 -0
  61. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-reconcile.d.ts +119 -0
  62. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-reconcile.d.ts.map +1 -0
  63. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-reconcile.js +0 -0
  64. package/payload/platform/plugins/outlook/mcp/dist/lib/draft-reconcile.js.map +1 -0
  65. package/payload/platform/plugins/outlook/mcp/dist/scripts/draft-reconcile.d.ts +8 -0
  66. package/payload/platform/plugins/outlook/mcp/dist/scripts/draft-reconcile.d.ts.map +1 -0
  67. package/payload/platform/plugins/outlook/mcp/dist/scripts/draft-reconcile.js +247 -0
  68. package/payload/platform/plugins/outlook/mcp/dist/scripts/draft-reconcile.js.map +1 -0
  69. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.d.ts.map +1 -1
  70. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.js +10 -0
  71. package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.js.map +1 -1
  72. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
  73. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +21 -0
  74. package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
  75. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.d.ts +16 -0
  76. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.d.ts.map +1 -1
  77. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js +5 -1
  78. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-fetch-body.js.map +1 -1
  79. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +4 -0
  80. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -1
  81. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +2 -1
  82. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -1
  83. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.d.ts.map +1 -1
  84. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js +24 -0
  85. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-reply.js.map +1 -1
  86. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -1
  87. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +2 -1
  88. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -1
  89. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts.map +1 -1
  90. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js +29 -0
  91. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js.map +1 -1
  92. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/draft-reconcile-throttle.test.d.ts +2 -0
  93. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/draft-reconcile-throttle.test.d.ts.map +1 -0
  94. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/draft-reconcile-throttle.test.js +21 -0
  95. package/payload/platform/plugins/scheduling/mcp/dist/__tests__/draft-reconcile-throttle.test.js.map +1 -0
  96. package/payload/platform/plugins/scheduling/mcp/dist/lib/draft-reconcile-throttle.d.ts +13 -0
  97. package/payload/platform/plugins/scheduling/mcp/dist/lib/draft-reconcile-throttle.d.ts.map +1 -0
  98. package/payload/platform/plugins/scheduling/mcp/dist/lib/draft-reconcile-throttle.js +10 -0
  99. package/payload/platform/plugins/scheduling/mcp/dist/lib/draft-reconcile-throttle.js.map +1 -0
  100. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +54 -0
  101. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  102. package/payload/platform/services/claude-session-manager/dist/authored-specialist-tools.d.ts +32 -0
  103. package/payload/platform/services/claude-session-manager/dist/authored-specialist-tools.d.ts.map +1 -0
  104. package/payload/platform/services/claude-session-manager/dist/authored-specialist-tools.js +144 -0
  105. package/payload/platform/services/claude-session-manager/dist/authored-specialist-tools.js.map +1 -0
  106. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  107. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  108. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  109. package/payload/platform/services/claude-session-manager/dist/html-structure-census.d.ts +44 -0
  110. package/payload/platform/services/claude-session-manager/dist/html-structure-census.d.ts.map +1 -0
  111. package/payload/platform/services/claude-session-manager/dist/html-structure-census.js +185 -0
  112. package/payload/platform/services/claude-session-manager/dist/html-structure-census.js.map +1 -0
  113. package/payload/platform/services/claude-session-manager/dist/index.js +125 -0
  114. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  115. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.d.ts.map +1 -1
  116. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js +7 -0
  117. package/payload/platform/services/claude-session-manager/dist/quote-delivery-reconcile.js.map +1 -1
  118. package/payload/platform/services/claude-session-manager/dist/quote-print-census.d.ts +42 -0
  119. package/payload/platform/services/claude-session-manager/dist/quote-print-census.d.ts.map +1 -0
  120. package/payload/platform/services/claude-session-manager/dist/quote-print-census.js +254 -0
  121. package/payload/platform/services/claude-session-manager/dist/quote-print-census.js.map +1 -0
  122. package/payload/platform/services/claude-session-manager/dist/specialist-census.d.ts +92 -0
  123. package/payload/platform/services/claude-session-manager/dist/specialist-census.d.ts.map +1 -0
  124. package/payload/platform/services/claude-session-manager/dist/specialist-census.js +227 -0
  125. package/payload/platform/services/claude-session-manager/dist/specialist-census.js.map +1 -0
  126. package/payload/platform/templates/account-settings.json +8 -4
  127. package/payload/premium-plugins/sitedesk/plugins/sitedesk-job/skills/quotation/references/quote-generation.md +23 -4
  128. package/payload/server/public/operator.html +1 -1
  129. package/payload/server/server.js +465 -361
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quote-print-census.js","sourceRoot":"","sources":["../src/quote-print-census.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ export declare const WINDOW_MS: number;
2
+ export type Logger = (line: string) => void;
3
+ export interface TranscriptEvent {
4
+ /** Epoch ms from the record's own `timestamp`, so the window is per-record
5
+ * rather than per-file. A transcript appended to over days holds events on
6
+ * both sides of the boundary. */
7
+ ts: number;
8
+ kind: 'dispatch' | 'bypass';
9
+ /** Dispatch: the `tool_use` id, resolved to an agent type later. Bypass: the
10
+ * tool name. */
11
+ key: string;
12
+ }
13
+ /** Dispatches and gated calls in one transcript.
14
+ *
15
+ * The input is the PARENT session transcript, which is the main conversation by
16
+ * construction: Task 2469 measured all 41,456 records of one parent as
17
+ * `isSidechain: false`, carrying none of a subagent's tool calls. So a
18
+ * specialist's own use of its own tool can never be counted as a bypass here.
19
+ *
20
+ * A line that will not parse yields nothing rather than throwing: the corpus
21
+ * carries partial trailing writes, and one bad line must not abort the
22
+ * transcript it sits in.
23
+ *
24
+ * A dispatch with no `tool_use` id is skipped rather than counted: it cannot be
25
+ * attributed to a specialist, and an unattributable dispatch counted as a
26
+ * success is exactly the false green this task exists to remove. */
27
+ export declare function scanTranscript(lines: Iterable<string>, gated: ReadonlySet<string>): TranscriptEvent[];
28
+ /** The two counts over one window.
29
+ *
30
+ * A dispatch counts only when its agent type names one of the account's own
31
+ * specialists. A dispatch to a shipped specialist is not evidence that the
32
+ * account's own clerks are being used, and an id that resolves to nothing is
33
+ * not counted either: "we could not tell who ran" is not "the account's
34
+ * specialist ran". */
35
+ export declare function countWindow(events: readonly TranscriptEvent[], agentTypeById: ReadonlyMap<string, string>, authoredNames: ReadonlySet<string>, sinceMs: number): {
36
+ dispatched: number;
37
+ bypassed: number;
38
+ };
39
+ /** The every-tick line. `declared>0 dispatched7d=0` is the alarm; `bypassed7d=0`
40
+ * with `dispatched7d>0` is the healthy state. Emitted including all-zero, so
41
+ * the line's presence proves the check ran. */
42
+ export declare function formatCensus(p: {
43
+ accountId8: string;
44
+ declared: number;
45
+ dispatched7d: number;
46
+ bypassed7d: number;
47
+ }): string;
48
+ /** The error path, deliberately carrying NO counts. Reporting `declared=0` when
49
+ * the card set could not be read would assert something never measured, and
50
+ * would be indistinguishable from an account that genuinely has none. Task 2469
51
+ * applied the same rule to `op=agent-registry-resolution`. */
52
+ export declare function formatCensusDegraded(p: {
53
+ accountId8: string;
54
+ reason: string;
55
+ }): string;
56
+ export interface CensusAccount {
57
+ accountId: string;
58
+ accountDir: string;
59
+ }
60
+ export interface CensusTranscript {
61
+ path: string;
62
+ sessionId: string;
63
+ mtimeMs: number;
64
+ }
65
+ export interface ResolvedGating {
66
+ declared: number;
67
+ authoredNames: ReadonlySet<string>;
68
+ gated: ReadonlySet<string>;
69
+ }
70
+ export interface SpecialistCensusDeps {
71
+ intervalMs: number;
72
+ logger: Logger;
73
+ now(): number;
74
+ listAccounts(): readonly CensusAccount[];
75
+ /** May throw; a throw is the degraded path for that ACCOUNT and never for the
76
+ * run, so one unreadable account does not cost every other account its line. */
77
+ resolveGated(accountDir: string): ResolvedGating;
78
+ /** May throw; same rule as `resolveGated`. */
79
+ listTranscripts(accountDir: string): readonly CensusTranscript[];
80
+ readLines(path: string): Iterable<string>;
81
+ /** `tool_use` id to the agent type it spawned, read from that session's
82
+ * `subagents/agent-<id>.meta.json` files. Task 2469 established that sibling
83
+ * meta as the only surface tying a subagent run to its type. */
84
+ readAgentTypes(accountDir: string, sessionId: string): ReadonlyMap<string, string>;
85
+ }
86
+ export interface SpecialistCensus {
87
+ start(): void;
88
+ stop(): void;
89
+ tickOnce(): void;
90
+ }
91
+ export declare function createSpecialistCensus(deps: SpecialistCensusDeps): SpecialistCensus;
92
+ //# sourceMappingURL=specialist-census.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialist-census.d.ts","sourceRoot":"","sources":["../src/specialist-census.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,SAAS,QAA0B,CAAA;AAEhD,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAS3C,MAAM,WAAW,eAAe;IAC9B;;sCAEkC;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAA;IAC3B;qBACiB;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;;;;;;;;;;;;qEAaqE;AACrE,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EACvB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GACzB,eAAe,EAAE,CA6BnB;AAED;;;;;;uBAMuB;AACvB,wBAAgB,WAAW,CACzB,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1C,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,GACd;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAa1C;AAED;;gDAEgD;AAChD,wBAAgB,YAAY,CAAC,CAAC,EAAE;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,MAAM,CAGT;AAED;;;+DAG+D;AAC/D,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEtF;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAClC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,IAAI,MAAM,CAAA;IACb,YAAY,IAAI,SAAS,aAAa,EAAE,CAAA;IACxC;qFACiF;IACjF,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAAA;IAChD,8CAA8C;IAC9C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,gBAAgB,EAAE,CAAA;IAChE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IACzC;;qEAEiE;IACjE,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACnF;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,QAAQ,IAAI,IAAI,CAAA;CACjB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAoHnF"}
@@ -0,0 +1,227 @@
1
+ // Task 2244 — an account's own specialists are present, and nothing dispatches
2
+ // them.
3
+ //
4
+ // Skipped delegation writes no record: the inline draft logs an ordinary
5
+ // success, so no log line carries the fault and no re-run reproduces it. On
6
+ // account 2078cb54 four authored clerks owned email, works orders, invoices and
7
+ // quotes while the admin produced all of them inline — zero dispatches against
8
+ // 472 direct `email-draft` calls, for three days, found by the operator rather
9
+ // than by the platform. Only a standing check that reports on a QUIET account
10
+ // can see that state, which is why the line is emitted including all-zero.
11
+ //
12
+ // This is a fourth signal beside three that cannot answer it. The registry
13
+ // reconcile (`account-agent-registry.ts`) says a specialist CAN be reached. The
14
+ // roster census says it is advertised and resolvable. The preference audit
15
+ // (`specialist-preference-audit.ts`) says the RIGHT specialist wrote an owned
16
+ // artefact. None of them counts a dispatch.
17
+ //
18
+ // Shape mirrors specialist-preference-audit.ts: pure scanners, selector and
19
+ // formatters, plus an impure factory whose setInterval is unref'd and whose
20
+ // readers are injected.
21
+ const TAG = '[specialist-census]';
22
+ export const WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
23
+ /** The dispatch tool has carried two names across CLI versions, and both are
24
+ * present in the corpus on disk: the current CLI writes `"name":"Agent"`, and
25
+ * Task 2237 recorded `"name":"Task"` on the same install. Counting one is how a
26
+ * brittle grep reads as a real zero — the trap that task documented when it
27
+ * validated its own count against a tool it knew had run. */
28
+ const DISPATCH_TOOLS = new Set(['Agent', 'Task']);
29
+ /** Dispatches and gated calls in one transcript.
30
+ *
31
+ * The input is the PARENT session transcript, which is the main conversation by
32
+ * construction: Task 2469 measured all 41,456 records of one parent as
33
+ * `isSidechain: false`, carrying none of a subagent's tool calls. So a
34
+ * specialist's own use of its own tool can never be counted as a bypass here.
35
+ *
36
+ * A line that will not parse yields nothing rather than throwing: the corpus
37
+ * carries partial trailing writes, and one bad line must not abort the
38
+ * transcript it sits in.
39
+ *
40
+ * A dispatch with no `tool_use` id is skipped rather than counted: it cannot be
41
+ * attributed to a specialist, and an unattributable dispatch counted as a
42
+ * success is exactly the false green this task exists to remove. */
43
+ export function scanTranscript(lines, gated) {
44
+ const out = [];
45
+ for (const line of lines) {
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(line);
49
+ }
50
+ catch {
51
+ continue;
52
+ }
53
+ const record = parsed;
54
+ if (typeof record.timestamp !== 'string')
55
+ continue;
56
+ const ts = Date.parse(record.timestamp);
57
+ if (Number.isNaN(ts))
58
+ continue;
59
+ const content = record.message?.content;
60
+ if (!Array.isArray(content))
61
+ continue;
62
+ for (const block of content) {
63
+ if (!block || typeof block !== 'object')
64
+ continue;
65
+ const b = block;
66
+ if (b.type !== 'tool_use' || typeof b.name !== 'string')
67
+ continue;
68
+ if (DISPATCH_TOOLS.has(b.name)) {
69
+ if (typeof b.id === 'string' && b.id.length > 0) {
70
+ out.push({ ts, kind: 'dispatch', key: b.id });
71
+ }
72
+ continue;
73
+ }
74
+ if (gated.has(b.name))
75
+ out.push({ ts, kind: 'bypass', key: b.name });
76
+ }
77
+ }
78
+ return out;
79
+ }
80
+ /** The two counts over one window.
81
+ *
82
+ * A dispatch counts only when its agent type names one of the account's own
83
+ * specialists. A dispatch to a shipped specialist is not evidence that the
84
+ * account's own clerks are being used, and an id that resolves to nothing is
85
+ * not counted either: "we could not tell who ran" is not "the account's
86
+ * specialist ran". */
87
+ export function countWindow(events, agentTypeById, authoredNames, sinceMs) {
88
+ let dispatched = 0;
89
+ let bypassed = 0;
90
+ for (const event of events) {
91
+ if (event.ts < sinceMs)
92
+ continue;
93
+ if (event.kind === 'bypass') {
94
+ bypassed++;
95
+ continue;
96
+ }
97
+ const agentType = agentTypeById.get(event.key);
98
+ if (agentType !== undefined && authoredNames.has(agentType))
99
+ dispatched++;
100
+ }
101
+ return { dispatched, bypassed };
102
+ }
103
+ /** The every-tick line. `declared>0 dispatched7d=0` is the alarm; `bypassed7d=0`
104
+ * with `dispatched7d>0` is the healthy state. Emitted including all-zero, so
105
+ * the line's presence proves the check ran. */
106
+ export function formatCensus(p) {
107
+ return `${TAG} account=${p.accountId8} declared=${p.declared}` +
108
+ ` dispatched7d=${p.dispatched7d} bypassed7d=${p.bypassed7d}`;
109
+ }
110
+ /** The error path, deliberately carrying NO counts. Reporting `declared=0` when
111
+ * the card set could not be read would assert something never measured, and
112
+ * would be indistinguishable from an account that genuinely has none. Task 2469
113
+ * applied the same rule to `op=agent-registry-resolution`. */
114
+ export function formatCensusDegraded(p) {
115
+ return `${TAG} account=${p.accountId8} op=degraded reason=${p.reason}`;
116
+ }
117
+ export function createSpecialistCensus(deps) {
118
+ /** transcript path -> the events found in it, at that mtime and under that
119
+ * gated set.
120
+ *
121
+ * Events rather than counts, because the window moves every tick while the
122
+ * file does not: a cached count would freeze at the window in force when the
123
+ * file was last read, and an account that went quiet would keep reporting the
124
+ * activity it had a fortnight ago.
125
+ *
126
+ * Keyed on the gated set as well as the mtime, because the gated set is not a
127
+ * property of the transcript. Authoring a specialist widens it while every
128
+ * existing file keeps its mtime, so an mtime-only cache would keep reporting
129
+ * the counts of the narrower set and the new clerk's tools would read as
130
+ * never bypassed on the day it was created. A transcript is re-read only when
131
+ * one of the two moves, so a steady state still costs one stat per file. */
132
+ const seen = new Map();
133
+ let timer = null;
134
+ /** A stable identity for a gated set, so a cache hit can prove the events were
135
+ * scanned under the set in force now. */
136
+ function gatingKeyFor(gated) {
137
+ return Array.from(gated).sort().join(',');
138
+ }
139
+ function tickOnce() {
140
+ const sinceMs = deps.now() - WINDOW_MS;
141
+ const live = new Set();
142
+ for (const account of deps.listAccounts()) {
143
+ const accountId8 = account.accountId.slice(0, 8);
144
+ let gating;
145
+ let transcripts;
146
+ try {
147
+ gating = deps.resolveGated(account.accountDir);
148
+ transcripts = deps.listTranscripts(account.accountDir);
149
+ }
150
+ catch (err) {
151
+ deps.logger(formatCensusDegraded({
152
+ accountId8,
153
+ reason: err instanceof Error ? err.message : String(err),
154
+ }));
155
+ continue;
156
+ }
157
+ const gatingKey = gatingKeyFor(gating.gated);
158
+ let dispatched7d = 0;
159
+ let bypassed7d = 0;
160
+ for (const transcript of transcripts) {
161
+ live.add(transcript.path);
162
+ const prior = seen.get(transcript.path);
163
+ let events;
164
+ if (prior && prior.mtimeMs === transcript.mtimeMs && prior.gatingKey === gatingKey) {
165
+ events = prior.events;
166
+ }
167
+ else {
168
+ try {
169
+ events = scanTranscript(deps.readLines(transcript.path), gating.gated);
170
+ }
171
+ catch {
172
+ // A transcript that cannot be read contributes nothing and is not
173
+ // cached, so the next tick retries it. It does not degrade the
174
+ // account: every other transcript still carries real counts.
175
+ continue;
176
+ }
177
+ seen.set(transcript.path, { mtimeMs: transcript.mtimeMs, gatingKey, events });
178
+ }
179
+ let agentTypes = new Map();
180
+ if (events.some((e) => e.kind === 'dispatch')) {
181
+ try {
182
+ agentTypes = deps.readAgentTypes(account.accountDir, transcript.sessionId);
183
+ }
184
+ catch {
185
+ // Unresolved dispatches are not counted, which countWindow already
186
+ // enforces. Never counted as a success.
187
+ agentTypes = new Map();
188
+ }
189
+ }
190
+ const counted = countWindow(events, agentTypes, gating.authoredNames, sinceMs);
191
+ dispatched7d += counted.dispatched;
192
+ bypassed7d += counted.bypassed;
193
+ }
194
+ deps.logger(formatCensus({ accountId8, declared: gating.declared, dispatched7d, bypassed7d }));
195
+ }
196
+ // Drop transcripts that have gone, so the cache describes what is on disk now
197
+ // rather than growing for the life of a process that runs for weeks.
198
+ for (const path of Array.from(seen.keys()))
199
+ if (!live.has(path))
200
+ seen.delete(path);
201
+ }
202
+ return {
203
+ tickOnce,
204
+ start() {
205
+ if (timer)
206
+ return;
207
+ timer = setInterval(() => {
208
+ try {
209
+ tickOnce();
210
+ }
211
+ catch (err) {
212
+ deps.logger(`${TAG} op=tick-failed message=${err instanceof Error ? err.message : String(err)}`);
213
+ }
214
+ }, deps.intervalMs);
215
+ if (typeof timer.unref === 'function')
216
+ timer.unref();
217
+ deps.logger(`${TAG} op=started intervalMs=${deps.intervalMs}`);
218
+ },
219
+ stop() {
220
+ if (timer) {
221
+ clearInterval(timer);
222
+ timer = null;
223
+ }
224
+ },
225
+ };
226
+ }
227
+ //# sourceMappingURL=specialist-census.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specialist-census.js","sourceRoot":"","sources":["../src/specialist-census.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,QAAQ;AACR,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,2EAA2E;AAC3E,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAChF,2EAA2E;AAC3E,8EAA8E;AAC9E,4CAA4C;AAC5C,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,wBAAwB;AAExB,MAAM,GAAG,GAAG,qBAAqB,CAAA;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAIhD;;;;8DAI8D;AAC9D,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;AAatE;;;;;;;;;;;;;qEAaqE;AACrE,MAAM,UAAU,cAAc,CAC5B,KAAuB,EACvB,KAA0B;IAE1B,MAAM,GAAG,GAAsB,EAAE,CAAA;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,MAAe,CAAA;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,SAAQ;QACV,CAAC;QACD,MAAM,MAAM,GAAG,MAAkE,CAAA;QACjF,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YAAE,SAAQ;QAClD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QACvC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,SAAQ;QAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAA;QACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAQ;QACrC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAQ;YACjD,MAAM,CAAC,GAAG,KAAsD,CAAA;YAChE,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAQ;YACjE,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC/B,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAChD,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBAC/C,CAAC;gBACD,SAAQ;YACV,CAAC;YACD,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;uBAMuB;AACvB,MAAM,UAAU,WAAW,CACzB,MAAkC,EAClC,aAA0C,EAC1C,aAAkC,EAClC,OAAe;IAEf,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,EAAE,GAAG,OAAO;YAAE,SAAQ;QAChC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,QAAQ,EAAE,CAAA;YACV,SAAQ;QACV,CAAC;QACD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9C,IAAI,SAAS,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,UAAU,EAAE,CAAA;IAC3E,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA;AACjC,CAAC;AAED;;gDAEgD;AAChD,MAAM,UAAU,YAAY,CAAC,CAK5B;IACC,OAAO,GAAG,GAAG,YAAY,CAAC,CAAC,UAAU,aAAa,CAAC,CAAC,QAAQ,EAAE;QAC5D,iBAAiB,CAAC,CAAC,YAAY,eAAe,CAAC,CAAC,UAAU,EAAE,CAAA;AAChE,CAAC;AAED;;;+DAG+D;AAC/D,MAAM,UAAU,oBAAoB,CAAC,CAAyC;IAC5E,OAAO,GAAG,GAAG,YAAY,CAAC,CAAC,UAAU,uBAAuB,CAAC,CAAC,MAAM,EAAE,CAAA;AACxE,CAAC;AA0CD,MAAM,UAAU,sBAAsB,CAAC,IAA0B;IAC/D;;;;;;;;;;;;;iFAa6E;IAC7E,MAAM,IAAI,GAAG,IAAI,GAAG,EAA6E,CAAA;IACjG,IAAI,KAAK,GAA0B,IAAI,CAAA;IAEvC;8CAC0C;IAC1C,SAAS,YAAY,CAAC,KAA0B;QAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC3C,CAAC;IAED,SAAS,QAAQ;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAA;QACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;QAE9B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YAEhD,IAAI,MAAsB,CAAA;YAC1B,IAAI,WAAwC,CAAA;YAC5C,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;gBAC9C,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;YACxD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CACT,oBAAoB,CAAC;oBACnB,UAAU;oBACV,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACzD,CAAC,CACH,CAAA;gBACD,SAAQ;YACV,CAAC;YAED,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC5C,IAAI,YAAY,GAAG,CAAC,CAAA;YACpB,IAAI,UAAU,GAAG,CAAC,CAAA;YAClB,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;gBACrC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;gBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;gBACvC,IAAI,MAAyB,CAAA;gBAC7B,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;oBACnF,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;gBACvB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC;wBACH,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;oBACxE,CAAC;oBAAC,MAAM,CAAC;wBACP,kEAAkE;wBAClE,+DAA+D;wBAC/D,6DAA6D;wBAC7D,SAAQ;oBACV,CAAC;oBACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAA;gBAC/E,CAAC;gBAED,IAAI,UAAU,GAAgC,IAAI,GAAG,EAAE,CAAA;gBACvD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;oBAC9C,IAAI,CAAC;wBACH,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,CAAA;oBAC5E,CAAC;oBAAC,MAAM,CAAC;wBACP,mEAAmE;wBACnE,wCAAwC;wBACxC,UAAU,GAAG,IAAI,GAAG,EAAE,CAAA;oBACxB,CAAC;gBACH,CAAC;gBAED,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;gBAC9E,YAAY,IAAI,OAAO,CAAC,UAAU,CAAA;gBAClC,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAA;YAChC,CAAC;YAED,IAAI,CAAC,MAAM,CACT,YAAY,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAClF,CAAA;QACH,CAAC;QAED,8EAA8E;QAC9E,qEAAqE;QACrE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpF,CAAC;IAED,OAAO;QACL,QAAQ;QACR,KAAK;YACH,IAAI,KAAK;gBAAE,OAAM;YACjB,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;gBACvB,IAAI,CAAC;oBACH,QAAQ,EAAE,CAAA;gBACZ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,MAAM,CACT,GAAG,GAAG,2BAA2B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACpF,CAAA;gBACH,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;YACnB,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU;gBAAE,KAAK,CAAC,KAAK,EAAE,CAAA;YACpD,IAAI,CAAC,MAAM,CAAC,GAAG,GAAG,0BAA0B,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QAChE,CAAC;QACD,IAAI;YACF,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,CAAC,KAAK,CAAC,CAAA;gBACpB,KAAK,GAAG,IAAI,CAAA;YACd,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -11,7 +11,8 @@
11
11
  "hooks": [
12
12
  { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
13
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" }
14
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" },
15
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/html-structure-gate.sh" }
15
16
  ]
16
17
  },
17
18
  {
@@ -19,7 +20,8 @@
19
20
  "hooks": [
20
21
  { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
21
22
  { "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
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" },
24
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/html-structure-gate.sh" }
23
25
  ]
24
26
  },
25
27
  {
@@ -27,7 +29,8 @@
27
29
  "hooks": [
28
30
  { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/archive-ingest-surface-gate.sh" },
29
31
  { "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" }
32
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/quote-path-write-gate.sh" },
33
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/html-structure-gate.sh" }
31
34
  ]
32
35
  },
33
36
  {
@@ -50,7 +53,8 @@
50
53
  {
51
54
  "hooks": [
52
55
  { "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" }
56
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/public-tool-surface.sh" },
57
+ { "type": "command", "command": "bash $PLATFORM_ROOT/plugins/admin/hooks/specialist-dispatch-gate.sh" }
54
58
  ]
55
59
  },
56
60
  {
@@ -59,6 +59,13 @@ client quote (see `references/verification.md`, "Verifying the issued document c
59
59
  - **`data-doc-header`** on the header block, so the tool can hold it to the account's declared canonical
60
60
  header template at `quoting/templates/header.html` (verbatim, structure and embedded logo data). The
61
61
  template is a fixed-path opt-in: when the account declares none the header check is skipped.
62
+ **The header block carries its own `<style>` element and is spliced into the body, never inside an
63
+ existing `<style>`.** A browser parses style content as raw text, so a second `<style>` opened inside
64
+ an open one does not nest: the first `</style>` closes the outer element, everything after it becomes
65
+ body content and renders as visible text above the header, and the rule immediately after the stray
66
+ opener is eaten as part of an invalid selector. Either put the block in the body as its own element,
67
+ or merge its rules into the one already open. A write that would produce the nested shape is refused
68
+ at the write, and any such document already on disk is reported on the standing census tick.
62
69
  - **`data-doc-terms`** on the standing-terms section, so the tool asserts it carries no above-normal
63
70
  weight (no `<b>`/`<strong>`, no inline `font-weight` of bold, bolder, or 500 to 900). No terms marker,
64
71
  no check.
@@ -91,10 +98,16 @@ The tool produces **HTML, not PDF**. Print each returned path to PDF with the `b
91
98
  final step: `browser-navigate` to its `file://` URL, then `browser-pdf-save` to a `.pdf` alongside it,
92
99
  confirming a non-zero byte count. A Workflow chains `quote-engine-run`, then `quote-render`, then one
93
100
  `browser` `browser-pdf-save` step per document. A **PostToolUse gate on `browser-pdf-save`** then holds
94
- the printed client-quote PDF to its two PDF-only conformance checks: its `/URI` count is at least the
95
- source HTML's absolute-link count, and every embedded `https://` link answers 200. A failure blocks the
96
- print with `[quote-render] op=bypass reason=pdf-link-conformance`, so a link-stripped or dead-link PDF
97
- is not sent.
101
+ the printed PDF to the conformance checks that can only be made once the PDF exists. Two are about
102
+ links on a gated client quote: its `/URI` count is at least the source HTML's absolute-link count, and
103
+ every embedded `https://` link answers 200; a failure blocks the print with
104
+ `[quote-render] op=bypass reason=pdf-link-conformance`, so a link-stripped or dead-link PDF is not
105
+ sent. Two are about page chrome, and apply to **any** printed document that declares the thing they
106
+ check, receipt or no receipt, because a template-seeded document never passes through `quote-render`
107
+ at all: a running header must appear on every physical page when a text margin box is declared
108
+ (`reason=pdf-header-conformance`), and the header's image must render no wider than a third of the
109
+ page when an image margin box is declared (`reason=pdf-header-image-geometry`). Both page-chrome
110
+ faults are reported on the same print, so fixing one does not hide the other.
98
111
 
99
112
  ## The three documents
100
113
 
@@ -185,6 +198,12 @@ the document:
185
198
 
186
199
  - page-level chrome — a running header or footer and page numbers — via `@page` margin boxes, never
187
200
  absolutely-positioned elements that drift across pages;
201
+ - an image used as a margin box's `content: url(...)` **pre-sized to the box**. The renderer paints
202
+ such an image at its own intrinsic pixel size, one image pixel to one CSS pixel at 96 pixels per
203
+ inch, and does **not** scale it down to the `width`/`height` the box declares. A full-resolution
204
+ logo therefore covers most of the page on every page the box paints, whatever the box says: a
205
+ 700-pixel-wide asset renders 525 points wide on a 595-point A4 page, against a declared box of 34
206
+ millimetres. Make a derivative at the size the box expects and point the box at that;
188
207
  - `print-color-adjust: exact` on coloured fills, so the operator's brand fills survive print. The
189
208
  renderer prints backgrounds, but make the intent explicit rather than relying on the default.
190
209
 
@@ -22,8 +22,8 @@
22
22
  <link rel="modulepreload" crossorigin href="/assets/wrench-D4ufQG6C.js">
23
23
  <link rel="modulepreload" crossorigin href="/assets/page-BbBCu9iP.js">
24
24
  <link rel="stylesheet" crossorigin href="/assets/jsx-runtime-DxsQ5Y-z.css">
25
- <link rel="stylesheet" crossorigin href="/assets/useMediaQuery-DXAuc8G-.css">
26
25
  <link rel="stylesheet" crossorigin href="/assets/AdminLoginScreens-CWMpccrR.css">
26
+ <link rel="stylesheet" crossorigin href="/assets/useMediaQuery-DXAuc8G-.css">
27
27
  <link rel="stylesheet" href="/brand-defaults.css">
28
28
  </head>
29
29
  <body>