@rubytech/create-maxy-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 (127) 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/server/server.js +465 -361
@@ -0,0 +1,144 @@
1
+ // Task 2244 — which specialists are the ACCOUNT's own, and which tools are
2
+ // theirs.
3
+ //
4
+ // Task 2244 defined both its deliverables against every card under
5
+ // `<accountDir>/specialists/agents/`. Measured against the tree, that rule
6
+ // refuses the admin nearly its whole surface: `provision-account-dir.sh:179-181`
7
+ // copies every shipped template into each account, and `personal-assistant.md`
8
+ // alone declares roughly 130 tools including the entire email, WhatsApp,
9
+ // calendar and browser surfaces, while `content-producer.md` and
10
+ // `sitedesk--quoter.md` declare Bash, Read, Edit and Write. So the set is
11
+ // narrowed on two axes, both settled with the operator before implementation.
12
+ //
13
+ // Card axis — a card is the account's own when its filename appears in none of
14
+ // the shipped roots. `<accountDir>/plugins/*/agents/` is deliberately NOT one of
15
+ // those: that is where `store-skill` files an authored agent's durable copy, so
16
+ // a card found there is still the account's own. These are the same roots
17
+ // `runRosterCensus` takes as `durableDirs` and `durablePluginRoots`, used here as
18
+ // a set difference so no new registry is introduced — the failure this tree has
19
+ // already hit twice, in Task 2460's three unreconciled agent directories and
20
+ // Task 2467's provision-time-only hook set.
21
+ //
22
+ // Tool axis — native tools are subtracted. Gating Bash or Read would refuse the
23
+ // admin its own seat, and every authored card declares some of them.
24
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
25
+ import { join } from 'node:path';
26
+ import { CC_NATIVE_TOOLS } from './specialist-drift.js';
27
+ /** `*.md` entries directly in `dir`, for a SHIPPED root. An absent or unreadable
28
+ * one contributes nothing: not every install carries premium-plugins, and an
29
+ * unreadable platform tree must not cost an account its census line. The
30
+ * consequence of swallowing here is a card wrongly counted as the account's
31
+ * own, which is a visible over-count rather than a silent zero. */
32
+ function markdownIn(dir) {
33
+ if (!existsSync(dir))
34
+ return [];
35
+ try {
36
+ return readdirSync(dir).filter((entry) => entry.endsWith('.md'));
37
+ }
38
+ catch {
39
+ return [];
40
+ }
41
+ }
42
+ /** `*.md` entries in the ACCOUNT's own specialists directory.
43
+ *
44
+ * Absent means an account with no specialists, which is normal and yields
45
+ * nothing. Present-but-unreadable is a measurement failure and THROWS, because
46
+ * the two must not collapse: returning nothing there would report `declared=0`,
47
+ * the unmeasured zero the census is forbidden to assert, and it would be
48
+ * indistinguishable from an account that genuinely has none. The gate throws on
49
+ * the same fault, so swallowing it here would leave the two surfaces disagreeing
50
+ * about one account. */
51
+ function accountMarkdownIn(dir) {
52
+ if (!existsSync(dir))
53
+ return [];
54
+ return readdirSync(dir).filter((entry) => entry.endsWith('.md'));
55
+ }
56
+ function subdirs(dir) {
57
+ if (!existsSync(dir))
58
+ return [];
59
+ try {
60
+ return readdirSync(dir, { withFileTypes: true })
61
+ .filter((entry) => entry.isDirectory())
62
+ .map((entry) => entry.name);
63
+ }
64
+ catch {
65
+ return [];
66
+ }
67
+ }
68
+ /** One frontmatter scalar, CRLF-tolerant and quote-stripping — the same idiom
69
+ * `specialist-roster.ts` and `roster-census.ts` use, so all three agree on what
70
+ * a card is called and what it declares. */
71
+ function frontmatterField(raw, field) {
72
+ const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---/);
73
+ if (!fm)
74
+ return null;
75
+ const m = fm[1].match(new RegExp(`^${field}:\\s*(.*?)\\r?$`, 'm'));
76
+ if (!m)
77
+ return null;
78
+ let value = m[1].trim();
79
+ if ((value.startsWith('"') && value.endsWith('"')) ||
80
+ (value.startsWith("'") && value.endsWith("'"))) {
81
+ value = value.slice(1, -1);
82
+ }
83
+ return value || null;
84
+ }
85
+ /** Every card in the account's specialists directory that no shipped root
86
+ * delivers, sorted by filename so the derived tool map is stable across ticks.
87
+ *
88
+ * A card missing `name` is skipped rather than throwing — the same tolerance
89
+ * `readSpecialistRoster` applies, because one malformed file must not cost the
90
+ * account its whole set. A card with no `tools` declares none, which is a real
91
+ * state (an authored card can own a domain through prose alone) and not an
92
+ * error. */
93
+ export function readAuthoredCards(input) {
94
+ const shipped = new Set();
95
+ for (const dir of input.shippedDirs) {
96
+ for (const filename of markdownIn(dir))
97
+ shipped.add(filename);
98
+ }
99
+ for (const root of input.shippedPluginRoots) {
100
+ for (const plugin of subdirs(root)) {
101
+ for (const filename of markdownIn(join(root, plugin, 'agents')))
102
+ shipped.add(filename);
103
+ }
104
+ }
105
+ const out = [];
106
+ for (const filename of accountMarkdownIn(input.specialistsAgentsDir).sort()) {
107
+ if (shipped.has(filename))
108
+ continue;
109
+ let raw;
110
+ try {
111
+ raw = readFileSync(join(input.specialistsAgentsDir, filename), 'utf8');
112
+ }
113
+ catch {
114
+ continue;
115
+ }
116
+ const name = frontmatterField(raw, 'name');
117
+ if (!name)
118
+ continue;
119
+ const tools = (frontmatterField(raw, 'tools') ?? '')
120
+ .split(',')
121
+ .map((tool) => tool.trim())
122
+ .filter((tool) => tool.length > 0);
123
+ out.push({ filename, name, tools });
124
+ }
125
+ return out;
126
+ }
127
+ /** Tool name to the authored specialist that owns it, native tools removed.
128
+ *
129
+ * First declarer wins when two cards name the same tool. The refusal names one
130
+ * specialist, and an account that split a tool across two of its own clerks has
131
+ * a roster problem that this gate is not the place to report. */
132
+ export function gatedToolMap(cards) {
133
+ const map = new Map();
134
+ for (const card of cards) {
135
+ for (const tool of card.tools) {
136
+ if (CC_NATIVE_TOOLS.has(tool))
137
+ continue;
138
+ if (!map.has(tool))
139
+ map.set(tool, card.name);
140
+ }
141
+ }
142
+ return map;
143
+ }
144
+ //# sourceMappingURL=authored-specialist-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authored-specialist-tools.js","sourceRoot":"","sources":["../src/authored-specialist-tools.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EA2B7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAsWtD,CAAA"}
1
+ {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EA2B7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAuWtD,CAAA"}
@@ -52,6 +52,7 @@ export const CANONICAL_MAXY_TOOL_NAMES = [
52
52
  "mcp__plugin_admin_admin__action-pending",
53
53
  "mcp__plugin_admin_admin__action-reject",
54
54
  "mcp__plugin_admin_admin__admin-add",
55
+ "mcp__plugin_admin_admin__admin-bind",
55
56
  "mcp__plugin_admin_admin__admin-hostname",
56
57
  "mcp__plugin_admin_admin__admin-list",
57
58
  "mcp__plugin_admin_admin__admin-remove",
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface HtmlStructureFinding {
2
+ accountId: string;
3
+ /** Path of the malformed document, relative to the account dir. */
4
+ path: string;
5
+ /** Line of the nested or unmatched <style> opener. */
6
+ line: number;
7
+ }
8
+ export interface HtmlStructureResult {
9
+ /** HTML documents walked on this account. */
10
+ documents: number;
11
+ findings: HtmlStructureFinding[];
12
+ }
13
+ /** One line per run, emitted with a zero count as well — silence is a broken
14
+ * walk, not a clean install. */
15
+ export declare function formatHtmlStructureCensusSummary(accounts: number, documents: number, malformed: number): string;
16
+ /** One line per malformed document. The path is JSON-quoted because these
17
+ * filenames carry spaces and a bare key=value line truncates at the first one. */
18
+ export declare function formatHtmlStructureFinding(f: HtmlStructureFinding): string;
19
+ /** Line of the first nested or unmatched <style> opener in `source`, else null.
20
+ *
21
+ * HTML comments are stripped first, each replaced by its own newlines, so a
22
+ * <style> inside <!-- … --> is not scanned and line numbers do not shift. That
23
+ * case is real: two account templates carry one and are clean, and a
24
+ * comment-blind detector reports both.
25
+ *
26
+ * A CSS comment protects an OPENER but never a CLOSER, and the asymmetry is the
27
+ * browser's, not a convenience. Style content is raw text to the HTML parser, so
28
+ * `</style>` terminates the element wherever it appears, comment or not. An
29
+ * opener, by contrast, is never a parse event inside a stylesheet — it is text
30
+ * the CSS parser reads as an invalid selector, which is what eats the rule after
31
+ * it. Inside a comment the CSS parser discards it and nothing is eaten: the
32
+ * shipped property-brochure template documents its override slot exactly that
33
+ * way and is correct. */
34
+ export declare function htmlStyleFaultLine(source: string): number | null;
35
+ /** Walk one account's HTML documents and report every malformed one. */
36
+ export declare function collectAccountHtmlFindings(accountDir: string, accountId: string): HtmlStructureResult;
37
+ export interface HtmlStructureCensusDeps {
38
+ /** <installDir>/data/accounts */
39
+ accountsDir: string;
40
+ logger: (line: string) => void;
41
+ }
42
+ /** One pass over every account. Called from the [quote-reconcile] tick. */
43
+ export declare function runHtmlStructureCensus(deps: HtmlStructureCensusDeps): void;
44
+ //# sourceMappingURL=html-structure-census.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-structure-census.d.ts","sourceRoot":"","sources":["../src/html-structure-census.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,oBAAoB,EAAE,CAAA;CACjC;AAED;iCACiC;AACjC,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,MAAM,CAER;AAED;mFACmF;AACnF,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAE1E;AAWD;;;;;;;;;;;;;;0BAc0B;AAC1B,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBhE;AA+CD,wEAAwE;AACxE,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,mBAAmB,CAkBrB;AAED,MAAM,WAAW,uBAAuB;IACtC,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,CAoB1E"}
@@ -0,0 +1,185 @@
1
+ // Standing census of malformed <style> nesting across every account's HTML.
2
+ //
3
+ // A second <style> opener inside an open <style> element is not cosmetic. HTML
4
+ // parses style content as raw text, so the FIRST </style> closes the outer
5
+ // element: everything after it becomes body content and renders as visible text,
6
+ // and the rule immediately after the stray opener is eaten as part of an invalid
7
+ // selector. One fault, two symptoms — and on 2026-08-07 both were reported on a
8
+ // client quotation that had been live since 2026-07-24.
9
+ //
10
+ // The write gate (plugins/admin/hooks/html-structure-gate.sh) refuses the write.
11
+ // It cannot close the fault on its own: it cannot see what is already on disk,
12
+ // and a Bash heredoc writes a file without passing a Write gate at all. This
13
+ // pass is the backstop, and it is the only instrument that can see the state —
14
+ // the failure emits no event and re-running the render surfaces nothing.
15
+ //
16
+ // The detector is the same three rules as the hook: comments stripped first,
17
+ // then a depth-tracking walk of <style…>/</style…>, then an openers-equal-closers
18
+ // check at end of input.
19
+ //
20
+ // Shape mirrors the standing-audit family (quote-delivery-reconcile.ts): pure
21
+ // formatters that are unit-tested, an impure per-account collector, and a
22
+ // one-pass entry point. It carries no timer of its own — the pass is called from
23
+ // the [quote-reconcile] tick, so one timer drives both audits. Filesystem only:
24
+ // no Neo4j, no writes, no deletes. A per-account error is caught so one bad
25
+ // account never aborts the run.
26
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
27
+ import { join, relative } from 'node:path';
28
+ const TAG = '[html-structure-census]';
29
+ /** Directories whose HTML is not a client document: vendored packages, build
30
+ * scratch, tool state and the account's own trash. */
31
+ const EXCLUDED = new Set(['node_modules', '.wrangler', '.tool', '.trash']);
32
+ /** One line per run, emitted with a zero count as well — silence is a broken
33
+ * walk, not a clean install. */
34
+ export function formatHtmlStructureCensusSummary(accounts, documents, malformed) {
35
+ return `${TAG} accounts=${accounts} documents=${documents} malformed=${malformed}`;
36
+ }
37
+ /** One line per malformed document. The path is JSON-quoted because these
38
+ * filenames carry spaces and a bare key=value line truncates at the first one. */
39
+ export function formatHtmlStructureFinding(f) {
40
+ return `${TAG} op=malformed account=${f.accountId} file=${JSON.stringify(f.path)} line=${f.line}`;
41
+ }
42
+ /** Spans of `/* … *​/` in `source`, as [start, end) index pairs. */
43
+ function cssCommentSpans(source) {
44
+ const spans = [];
45
+ const re = /\/\*[\s\S]*?\*\//g;
46
+ let m;
47
+ while ((m = re.exec(source)) !== null)
48
+ spans.push([m.index, m.index + m[0].length]);
49
+ return spans;
50
+ }
51
+ /** Line of the first nested or unmatched <style> opener in `source`, else null.
52
+ *
53
+ * HTML comments are stripped first, each replaced by its own newlines, so a
54
+ * <style> inside <!-- … --> is not scanned and line numbers do not shift. That
55
+ * case is real: two account templates carry one and are clean, and a
56
+ * comment-blind detector reports both.
57
+ *
58
+ * A CSS comment protects an OPENER but never a CLOSER, and the asymmetry is the
59
+ * browser's, not a convenience. Style content is raw text to the HTML parser, so
60
+ * `</style>` terminates the element wherever it appears, comment or not. An
61
+ * opener, by contrast, is never a parse event inside a stylesheet — it is text
62
+ * the CSS parser reads as an invalid selector, which is what eats the rule after
63
+ * it. Inside a comment the CSS parser discards it and nothing is eaten: the
64
+ * shipped property-brochure template documents its override slot exactly that
65
+ * way and is correct. */
66
+ export function htmlStyleFaultLine(source) {
67
+ const stripped = source.replace(/<!--[\s\S]*?-->/g, (m) => '\n'.repeat((m.match(/\n/g) ?? []).length));
68
+ const comments = cssCommentSpans(stripped);
69
+ const inComment = (i) => comments.some(([s, e]) => i >= s && i < e);
70
+ const re = /<\s*(\/)?\s*style\b[^>]*>/gi;
71
+ let depth = 0;
72
+ let openLine = 0;
73
+ let m;
74
+ while ((m = re.exec(stripped)) !== null) {
75
+ const line = stripped.slice(0, m.index).split('\n').length;
76
+ if (m[1]) {
77
+ if (depth > 0)
78
+ depth -= 1;
79
+ }
80
+ else if (depth > 0) {
81
+ if (inComment(m.index))
82
+ continue;
83
+ return line;
84
+ }
85
+ else {
86
+ depth = 1;
87
+ openLine = line;
88
+ }
89
+ }
90
+ return depth > 0 ? openLine : null;
91
+ }
92
+ /** Every .html/.htm under `dir` at any depth, skipping the excluded directories.
93
+ * Scope is the whole account with an exclusion list, never a bucket list: a
94
+ * bucket list is what let the live document through, since it sat under
95
+ * sites/<project>/public/, which no quote bucket covers. */
96
+ function listHtmlDeep(dir) {
97
+ const out = [];
98
+ let entries;
99
+ try {
100
+ entries = readdirSync(dir);
101
+ }
102
+ catch {
103
+ return out;
104
+ }
105
+ for (const name of entries) {
106
+ const p = join(dir, name);
107
+ try {
108
+ const st = statSync(p);
109
+ if (st.isDirectory()) {
110
+ if (!EXCLUDED.has(name))
111
+ out.push(...listHtmlDeep(p));
112
+ }
113
+ else if (st.isFile()) {
114
+ const lower = name.toLowerCase();
115
+ if (lower.endsWith('.html') || lower.endsWith('.htm'))
116
+ out.push(p);
117
+ }
118
+ }
119
+ catch {
120
+ // An entry that vanished mid-walk is not a finding.
121
+ }
122
+ }
123
+ return out;
124
+ }
125
+ function listDirs(dir) {
126
+ try {
127
+ return readdirSync(dir)
128
+ .map((n) => join(dir, n))
129
+ .filter((p) => {
130
+ try {
131
+ return statSync(p).isDirectory();
132
+ }
133
+ catch {
134
+ return false;
135
+ }
136
+ });
137
+ }
138
+ catch {
139
+ return [];
140
+ }
141
+ }
142
+ /** Walk one account's HTML documents and report every malformed one. */
143
+ export function collectAccountHtmlFindings(accountDir, accountId) {
144
+ const findings = [];
145
+ let documents = 0;
146
+ for (const f of listHtmlDeep(accountDir)) {
147
+ documents += 1;
148
+ let source;
149
+ try {
150
+ source = readFileSync(f, 'utf8');
151
+ }
152
+ catch {
153
+ // An unreadable document is not evidence of a fault.
154
+ continue;
155
+ }
156
+ const line = htmlStyleFaultLine(source);
157
+ if (line !== null)
158
+ findings.push({ accountId, path: relative(accountDir, f), line });
159
+ }
160
+ return { documents, findings };
161
+ }
162
+ /** One pass over every account. Called from the [quote-reconcile] tick. */
163
+ export function runHtmlStructureCensus(deps) {
164
+ let accounts = 0;
165
+ let documents = 0;
166
+ const findings = [];
167
+ for (const accountDir of listDirs(deps.accountsDir)) {
168
+ if (!existsSync(join(accountDir, 'account.json')))
169
+ continue;
170
+ accounts += 1;
171
+ const accountId = accountDir.slice(accountDir.lastIndexOf('/') + 1);
172
+ try {
173
+ const r = collectAccountHtmlFindings(accountDir, accountId);
174
+ documents += r.documents;
175
+ findings.push(...r.findings);
176
+ }
177
+ catch {
178
+ // One unreadable account never aborts the run.
179
+ }
180
+ }
181
+ for (const f of findings)
182
+ deps.logger(formatHtmlStructureFinding(f));
183
+ deps.logger(formatHtmlStructureCensusSummary(accounts, documents, findings.length));
184
+ }
185
+ //# sourceMappingURL=html-structure-census.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-structure-census.js","sourceRoot":"","sources":["../src/html-structure-census.ts"],"names":[],"mappings":"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"}
@@ -42,6 +42,7 @@ import { createPtyCensus } from './pty-census.js';
42
42
  import { createBlockedToolCensus, postBlockedNotifyViaFetch } from './blocked-tool-census.js';
43
43
  import { createSliceMemoryPolicy } from './slice-memory-policy.js';
44
44
  import { emitRootlessCensus, createRootlessAudit } from './rootless-client-audit.js';
45
+ import { createPrintCensus } from './quote-print-census.js';
45
46
  import { createPreferenceAudit } from './preference-reconciliation-audit.js';
46
47
  import { createIdentityAudit } from './identity-audit.js';
47
48
  import { createRedundantOperatorSeatAudit } from './redundant-operator-seat-audit.js';
@@ -54,6 +55,8 @@ import { createSessionCapAudit } from './session-cap-audit.js';
54
55
  import { createSkillStalenessAudit, collectPlatformSkillMtimes, collectPremiumSkillMtimes, resolveEnabledPlugins, buildLiveSessionRefs, parseProcStartMs, } from './skill-staleness-audit.js';
55
56
  import { createPublicSurfaceAudit, parseMcpLogServerName } from './public-surface-audit.js';
56
57
  import { createSpecialistPreferenceAudit, readLinesSync } from './specialist-preference-audit.js';
58
+ import { createSpecialistCensus } from './specialist-census.js';
59
+ import { gatedToolMap, readAuthoredCards } from './authored-specialist-tools.js';
57
60
  import { projectsDirForCwd, sessionsDir, jsonlPathForSessionId, slugForExistingJsonl, jsonlPathForSlug, sidecarPathForSlug } from './jsonl-path.js';
58
61
  import { readSidecar } from './session-sidecar.js';
59
62
  import { runSystemPromptSelfTest, runIdentityDriftAssertion, runIdentityForbiddenTokenCheck } from './system-prompt.js';
@@ -958,6 +961,100 @@ async function main() {
958
961
  readLines: (path) => readLinesSync(path),
959
962
  });
960
963
  specialistPreferenceAudit.start();
964
+ // Task 2244 — the fourth specialist signal, and the only one that counts a
965
+ // dispatch. The registry reconcile says a specialist CAN be reached, the
966
+ // roster census says it is advertised, and the preference audit above says the
967
+ // right one wrote an owned artefact. None of them sees the state that ran
968
+ // undetected for three days on a live account: four authored clerks present
969
+ // and resolvable, zero dispatches, 472 inline drafts. Skipped delegation
970
+ // writes no record, so only a check that reports on a QUIET account can see it
971
+ // — hence a line per account every tick, including all-zero.
972
+ //
973
+ // Authored cards only, native tools subtracted. Provisioning copies every
974
+ // shipped template into each account and one of them declares roughly 130
975
+ // tools, so counting every card's `tools:` would make `bypassed7d` count
976
+ // almost every call the admin makes.
977
+ //
978
+ // 300s and the mtime cache, matching the audit beside it: this reads parent
979
+ // transcripts, and a steady state costs one stat per file.
980
+ const specialistCensus = createSpecialistCensus({
981
+ intervalMs: 300_000,
982
+ logger: log,
983
+ now: () => Date.now(),
984
+ listAccounts: () => provisionedAccountDirs(),
985
+ resolveGated: (accountDir) => {
986
+ const cards = readAuthoredCards({
987
+ specialistsAgentsDir: join(accountDir, 'specialists', 'agents'),
988
+ shippedDirs: [join(platformRoot, 'templates', 'specialists', 'agents')],
989
+ // The ACCOUNT's own plugin root is deliberately absent: a card filed
990
+ // under <accountDir>/plugins/<x>/agents/ is that account's own durable
991
+ // copy, not something we ship, and treating it as shipped would drop
992
+ // exactly the cards this census exists to count.
993
+ shippedPluginRoots: [premiumPluginsRoot, pluginsRoot],
994
+ });
995
+ return {
996
+ declared: cards.length,
997
+ authoredNames: new Set(cards.map((card) => card.name)),
998
+ gated: new Set(gatedToolMap(cards).keys()),
999
+ };
1000
+ },
1001
+ listTranscripts: (accountDir) => {
1002
+ const dir = projectsDirForCwd(accountDir);
1003
+ const out = [];
1004
+ // Both the live directory and `archive/`. The user-initiated archive route
1005
+ // `mv`s a JSONL between the two, and a dispatch inside a session the
1006
+ // operator later archived still happened — dropping it would manufacture
1007
+ // the very `declared>0 dispatched7d=0` alarm this census exists to raise.
1008
+ // The subagent meta files stay beside the session id in either case.
1009
+ for (const root of [dir, join(dir, 'archive')]) {
1010
+ if (!existsSync(root))
1011
+ continue;
1012
+ for (const file of readdirSync(root)) {
1013
+ if (!file.endsWith('.jsonl'))
1014
+ continue;
1015
+ const path = join(root, file);
1016
+ let mtimeMs;
1017
+ try {
1018
+ mtimeMs = statSync(path).mtimeMs;
1019
+ }
1020
+ catch {
1021
+ // Archived or purged between the readdir and the stat. Skipping it
1022
+ // costs one transcript this tick; letting it throw would cost the
1023
+ // account its whole line and report a degradation that never was.
1024
+ continue;
1025
+ }
1026
+ out.push({ path, sessionId: file.slice(0, -'.jsonl'.length), mtimeMs });
1027
+ }
1028
+ }
1029
+ return out;
1030
+ },
1031
+ readLines: (path) => readLinesSync(path),
1032
+ readAgentTypes: (accountDir, sessionId) => {
1033
+ // `agent-<id>.meta.json` is the only surface tying a subagent run to its
1034
+ // type, and its `toolUseId` is the parent's own tool-use id, which is what
1035
+ // makes the join to the parent transcript exact rather than by timestamp.
1036
+ const dir = join(projectsDirForCwd(accountDir), sessionId, 'subagents');
1037
+ const out = new Map();
1038
+ if (!existsSync(dir))
1039
+ return out;
1040
+ for (const file of readdirSync(dir)) {
1041
+ if (!file.endsWith('.meta.json'))
1042
+ continue;
1043
+ try {
1044
+ const meta = JSON.parse(readFileSync(join(dir, file), 'utf8'));
1045
+ if (typeof meta.agentType === 'string' && typeof meta.toolUseId === 'string') {
1046
+ out.set(meta.toolUseId, meta.agentType);
1047
+ }
1048
+ }
1049
+ catch {
1050
+ // An unreadable meta leaves its dispatch unresolved, and countWindow
1051
+ // declines to count an unresolved dispatch. Never read as a success.
1052
+ }
1053
+ }
1054
+ return out;
1055
+ },
1056
+ });
1057
+ specialistCensus.start();
961
1058
  // Task 2285 — standing audit for public-agent knowledge curation. A
962
1059
  // `knowledgeKeywords` subscription nobody asked for is dormant until matching
963
1060
  // content lands, and a KNOWLEDGE.md that grows after deployment emits nothing
@@ -1135,6 +1232,14 @@ async function main() {
1135
1232
  // while the bypass counter for that day sat at zero, so no transition log
1136
1233
  // could have shown it. Emits one line per unreconciled document plus one
1137
1234
  // summary per run, zero count included. Purely filesystem — no Neo4j.
1235
+ //
1236
+ // The same tick also runs the HTML structure census, which reports every
1237
+ // client document holding a <style> element opened inside another one. That
1238
+ // fault renders the rest of the stylesheet as visible text and discards the
1239
+ // rule after the stray opener; the write gate refuses it at the write, but a
1240
+ // gate cannot see what is already on disk and a Bash heredoc writes a file
1241
+ // without passing one. Emits one line per malformed document plus one summary
1242
+ // per run, zero count included.
1138
1243
  const quoteReconcile = createQuoteDeliveryReconcile({
1139
1244
  accountsDir: dirname(config.accountDir),
1140
1245
  logger: log,
@@ -1182,6 +1287,26 @@ async function main() {
1182
1287
  notify: postBlockedNotifyViaFetch({ uiPort: uiPortForTail || '0', logger: log }),
1183
1288
  });
1184
1289
  blockedToolCensus.start();
1290
+ // Task 2446 — standing census over printed client documents. The PostToolUse
1291
+ // conformance gate only fires on a print, so four of the six ways a document
1292
+ // goes out with broken page chrome emit nothing at all and do not reproduce on
1293
+ // demand: the gate passing a defective PDF, the gate never matching the path
1294
+ // (account settings are written at provision time and never reconciled), a
1295
+ // template drifting back to a full-resolution asset, and a stale document never
1296
+ // re-rendered. Hourly rather than 60s because it spawns poppler per PDF and
1297
+ // nothing it watches changes faster than a print.
1298
+ const printCensusPlatformRoot = process.env.PLATFORM_ROOT ?? process.env.MAXY_PLATFORM_ROOT;
1299
+ if (printCensusPlatformRoot) {
1300
+ createPrintCensus({
1301
+ accountsRoot: dirname(config.accountDir),
1302
+ hookPath: join(printCensusPlatformRoot, 'plugins', 'admin', 'hooks', 'quote-render-pdf-conformance.sh'),
1303
+ intervalMs: 3_600_000,
1304
+ logger: log,
1305
+ }).start();
1306
+ }
1307
+ else {
1308
+ log('[quote-print-census] op=skip reason=no-platform-root');
1309
+ }
1185
1310
  // Task 278 — derives effectivePermissionMode from the per-session
1186
1311
  // auto-mode debug capture. http-server's jsonl-event subscriber drives it.
1187
1312
  const permissionModeTail = createPermissionModeTail({ logger: log });