@jrpool/kilotest 60.4.0 → 60.5.0

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 (48) hide show
  1. package/error.html +1 -0
  2. package/index.ts +6 -0
  3. package/lhm.plugin.json +5 -5
  4. package/mcp.ts +4 -4
  5. package/openapi-3.0.yaml +1 -1
  6. package/openapi.yaml +1 -1
  7. package/package.json +1 -1
  8. package/server.json +1 -1
  9. package/sitemap.xml +2 -0
  10. package/style.css +41 -0
  11. package/util.ts +4 -2
  12. package/web/accessibility/accessibility.test.ts +18 -0
  13. package/web/accessibility/index.html +29 -0
  14. package/web/accessibility/index.ts +19 -0
  15. package/web/ai0BalanceForm/index.html +1 -0
  16. package/web/deleteNotesForm/index.html +1 -0
  17. package/web/enqueue/index.html +1 -0
  18. package/web/enqueueForm/index.html +1 -0
  19. package/web/expungeReportsForm/index.html +1 -0
  20. package/web/footer.partial +9 -0
  21. package/web/hideReportForm/index.html +1 -0
  22. package/web/home/index.html +3 -3
  23. package/web/listDiagnoses/index.html +1 -0
  24. package/web/listIssues/index.html +1 -0
  25. package/web/listPages/index.html +1 -0
  26. package/web/listRules/index.html +1 -0
  27. package/web/listTopIssues/index.html +1 -0
  28. package/web/listViolators/index.html +1 -0
  29. package/web/manage/index.html +1 -0
  30. package/web/metrics/index.html +1 -0
  31. package/web/privacy/index.html +5 -3
  32. package/web/pruneReportsForm/index.html +1 -0
  33. package/web/reannotate/index.html +1 -0
  34. package/web/reannotateForm/index.html +1 -0
  35. package/web/renewWCAG/index.html +1 -0
  36. package/web/renewWCAGForm/index.html +1 -0
  37. package/web/requestNewTest/index.html +1 -0
  38. package/web/requestNewTestForm/index.html +1 -0
  39. package/web/requestRetest/index.html +1 -0
  40. package/web/requestRetestForm/index.html +1 -0
  41. package/web/rewindReportsForm/index.html +1 -0
  42. package/web/showHiddenReportsForm/index.html +1 -0
  43. package/web/terms/index.html +27 -0
  44. package/web/terms/index.ts +19 -0
  45. package/web/terms/terms.test.ts +18 -0
  46. package/web/tutorialAI/index.html +15 -14
  47. package/web/tutorialWeb/index.html +1 -0
  48. package/web/unhideReportForm/index.html +1 -0
package/error.html CHANGED
@@ -10,5 +10,6 @@
10
10
  <h1><a href="/">Kilotest</a>: error</h1>
11
11
  <p class="error">__error__</p>
12
12
  </main>
13
+ __footer__
13
14
  </body>
14
15
  </html>
package/index.ts CHANGED
@@ -41,8 +41,10 @@ import {handleMCP, mcpPath} from './mcp.ts';
41
41
  import fs from 'node:fs/promises';
42
42
  import {handleComment as handleTutorialWebComment} from './web/tutorialWeb/index.ts';
43
43
  import {answer as tutorialWeb} from './web/tutorialWeb/index.ts';
44
+ import {answer as accessibility} from './web/accessibility/index.ts';
44
45
  import {answer as home} from './web/home/index.ts';
45
46
  import {answer as privacy} from './web/privacy/index.ts';
47
+ import {answer as terms} from './web/terms/index.ts';
46
48
  import {answer as tutorialAI, handleComment as handleTutorialAIComment} from './web/tutorialAI/index.ts';
47
49
  import http, {type IncomingMessage, type ServerResponse} from 'node:http';
48
50
  import https from 'node:https';
@@ -106,6 +108,7 @@ type AnswerData = {
106
108
  type PageHandler = (...args: any[]) => Promise<AnswerData>;
107
109
 
108
110
  const answer: {
111
+ accessibility: PageHandler;
109
112
  ai0BalanceForm: PageHandler;
110
113
  deleteNotesForm: PageHandler;
111
114
  enqueue: PageHandler;
@@ -134,9 +137,11 @@ const answer: {
134
137
  requestNewTestForm: PageHandler;
135
138
  rewindReportsForm: PageHandler;
136
139
  showHiddenReportsForm: PageHandler;
140
+ terms: PageHandler;
137
141
  unhideReportForm: PageHandler;
138
142
  [key: string]: PageHandler | undefined;
139
143
  } = {
144
+ accessibility,
140
145
  ai0BalanceForm,
141
146
  deleteNotesForm,
142
147
  enqueue,
@@ -165,6 +170,7 @@ const answer: {
165
170
  requestNewTestForm,
166
171
  rewindReportsForm,
167
172
  showHiddenReportsForm,
173
+ terms,
168
174
  unhideReportForm
169
175
  };
170
176
  // Response functions of the API services.
package/lhm.plugin.json CHANGED
@@ -2778,7 +2778,7 @@
2778
2778
  "readOnlyHint": false,
2779
2779
  "destructiveHint": false,
2780
2780
  "idempotentHint": false,
2781
- "openWorldHint": false
2781
+ "openWorldHint": true
2782
2782
  },
2783
2783
  "execution": {
2784
2784
  "taskSupport": "forbidden"
@@ -3122,7 +3122,7 @@
3122
3122
  "readOnlyHint": false,
3123
3123
  "destructiveHint": false,
3124
3124
  "idempotentHint": false,
3125
- "openWorldHint": false
3125
+ "openWorldHint": true
3126
3126
  },
3127
3127
  "execution": {
3128
3128
  "taskSupport": "forbidden"
@@ -3763,7 +3763,7 @@
3763
3763
  "readOnlyHint": false,
3764
3764
  "destructiveHint": false,
3765
3765
  "idempotentHint": false,
3766
- "openWorldHint": false
3766
+ "openWorldHint": true
3767
3767
  },
3768
3768
  "execution": {
3769
3769
  "taskSupport": "forbidden"
@@ -4115,7 +4115,7 @@
4115
4115
  "readOnlyHint": false,
4116
4116
  "destructiveHint": false,
4117
4117
  "idempotentHint": false,
4118
- "openWorldHint": false
4118
+ "openWorldHint": true
4119
4119
  },
4120
4120
  "execution": {
4121
4121
  "taskSupport": "forbidden"
@@ -4423,5 +4423,5 @@
4423
4423
  }
4424
4424
  }
4425
4425
  ],
4426
- "version": "60.4.0"
4426
+ "version": "60.5.0"
4427
4427
  }
package/mcp.ts CHANGED
@@ -208,7 +208,7 @@ export const createMCPServer = (): McpServer => {
208
208
  readOnlyHint: false,
209
209
  idempotentHint: false,
210
210
  destructiveHint: false,
211
- openWorldHint: false
211
+ openWorldHint: true
212
212
  }
213
213
  },
214
214
  async ({description, URL, reason}) => {
@@ -228,7 +228,7 @@ export const createMCPServer = (): McpServer => {
228
228
  readOnlyHint: false,
229
229
  idempotentHint: false,
230
230
  destructiveHint: false,
231
- openWorldHint: false
231
+ openWorldHint: true
232
232
  }
233
233
  },
234
234
  async ({reportID, reason}) => {
@@ -268,7 +268,7 @@ export const createMCPServer = (): McpServer => {
268
268
  readOnlyHint: false,
269
269
  idempotentHint: false,
270
270
  destructiveHint: false,
271
- openWorldHint: false
271
+ openWorldHint: true
272
272
  }
273
273
  },
274
274
  async ({description, URL, reason}) => {
@@ -288,7 +288,7 @@ export const createMCPServer = (): McpServer => {
288
288
  readOnlyHint: false,
289
289
  idempotentHint: false,
290
290
  destructiveHint: false,
291
- openWorldHint: false
291
+ openWorldHint: true
292
292
  }
293
293
  },
294
294
  async ({reportID, reason}) => {
package/openapi-3.0.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.0.3
2
2
  info:
3
3
  title: Kilotest API
4
4
  description: 'Kilotest is an ensemble testing and reporting service for front-end web quality. It uses an ensemble of 12 rule engines to test web pages for front-end quality (accessibility, usability, and web standards, including HTML, CSS, ARIA, and WCAG). Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
5
- version: 60.4.0
5
+ version: 60.5.0
6
6
  license:
7
7
  name: MIT
8
8
  url: https://github.com/jrpool/kilotest/blob/main/LICENSE
package/openapi.yaml CHANGED
@@ -2,7 +2,7 @@ openapi: 3.1.0
2
2
  info:
3
3
  title: Kilotest API
4
4
  description: 'Kilotest is an ensemble testing and reporting service for front-end web quality. It uses an ensemble of 12 rule engines to test web pages for front-end quality (accessibility, usability, and web standards, including HTML, CSS, ARIA, and WCAG). Kilotest acts as a web server for human users, an MCP server for AI platforms, and an API for programmatic access. With this API you can request that a page be tested or retested, discover available reports, incrementally retrieve facts from a report: from what reports are available, to what issues were reported in one report, to what elements violated one issue, to what diagnoses rule engines gave for one violation.'
5
- version: 60.4.0
5
+ version: 60.5.0
6
6
  license:
7
7
  name: MIT
8
8
  identifier: MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "60.4.0",
3
+ "version": "60.5.0",
4
4
  "description": "Ensemble testing for front-end web quality",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/server.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/jrpool/kilotest",
7
7
  "source": "github"
8
8
  },
9
- "version": "60.4.0",
9
+ "version": "60.5.0",
10
10
  "remotes": [
11
11
  {
12
12
  "type": "streamable-http",
package/sitemap.xml CHANGED
@@ -7,6 +7,8 @@
7
7
  <url><loc>https://kilotest.com/manage.html</loc></url>
8
8
  <url><loc>https://kilotest.com/tutorial.html</loc></url>
9
9
  <url><loc>https://kilotest.com/privacy.html</loc></url>
10
+ <url><loc>https://kilotest.com/terms.html</loc></url>
11
+ <url><loc>https://kilotest.com/accessibility.html</loc></url>
10
12
  <url><loc>https://kilotest.com/openapi.yaml</loc></url>
11
13
  <url><loc>https://kilotest.com/llms.txt</loc></url>
12
14
  <url><loc>https://kilotest.com/llms-full.txt</loc></url>
package/style.css CHANGED
@@ -74,6 +74,25 @@ fieldset {
74
74
  form {
75
75
  margin-top: 1rem;
76
76
  }
77
+ footer {
78
+ margin-top: 3rem;
79
+ padding-top: 1rem;
80
+ border-top: solid 0.1rem #000;
81
+ }
82
+ .footer-inner ul {
83
+ margin: 0;
84
+ padding: 0;
85
+ list-style: none;
86
+ }
87
+ .footer-inner li {
88
+ display: inline-block;
89
+ }
90
+ .footer-inner a {
91
+ display: inline-block;
92
+ min-height: 44px;
93
+ padding: 0.5rem 0.25rem;
94
+ margin-right: 1.5rem;
95
+ }
77
96
  h4, h5, h6 {
78
97
  margin-top: 1rem;
79
98
  margin-bottom: 0;
@@ -469,3 +488,25 @@ body.styled .warn {
469
488
  border: 1px solid #e8d48b;
470
489
  border-radius: 0.5rem;
471
490
  }
491
+ body.styled footer {
492
+ background: var(--card);
493
+ border-top: 1px solid var(--line);
494
+ }
495
+ body.styled .footer-inner {
496
+ max-width: 64rem;
497
+ margin-inline: auto;
498
+ padding: 1rem 1.5rem;
499
+ }
500
+ body.styled .footer-inner ul {
501
+ display: flex;
502
+ flex-wrap: wrap;
503
+ gap: 0.25rem 1.75rem;
504
+ }
505
+ body.styled .footer-inner a {
506
+ font-size: 0.9rem;
507
+ color: var(--muted);
508
+ }
509
+ body.styled .footer-inner a:hover {
510
+ color: var(--accent);
511
+ background-color: transparent;
512
+ }
package/util.ts CHANGED
@@ -376,9 +376,9 @@ export const getPlainText = (string: string): string => string
376
376
  .replace(/&/g, '+')
377
377
  .replace(/[<>"']/g, ' ');
378
378
  // Markup shared by populated templates, lazily read once from files.
379
- let sharedContent: {head: string, header: string, headerNL: string, logo: string} | undefined;
379
+ let sharedContent: {head: string, header: string, headerNL: string, footer: string, logo: string} | undefined;
380
380
  // Returns the markup shared by populated templates.
381
- const getSharedContent = async (): Promise<{head: string, header: string, headerNL: string, logo: string}> => {
381
+ const getSharedContent = async (): Promise<{head: string, header: string, headerNL: string, footer: string, logo: string}> => {
382
382
  // Trailing newlines are stripped so injection does not add blank lines.
383
383
  if (!sharedContent) {
384
384
  const webDir = path.join(import.meta.dirname, 'web');
@@ -390,6 +390,7 @@ const getSharedContent = async (): Promise<{head: string, header: string, header
390
390
  header,
391
391
  // The home page gets the same header with its brand as text, not a link to itself.
392
392
  headerNL: header.replace('<a class="brand" href="/">', '<span class="brand">').replace('</a>', '</span>'),
393
+ footer: (await fs.readFile(path.join(webDir, 'footer.partial'), 'utf8')).trimEnd(),
393
394
  logo
394
395
  };
395
396
  }
@@ -405,6 +406,7 @@ export const populateFile = async (filePath: string, query: Record<string, strin
405
406
  .replace(/__head__/g, () => shared.head)
406
407
  .replace(/__headerNL__/g, () => shared.headerNL)
407
408
  .replace(/__header__/g, () => shared.header)
409
+ .replace(/__footer__/g, () => shared.footer)
408
410
  .replace(/__logo__/g, () => shared.logo);
409
411
  // Replace its placeholders.
410
412
  Object.keys(query).forEach(param => {
@@ -0,0 +1,18 @@
1
+ /*
2
+ accessibility.test.ts
3
+ Unit tests for web/accessibility/index.ts, covering the answer export.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ import {test} from 'node:test';
9
+ import assert from 'node:assert/strict';
10
+ import {answer} from './index.ts';
11
+
12
+ // TESTS
13
+
14
+ test('answer returns the accessibility statement page', async () => {
15
+ const result = await answer();
16
+ assert.equal(result.status, 'ok');
17
+ assert.ok(result.answerPage.includes('WCAG'));
18
+ });
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ __head__
5
+ <meta name="description" content="Kilotest accessibility statement: the accessibility goals, testing, and feedback channel for kilotest.com">
6
+ <title>Accessibility statement | Kilotest</title>
7
+ </head>
8
+ <body class="styled">
9
+ __header__
10
+ <main class="page">
11
+ <h1>Accessibility statement</h1>
12
+ <p>This statement applies to the Kilotest web site at <code>kilotest.com</code>. It was last updated in October 2026.</p>
13
+ <h2>Policy</h2>
14
+ <p>Kilotest intends to have a simple, intuitive, and accessible web interface that conforms to Level AAA of Web Content Accessibility Guidelines (WCAG) 2.2 and best practices defined by various accessibility experts. One requirement that Kilotest imposes on itself is that no page exhibits any issues other than lowest-priority issues when tested by Kilotest itself. Any lowest-priority issues will be remediated or their justifications will be documented on this page.</p>
15
+ <h2>Unremediated issues</h2>
16
+ <p>Kilotest has reported these lowest-priority issues:</p>
17
+ <ul>
18
+ <li><strong>large visible-element count</strong> (<code>visibleBulk</code>) on the list-pages page: justified by the existence of more than 100 tested pages</li>
19
+ <li><strong>inconsistent heading, link, or button styles</strong> (<code>incnsistentStyles</code>) on the list-pages page: under investigation</li>
20
+ </ul>
21
+ <p>The testing of Kilotest pages is incomplete, so additional unremediated issues may remain.</p>
22
+ <h2>Known limitations</h2>
23
+ <p>Reports about third-party pages quote elements of those pages, such as tag names, attributes, and text excerpts. Kilotest does not control the accessibility of quoted content or of the tested pages themselves.</p>
24
+ <h2>Comments</h2>
25
+ <p>If you encounter an accessibility barrier on this site, or if any content is hard for you to perceive or operate, email <a href="mailto:info@kilotest.com">info@kilotest.com</a> or submit an issue on <a href="https://github.com/jrpool/kilotest/issues">GitHub</a>. Reported barriers are treated as defects and prioritized for remediation.</p>
26
+ </main>
27
+ __footer__
28
+ </body>
29
+ </html>
@@ -0,0 +1,19 @@
1
+ /*
2
+ index.ts
3
+ Serves the accessibility statement.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ import {populateTemplate} from '../../util.ts';
9
+
10
+ // FUNCTIONS
11
+
12
+ // Returns the accessibility statement page.
13
+ export const answer = async () => {
14
+ const answerPage = await populateTemplate(import.meta.dirname, {});
15
+ return {
16
+ status: 'ok',
17
+ answerPage
18
+ };
19
+ };
@@ -21,5 +21,6 @@
21
21
  <p><button type="submit">Submit</button></p>
22
22
  </form>
23
23
  </main>
24
+ __footer__
24
25
  </body>
25
26
  </html>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit" __disabled__>Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -14,5 +14,6 @@
14
14
  <p>Once the job has been completed, it will appear in the answer to the question, <q>Which web pages have been tested?</q>.</p>
15
15
  <p>All recommendations for the retest of the __target__ page have been deleted.</p>
16
16
  </main>
17
+ __footer__
17
18
  </body>
18
19
  </html>
@@ -24,5 +24,6 @@
24
24
  <p><button type="submit" __disabled__>Submit</button></p>
25
25
  </form>
26
26
  </main>
27
+ __footer__
27
28
  </body>
28
29
  </html>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit" __disabled__>Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -0,0 +1,9 @@
1
+ <footer>
2
+ <nav class="footer-inner" aria-label="Site">
3
+ <ul>
4
+ <li><a href="/privacy.html">Privacy policy</a></li>
5
+ <li><a href="/terms.html">Terms of service</a></li>
6
+ <li><a href="/accessibility.html">Accessibility statement</a></li>
7
+ </ul>
8
+ </nav>
9
+ </footer>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit">Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -77,9 +77,9 @@
77
77
  <h2>Who are you?</h2>
78
78
  <h3>If you are a human user on the web</h3>
79
79
  <p>You can use Kilotest starting on this page.</p>
80
- <p>If your main interest is accessibility, feel free to learn more about it with our <a href="/tutorialWeb.html">tutorial</a>.</p>
80
+ <p>There is an <a href="/tutorialWeb.html">in-depth explanation of how Kilotest tests for accessibility</a>.</p>
81
81
  <h3>If you are a human user of AI</h3>
82
- <p>An AI assistant can use the Kilotest MCP server to give you precise answers about the front-end quality of a web page. If the AI assistant does not already have permission to use Kilotest, you can grant that permission. <a href="/tutorialAI.html">Learn how to connect AI platforms to Kilotest</a>.</p>
82
+ <p>An AI assistant can use Kilotest to analyze the quality of a web page more precisely and comprehensively. There is a <a href="/tutorialAI.html">step-by-step guide on using Kilotest with AI</a>.</p>
83
83
  <h3>If you are an AI agent or model</h3>
84
84
  <p>Go to the <a href="/mcp">Kilotest MCP server</a>.</p>
85
85
  <h3>If you are developing an application</h3>
@@ -99,9 +99,9 @@
99
99
  <h2 id="more-heading">More …</h2>
100
100
  <ul class="nav">
101
101
  <li><a href="manage.html"><span class="card-title">Management actions</span><span class="card-desc">Approval, queue, and report administration for managers.</span></a></li>
102
- <li><a href="privacy.html"><span class="card-title">Privacy policy</span><span class="card-desc">What Kilotest collects, stores, and shares.</span></a></li>
103
102
  </ul>
104
103
  </section>
105
104
  </main>
105
+ __footer__
106
106
  </body>
107
107
  </html>
@@ -22,5 +22,6 @@ __takeMeThere__
22
22
  __diagnoses__
23
23
  </ol>
24
24
  </main>
25
+ __footer__
25
26
  </body>
26
27
  </html>
@@ -47,5 +47,6 @@ __history__
47
47
  <p><a href="/tutorialAI.html">Make Kilotest available to an AI assistant</a>. Then give it a prompt like this:</p>
48
48
  <blockquote><q>Kilotest reports issues on the __target__ web page. Describe them and propose a plan to resolve the genuine defects.</q></blockquote>
49
49
  </main>
50
+ __footer__
50
51
  </body>
51
52
  </html>
@@ -14,5 +14,6 @@ __jobSections__
14
14
  <h2>Already tested</h2>
15
15
  __testedPages__
16
16
  </main>
17
+ __footer__
17
18
  </body>
18
19
  </html>
@@ -17,5 +17,6 @@
17
17
  <h2>Rules</h2>
18
18
  __rules__
19
19
  </main>
20
+ __footer__
20
21
  </body>
21
22
  </html>
@@ -11,5 +11,6 @@
11
11
  <p>These are the issues reported most often. If a page has been tested more than once, only its last test is counted.</p>
12
12
  __issues__
13
13
  </main>
14
+ __footer__
14
15
  </body>
15
16
  </html>
@@ -20,5 +20,6 @@ __issueFacts__
20
20
  __violators__
21
21
  </ul>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -25,5 +25,6 @@
25
25
  <li><a href="/metrics.html">View usage metrics</a></li>
26
26
  </ul>
27
27
  </main>
28
+ __footer__
28
29
  </body>
29
30
  </html>
@@ -10,5 +10,6 @@
10
10
  <h1><a href="/">Kilotest</a>: Usage metrics</h1>
11
11
  __body__
12
12
  </main>
13
+ __footer__
13
14
  </body>
14
15
  </html>
@@ -5,9 +5,10 @@
5
5
  <meta name="description" content="Kilotest privacy policy: what information Kilotest collects, uses, shares, and keeps">
6
6
  <title>Privacy policy | Kilotest</title>
7
7
  </head>
8
- <body>
9
- <main>
10
- <h1><a href="/">Kilotest</a>: Privacy policy</h1>
8
+ <body class="styled">
9
+ __header__
10
+ <main class="page">
11
+ <h1>Privacy policy</h1>
11
12
  <p>This policy applies to the Kilotest web site, API, and MCP server at <code>kilotest.com</code>, and does not apply to any other deployment of Kilotest. Kilotest does not require an account, does not ask for your name or email address, and does not use advertising or tracking cookies.</p>
12
13
  <h2>What Kilotest collects</h2>
13
14
  <ul>
@@ -28,5 +29,6 @@
28
29
  <h2>Changes and contact</h2>
29
30
  <p>Changes to this policy are recorded in the <a href="https://github.com/jrpool/kilotest">public repository</a>. Questions can be sent to <a href="mailto:info@kilotest.com">info@kilotest.com</a>.</p>
30
31
  </main>
32
+ __footer__
31
33
  </body>
32
34
  </html>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit" __disabled__>Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -10,5 +10,6 @@
10
10
  <h1><a href="/">Kilotest</a>: Reannotation order</h1>
11
11
  <p>The latest report on each target has been reannotated.</p>
12
12
  </main>
13
+ __footer__
13
14
  </body>
14
15
  </html>
@@ -20,5 +20,6 @@
20
20
  <p>__how__</p>
21
21
  __reannotateForm__
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -10,5 +10,6 @@
10
10
  <h1><a href="/">Kilotest</a>: WCAG map renewed</h1>
11
11
  <p>The WCAG map has been renewed.</p>
12
12
  </main>
13
+ __footer__
13
14
  </body>
14
15
  </html>
@@ -16,5 +16,6 @@
16
16
  <p><button type="submit">Submit</button></p>
17
17
  </form>
18
18
  </main>
19
+ __footer__
19
20
  </body>
20
21
  </html>
@@ -14,5 +14,6 @@
14
14
  <p>If a <a href="/enqueueForm.html">Kilotest manager approves this request</a>, a test order will be added to the queue.</p>
15
15
  <p>In most cases, if you check Kilotest again in 1 day, you will find that the requested job has been performed.</p>
16
16
  </main>
17
+ __footer__
17
18
  </body>
18
19
  </html>
@@ -25,5 +25,6 @@
25
25
  <p><button type="submit">Submit</button></p>
26
26
  </form>
27
27
  </main>
28
+ __footer__
28
29
  </body>
29
30
  </html>
@@ -14,5 +14,6 @@
14
14
  <p>If a <a href="/enqueueForm.html">Kilotest manager approves this request</a>, a test order will be added to the queue.</p>
15
15
  <p>In most cases, if you check Kilotest again in 1 day, you will find that the requested test has been performed.</p>
16
16
  </main>
17
+ __footer__
17
18
  </body>
18
19
  </html>
@@ -18,5 +18,6 @@
18
18
  <p><button type="submit">Submit</button></p>
19
19
  </form>
20
20
  </main>
21
+ __footer__
21
22
  </body>
22
23
  </html>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit" __disabled__>Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>
@@ -15,5 +15,6 @@
15
15
  <p><button type="submit">Submit</button></p>
16
16
  </form>
17
17
  </main>
18
+ __footer__
18
19
  </body>
19
20
  </html>
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-US">
3
+ <head>
4
+ __head__
5
+ <meta name="description" content="Kilotest terms of service: rules for using the Kilotest web site, API, and MCP server">
6
+ <title>Terms of service | Kilotest</title>
7
+ </head>
8
+ <body class="styled">
9
+ __header__
10
+ <main class="page">
11
+ <h1>Terms of service</h1>
12
+ <p>These terms apply to the Kilotest web site, API, and MCP server at <code>kilotest.com</code>, and do not apply to any other deployment of Kilotest. By using Kilotest you accept these terms. Kilotest is free and does not require an account.</p>
13
+ <h2>What Kilotest does</h2>
14
+ <p>Kilotest tests publicly reachable web pages for front-end quality (accessibility, usability, and web standards) with an ensemble of rule engines, stores the results as reports, and makes the reports publicly available through its web site, API, and MCP server. Owners of tested pages can request deletion of reports under the <a href="/privacy.html">privacy policy</a>.</p>
15
+ <h2>What you submit</h2>
16
+ <p>When you request or order a test or retest, you ask Kilotest to fetch the page and publish a report about it. You do not need the page owner&rsquo;s permission to do so. Submit only publicly reachable URLs, and do not submit URLs that require credentials or that would put secrets into a public report. Kilotest may reject any request or order.</p>
17
+ <h2>Acceptable use</h2>
18
+ <p>Do not use Kilotest to attack, probe, or overload web sites, including this one, and do not submit unlawful or deceptive content. Kilotest may rate-limit, refuse, or block any use.</p>
19
+ <p>Reports attribute results to third-party rule engines, whose own terms may restrict the use of those results. In particular, results derived from WAVE are subject to the <a href="https://wave.webaim.org/terms">WAVE terms of use</a>, which prohibit their use for any purpose related to a legal action without written permission from WebAIM.</p>
20
+ <h2>No warranty</h2>
21
+ <p>Kilotest and its reports are provided as is. Automated rule engines can produce incomplete or incorrect results. Kilotest runs multiple rule engines and discloses selected results from them with attribution to them, but results disclosed from any particular rule engine differ in detail from the results that the same rule engine would produce if run directly. A Kilotest report is not a certification of conformance with WCAG or any other standard or law, and it is not legal advice. Kilotest is not liable for decisions made on the basis of a report.</p>
22
+ <h2>Changes and contact</h2>
23
+ <p>Changes to these terms are recorded in the <a href="https://github.com/jrpool/kilotest">public repository</a>. Questions can be sent to <a href="mailto:info@kilotest.com">info@kilotest.com</a>.</p>
24
+ </main>
25
+ __footer__
26
+ </body>
27
+ </html>
@@ -0,0 +1,19 @@
1
+ /*
2
+ index.ts
3
+ Serves the terms of service.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ import {populateTemplate} from '../../util.ts';
9
+
10
+ // FUNCTIONS
11
+
12
+ // Returns the terms of service page.
13
+ export const answer = async () => {
14
+ const answerPage = await populateTemplate(import.meta.dirname, {});
15
+ return {
16
+ status: 'ok',
17
+ answerPage
18
+ };
19
+ };
@@ -0,0 +1,18 @@
1
+ /*
2
+ terms.test.ts
3
+ Unit tests for web/terms/index.ts, covering the answer export.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ import {test} from 'node:test';
9
+ import assert from 'node:assert/strict';
10
+ import {answer} from './index.ts';
11
+
12
+ // TESTS
13
+
14
+ test('answer returns the terms of service page', async () => {
15
+ const result = await answer();
16
+ assert.equal(result.status, 'ok');
17
+ assert.ok(result.answerPage.includes('provided as is'));
18
+ });
@@ -82,20 +82,6 @@
82
82
  <li>Save the connector.</li>
83
83
  </ol>
84
84
  </details>
85
- <details id="vibe">
86
- <summary>Vibe</summary>
87
- <p>These instructions apply to Mistral <a href="https://chat.mistral.ai/work">Vibe</a>.</p>
88
- <ol>
89
- <li>Choose the Work tab.</li>
90
- <li>Click <q>Connect your apps for better answers</q>.</li>
91
- <li>Click the <q>+ Add connector</q> button.</li>
92
- <li>Click the <q>Add a custom connector</q> button.</li>
93
- <li>Enter <q>Kilotest</q> into the <q>Connector name</q> input.</li>
94
- <li>Enter <q>https://kilotest.com/mcp</q> into the <q>Server</q> input.</li>
95
- <li>Click the <q>Add connector</q> button.</li>
96
- <li>Toggle the <q>Ask/Allow</q> buttons to show <q>Allow</q>.</li>
97
- </ol>
98
- </details>
99
85
  <details id="perplexity">
100
86
  <summary>Perplexity</summary>
101
87
  <p>These instructions apply to <a href="https://www.perplexity.ai/">Perplexity</a> Pro in a browser.</p>
@@ -111,6 +97,20 @@
111
97
  </ol>
112
98
  <p>Once you add Kilotest, it <strong>may</strong> become available in the Perplexity app on your computer or mobile device, too.</p>
113
99
  </details>
100
+ <details id="vibe">
101
+ <summary>Vibe</summary>
102
+ <p>These instructions apply to Mistral <a href="https://chat.mistral.ai/work">Vibe</a>.</p>
103
+ <ol>
104
+ <li>Choose the Work tab.</li>
105
+ <li>Click <q>Connect your apps for better answers</q>.</li>
106
+ <li>Click the <q>+ Add connector</q> button.</li>
107
+ <li>Click the <q>Add a custom connector</q> button.</li>
108
+ <li>Enter <q>Kilotest</q> into the <q>Connector name</q> input.</li>
109
+ <li>Enter <q>https://kilotest.com/mcp</q> into the <q>Server</q> input.</li>
110
+ <li>Click the <q>Add connector</q> button.</li>
111
+ <li>Toggle the <q>Ask/Allow</q> buttons to show <q>Allow</q>.</li>
112
+ </ol>
113
+ </details>
114
114
  <h2 id="other">Other AI platforms</h2>
115
115
  <p>You can connect Kilotest to some other AI platforms, too. The instructions above are limited to consumer platforms that are either free or relatively inexpensive (US$20 per month or less). Business platforms such as ChatGPT Business, and developer platforms such as Devin Desktop, also permit you to enable Kilotest.</p>
116
116
  <p>Feel free to submit a comment below about empowering any AI platform to use Kilotest.</p>
@@ -234,5 +234,6 @@
234
234
  color: #1a4a1a;
235
235
  }
236
236
  </style>
237
+ __footer__
237
238
  </body>
238
239
  </html>
@@ -633,5 +633,6 @@
633
633
  }
634
634
  });
635
635
  </script>
636
+ __footer__
636
637
  </body>
637
638
  </html>
@@ -20,5 +20,6 @@
20
20
  <p><button type="submit">Submit</button></p>
21
21
  </form>
22
22
  </main>
23
+ __footer__
23
24
  </body>
24
25
  </html>