@jrpool/kilotest 36.1.1 → 37.0.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.
@@ -185,4 +185,4 @@ The [Perplexity documentation](https://www.perplexity.ai/help-center/en/articles
185
185
 
186
186
  Once the compatibility of Kilotest as a connector with AI platforms of two different vendors had been confirmed, the focus of work returned to completion of the missing endpoints of the API. The first was an endpoint that would let a model efficiently search for an available report about a particular web page.
187
187
 
188
- The new `identifyReportsAboutMatchingWebPages` tool provides inputs for fragments of a description and of a URL hostname of a web page and responds with summary data about all and only the available reports of pages that match at least one of those fragments, where matching means either including or being included by the provided fragment, case-insensitively.
188
+ The new `summarizeQualityOfMatchingWebPages` tool provides inputs for fragments of a description and of a URL hostname of a web page and responds with summary data about all and only the available reports of pages that match at least one of those fragments, where matching means either including or being included by the provided fragment, case-insensitively.
@@ -0,0 +1,110 @@
1
+ ---
2
+ date: 2026-07-09
3
+ status: proposed
4
+ ---
5
+
6
+ # API design
7
+
8
+ ## Context and problem
9
+
10
+ The UI of Kilotest offers human non-manager users opportunities to influence and to interrogate the data managed by the application. The data are organized into reports. Each report contains the results of one session in which 10 rule engines were used for testing the front-end quality of one web page.
11
+
12
+ The opportunities to interrogate the data in the UI are organized as a hierarchy of granularity:
13
+
14
+ 1. All available reports
15
+ 2. All issues from one report
16
+ 3. All violators of one issue from one report
17
+ 4. All diagnoses for one violator of one issue from one report
18
+
19
+ A violator is a particular element (HTML, SVG, etc.) on the page that some rule engine reported having violated a particular rule of the rule engine. If the rule classifier used by Kilotest classifies that rule as belonging to a particular issue, then that element is referred to as a violator of that issue.
20
+
21
+ This hierarchical design is based on a realistic assumption about how human users interact with Kilotest. They visit its home page and begin what to them is a session. Although requests to Kilotest are stateless, the response at each level includes links that contain all the specifications required for a request at the next level. For example, the response to a request at level 3 includes, for each violator, a link that makes a request at level 4 and includes identifiers of the page, the issue and the violator.
22
+
23
+ The responses to requests in the UI at any level include a summary of some of the information about the previous levels. For example, a response at level 3 includes a summary of information about the report and about the issues in that report. The prior-level summarized information is based on assumptions about what a typical human user would value. For example, at level 3, the prior-level information does not summarize all the available reports, but does include a list of the rule engines that succeeded and failed in testing the page and the counts of issues reported.
24
+
25
+ These assumptions for human UI users may or may not be valid for how LLMs interact with the Kilotest API. Those interactions may vary depending on the tasks that they are performing. Consider three scenarios:
26
+
27
+ 1. A user asks an LLM for all available information about the front-end quality of a particular web page.
28
+ 2. A user asks an LLM for all the available information about issues related to a particular topic, such as keyboard navigation, for a particular web page.
29
+ 3. A user asks an LLM to summarize the front-end quality of a particular web page; having consumed the summary, asks the LLM for a summary of information about one of the reported issues; having consumed that summary, asks the LLM for a summary of information about one of the reported violators of that issue; and, having consumed that summary, asks the LLM for a summary of information about the diagnoses for that violator of that issue.
30
+
31
+ Scenario 1 seems to justify an API that can aggregate all the information about the latest report about the page into a single response.
32
+
33
+ Scenario 2 seems to justify an API that offers enough information about all the available reports and all the defined issues to allow the LLM to make a request at level 3 for a particular issue in a particular report.
34
+
35
+ Scenario 3 seems to justify an API that mimics the UI in structure, but perhaps not in the prior-levels information provided at each level.
36
+
37
+ Even these apparently justified API designs depend on the assumption that users mean what they say, particularly in scenario 1. A user who asks for **all** available information about the front-end quality of a particular web page may do so because of ignorance about how voluminous that information is, and the real wish may be more conditional: all the information if there is not much, but otherwise a summary so I can select what I want to learn more about.
38
+
39
+ Uncertainty about how LLMs will interact with the API creates a design problem. How should the API be further developed?
40
+
41
+ As of the date of this decision, a partial initial API version already exists: an API that mimics the UI for levels 1, 2, and 3. For each level, the MCP server provides a tool.
42
+
43
+ ## Considered options
44
+
45
+ 1. **Iterate and instrument.** (1) Add a tool that implements level 4; then (2) add a tool that asks LLMs to comment on how the API design could better satisfy their needs; then (3) add metrics to make API usage and submitted LLM comments available to Kilotest managers.
46
+ 2. **Research first.** (1) Pause further API development while doing fundamental research to predict LLM needs; then (2) resume API and metrics development, including API redesign if the research results warrant.
47
+
48
+ ## Decision
49
+
50
+ The decision is to adopt **option 1: iterate and instrument**.
51
+
52
+ ## Empirical basis
53
+
54
+ The decision is based on the fact that, even without a pause for fundamental research, there is enough empirical evidence to justify this decision.
55
+
56
+ ### Completion of the 4-level hierarchy
57
+
58
+ There is empirical support for an API that assumes scenario 3, i.e. incremental rather than one-shot interrogation. Both single-shot comprehensive requests and incremental drill-downs occur in significant numbers in real-world LLM use.
59
+
60
+ - Jian et al. (2024) studied experienced ChatGPT users and found that **43.8% of prompts were single-component**, **38.2% were dual-component**, and only **18.0% were multi-component**. A request such as scenario 1 ("tell me everything about page X") or scenario 2 ("tell me about defect class X on page Y") is structurally common because it is typically a single-component prompt.
61
+ - At the same time, follow-up refinement is routine. Mysore et al. (2025) analyzed large-scale Bing Copilot and WildChat writing sessions and report: “Rather than passively accepting output, users actively refine, explore, and co-construct text.” This matches scenario 3.
62
+
63
+ For scenario 3, current LLM tool-use patterns do not require the model to restart at level 1. Anthropic's tool-use documentation describes an agentic loop in which the full conversation history is kept and “every turn sees the complete prior context”. Cohere’s multi-step tool-use documentation explains that the model can use information learned from one tool call to parameterize a subsequent call. MCP’s typed tool schemas support this pattern. Therefore the existing hierarchy can be expected to be practical in scenario 3.
64
+
65
+ ### Usage and suggestion metrics
66
+
67
+ There is also empirical support for modesty in any estimate of the adequacy of the current or any other single API design. As found by Zhu et al. (2025), “users do not transfer existing conversational norms to LLM interactions, but instead develop new registers with distinct pragmatic features.” Metrics will help to inform the contributors to the API about how LLMs are actually using it and how they want it to be improved.
68
+
69
+ ## Cost and context-window constraints
70
+
71
+ A user-friendly rendering of an entire Kilotest report is estimated at about 5 MB of text, or roughly 1.25 million tokens. This exceeds the 200,000-token context window of Claude 3.5 Sonnet, so the model cannot consume the whole report in one prompt. If it could be passed whole, each pass would cost roughly $3.75 in input tokens at current pricing, and every subsequent question about it would require re-sending it. By contrast, a four-level drill-down through report → issue → violator → diagnosis costs roughly $0.07 for a typical path. An intuitive guess is that a typical conversation would involve 1 report, 2 issues, and 3 violators per issue. Delivering such results with the full-report method would require 2 issue passes and 6 violator passes beyond the initial pass, for a total of about $33.75. Doing so incrementally would cost about $0.26, which is only **1/130th** of the cost of the same result with the full-report strategy. Even if a user initially wanted a comprehensive report and then wanted an LLM to find and interpret it, the impact of that strategy on cost would likely motivate the user to switch to an incremental strategy.
72
+
73
+ ## Sub-decision: ancestor information in level responses
74
+
75
+ Given this decision, a secondary decision to make is what information from prior levels to repeat in a response. Three alternatives were considered:
76
+
77
+ 1. **Identifiers only:** The report, issue, and violator would be described by their unique identifiers only. The LLM would use the identifiers to retrieve from its conversation-history context any information needed about them.
78
+ 2. **Identifiers plus labels:** The report, issue, and violator would be described by their unique identifiers and human-interpretable labels. If the LLM needs more information about them than what their labels provide, the LLM would use the identifiers to retrieve from its conversation-history context that additional information.
79
+ 3. **Cumulative responses:** All the information from the prior responses would be repeated, so that any needed information would be available in the current response and no search of the conversation history would be needed.
80
+
81
+ The sub-decision was **identifiers plus labels** (option 2). This decision was based on cost and reliability, as follows.
82
+
83
+ - **Cost:** Option 3 would probably make a four-level drill-down several times as expensive as option 2, because of the large response volumes.
84
+ - **Reliability:** Option 1 would entail a greater risk of information loss and hallucination than option 2, because the LLM could be unable to retrieve the needed information using identifiers if its history were truncated, if a tool were invoked in isolation, or if the model were asked later to summarize findings in natural language.
85
+
86
+ ## Implementation plan
87
+
88
+ - The existing MCP tools for levels 1, 2, and 3 will be revised to remove excess information about prior levels and include only identifiers and labels for them.
89
+ - Level 4 will be implemented as an MCP tool that returns the diagnoses for one violator of one issue in one report.
90
+ - A suggestions tool will be provided so that LLM-based clients can report friction or suggest improvements to the API design.
91
+ - Usage metrics will be defined, captured, and recorded so that Kilotest managers can observe which levels, issues, and patterns are most common and what suggestions have been received.
92
+ - If the empirical data later show that the API does not serve some common scenario well, the API will be redesigned accordingly.
93
+
94
+ ### Risks and mitigations
95
+
96
+ - **Risk:** The hierarchy may not match the way LLMs actually want to query the data.
97
+ - **Mitigation:** The suggestions tool and usage metrics will surface mismatches early.
98
+ - **Risk:** The cost estimate assumes a well-behaved client that preserves conversation history; a poorly implemented client could still incur higher-than-necessary costs.
99
+ - **Mitigation:** MCP clients are expected to maintain message history by protocol; the ancestor labels provide a minimal human-friendly substitute.
100
+ - **Risk:** Scenario 1 users may still want an aggregated "everything about page X" response.
101
+ - **Mitigation:** A future tool can be added to aggregate the hierarchy on the server side and return a structured summary, but that decision is deferred until usage data justify it.
102
+
103
+ ## References
104
+
105
+ - Jian, J., et al. (2024). [Understanding User Prompting Behavior in Generative AI](https://dl.acm.org/doi/abs/10.1002/pra2.1318).
106
+ - Mysore, S., et al. (2025). [Prototypical Human-AI Collaboration Behaviors from LLM-Assisted Writing in the Wild](https://aclanthology.org/2025.emnlp-main.852/).
107
+ - Zhu, S., et al. (2025). [Show or Tell? Modeling the evolution of request-making in human-LLM conversations](https://arxiv.org/html/2508.01213v2).
108
+ - Anthropic. [Tutorial: Build a tool-using agent](https://platform.claude.com/docs/en/agents-and-tools/tool-use/build-a-tool-using-agent).
109
+ - Cohere. [Multi-step Tool Use](https://docs.cohere.com/v1/docs/multi-step-tool-use).
110
+ - [Model Context Protocol specification](https://modelcontextprotocol.io/specification/2025-06-18/server/tools).
package/index.js CHANGED
@@ -342,10 +342,10 @@ const requestHandler = async (request, response) => {
342
342
  // Otherwise, if it is for an API service:
343
343
  else if (pageName === 'api') {
344
344
  const [service, ... specs] = pathTail.split('/');
345
- // If the service is provision of facts about the available reports:
346
- if (service === 'targets') {
345
+ // If the service is provision of a list of all available reports:
346
+ if (service === 'reportList') {
347
347
  // Get the response (potentially error) data.
348
- const responseData = await require(path.join(__dirname, 'targets', 'api')).response(specs);
348
+ const responseData = await require(path.join(__dirname, 'reportList', 'api')).response(specs);
349
349
  // Send them.
350
350
  setHeaders('application/json', null, 'ultra');
351
351
  response.end(JSON.stringify(responseData));
@@ -702,7 +702,7 @@ const requestHandler = async (request, response) => {
702
702
  // Otherwise, if the first segment is the report finding service:
703
703
  else if (segments[0] === 'target') {
704
704
  const {what = '', hostname = ''} = postData;
705
- // If the payload contains a description fragment or URL fragment:
705
+ // If the payload contains a description fragment or hostname fragment:
706
706
  if (what || hostname) {
707
707
  // Process the request and get the response data.
708
708
  const responseData = await require(path.join(__dirname, 'target', 'api'))
package/llms-full.txt CHANGED
@@ -82,10 +82,10 @@ The implementation is currently in an alpha phase and offers 4 tools:
82
82
  - payload properties
83
83
  - `what`: all or part of a description of the page
84
84
  - `hostname`: all or part of the hostname of the page
85
- - `summarizeQualityOfAllTestedWebPages`
85
+ - `getListOfAllAvailableReports`
86
86
  - method: `GET`
87
- - purpose: summarize front-end quality test results from all available reports
88
- - path: `/api/targets`
87
+ - purpose: get a list of all available reports
88
+ - path: `/api/reportList`
89
89
  - caveat: Cached results are likely to be stale and should not be used
90
90
  - `describeQualityOfOneWebPage`
91
91
  - method: `GET`
@@ -94,7 +94,7 @@ The implementation is currently in an alpha phase and offers 4 tools:
94
94
  - parameters
95
95
  - `timeStamp`: initial segment of report identifier
96
96
  - `jobID`: final segment of report identifier
97
- - source of parameters: response to a `summarizeQualityOfAllTestedWebPages` request
97
+ - source of parameters: response to a `getListOfAllAvailableReports` request
98
98
  - `describeOneIssueFromOneReport`
99
99
  - method: `GET`
100
100
  - purpose: provide details about one issue from one report
@@ -156,7 +156,7 @@ More information about Kilotest features and internals:
156
156
 
157
157
  ### For language models and AI platforms
158
158
 
159
- - [AI-TOOL file](https://github.com/jrpool/kilotest/blob/main/AI-TOOL.md)
159
+ - [AI-TOOL file](https://github.com/jrpool/kilotest/blob/main/docs/AI-TOOL.md)
160
160
  - [OpenAPI specification for Kilotest](https://kilotest.com/openapi.yaml)
161
161
  - [Tool caller for testing](https://github.com/jrpool/kilotest/blob/main/researchAgent.js)
162
162
 
package/llms.txt CHANGED
@@ -8,8 +8,8 @@ There is a [detailed explanation of Kilotest and its capabilities for LLMs](http
8
8
 
9
9
  ## API
10
10
 
11
- - [Find any available reports about a specified web page](/api/identifyReportsAboutMatchingWebPages)
12
- - [Get summaries of all available reports](/api/targets)
11
+ - [Get summaries of reports about a specified web page](/api/target)
12
+ - [Get a list of all available reports](/api/reportList)
13
13
  - Get summarized test results from one report: `/api/reportIssues/{timeStamp}/{jobID}`
14
14
  - Get details about one issue from one report: `/api/reportIssue/{issueID}/{timeStamp}/{jobID}`
15
15
  - Recommend testing of a web page: `/api/testRecForm` (requires `POST` request)
package/mcp.js CHANGED
@@ -10,7 +10,7 @@ const {StreamableHTTPServerTransport} = require('@modelcontextprotocol/sdk/serve
10
10
  const {z} = require('zod');
11
11
  const {isReportAvailable, isURL} = require('./util');
12
12
  const targetAPI = require('./target/api');
13
- const targetsAPI = require('./targets/api');
13
+ const reportListAPI = require('./reportList/api');
14
14
  const reportIssuesAPI = require('./reportIssues/api');
15
15
  const reportIssueAPI = require('./reportIssue/api');
16
16
  const testRecFormAPI = require('./testRecForm/api');
@@ -27,10 +27,10 @@ const createMCPServer = () => {
27
27
  server.registerTool(
28
28
  'summarizeQualityOfMatchingWebPages',
29
29
  {
30
- description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages that match the description or hostname fragment of a web page that you have provided. Matching is case-insensitive and succeeds if the page property either is included by or includes the specified fragmant. Before calling recommendQualityTestingOfOneWebPage and waiting for testing to occur, call this tool to check whether a report about the page is available now.',
30
+ description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages that match the description or hostname fragment of a web page that you have provided. Matching is case-insensitive and succeeds if the page property either is included by or includes the specified fragment.',
31
31
  inputSchema: {
32
32
  what: z.string().describe('All or part of a description of the web page.'),
33
- url: z.string().describe('All or part of the hostname of the URL of the web page.')
33
+ hostname: z.string().describe('All or part of the hostname of the URL of the web page.')
34
34
  },
35
35
  annotations: {
36
36
  title: 'Summarize the quality of matching web pages',
@@ -40,18 +40,18 @@ const createMCPServer = () => {
40
40
  openWorldHint: false
41
41
  }
42
42
  },
43
- async ({what, url}) => {
44
- const result = await targetAPI.response([what, url]);
43
+ async ({what, hostname}) => {
44
+ const result = await targetAPI.response([what, hostname]);
45
45
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
46
46
  }
47
47
  );
48
48
  server.registerTool(
49
- 'summarizeQualityOfAllTestedWebPages',
49
+ 'getListOfAllAvailableReports',
50
50
  {
51
- description: 'Returns summary data from every available Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page.',
51
+ description: 'Returns a list of all available Kilotest reports; each report describes the results of a job that tested one web page for front-end quality (i.e. accessibility, usability, and standards conformity).',
52
52
  inputSchema: {},
53
53
  annotations: {
54
- title: 'Summarize the quality of all tested web pages',
54
+ title: 'Get a list of all available reports',
55
55
  readOnlyHint: true,
56
56
  idempotentHint: true,
57
57
  destructiveHint: false,
@@ -59,14 +59,14 @@ const createMCPServer = () => {
59
59
  }
60
60
  },
61
61
  async () => {
62
- const result = await targetsAPI.response();
62
+ const result = await reportListAPI.response();
63
63
  return {content: [{type: 'text', text: JSON.stringify(result)}]};
64
64
  }
65
65
  );
66
66
  server.registerTool(
67
67
  'describeQualityOfOneWebPage',
68
68
  {
69
- description: 'Returns data from a specified Kilotest report about issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a summarizeQualityOfAllTestedWebPages response.',
69
+ description: 'Returns data from a specified Kilotest report about issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. The required timeStamp and jobID parameters identify the report and are obtained from a getListOfAllAvailableReports response.',
70
70
  inputSchema: {
71
71
  timeStamp: z.string().describe('Report timestamp in YYMMDDTHHMM format, e.g. 260503T0432'),
72
72
  jobID: z.string().describe('Job identifier, e.g. x9z')
@@ -109,9 +109,9 @@ const createMCPServer = () => {
109
109
  server.registerTool(
110
110
  'recommendQualityTestingOfOneWebPage',
111
111
  {
112
- description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call summarizeQualityOfAllTestedWebPages to check whether a report about the page, or a related page that satisfies your requirements, is available.',
112
+ description: 'Recommends a web page for Kilotest to test for front-end quality (i.e. accessibility, usability, and standards conformity). Do not call this tool until after you call getListOfAllAvailableReports to check whether a report about the page, or a related page that satisfies your requirements, is available and to understand the naming conventions for pages.',
113
113
  inputSchema: {
114
- what: z.string().describe('Short description of the page, following the naming conventions visible in the summarizeQualityOfAllTestedWebPages response'),
114
+ what: z.string().describe('Short description of the page, following the naming conventions visible in the getListOfAllAvailableReports response'),
115
115
  url: z.string().describe('Full HTTPS URL of the page to test'),
116
116
  why: z.string().describe('Reason for recommending this page for testing')
117
117
  },
package/openapi.yaml CHANGED
@@ -17,7 +17,7 @@ paths:
17
17
  post:
18
18
  operationId: summarizeQualityOfMatchingWebPages
19
19
  summary: Summarize the quality of matching web pages
20
- description: Get summary data from the available reports about web pages whose descriptions or hostnames match your specifications. Matching is case-insensitive and succeeds at least 1 specification is included by or includes the corresponding property of a tested page. The data include the name and URL of each tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standards conformity) issues were reported, and URLs for retrieving more detailed data from the report. Before calling the recommendQualityTestingOfOneWebPage tool and waiting for testing to occur, call this tool to check whether a report about the page is available now. If so, you can retrieve data from it. If not, you can use the recommendQualityTestingOfOneWebPage tool to recommend the page for testing.
20
+ description: Get summary data from the available reports about web pages whose descriptions or hostnames match your specifications. Matching is case-insensitive and succeeds if at least 1 specification is included by or includes the corresponding property of a tested page. The data include the name and URL of each tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standards conformity) issues were reported, and URLs for retrieving more detailed data from the report.
21
21
  requestBody:
22
22
  description: Page specifications
23
23
  required: true
@@ -33,24 +33,24 @@ paths:
33
33
  schema:
34
34
  $ref: '#/components/schemas/TargetsResponse'
35
35
 
36
- /api/targets:
36
+ /api/reportList:
37
37
  get:
38
- operationId: summarizeQualityOfAllTestedWebPages
39
- summary: Summarize the quality of all tested web pages
40
- description: Get summary data about every non-hidden report available from Kilotest, including the name and URL of the tested web page, when the testing was performed, how many front-end quality (i.e. accessibility, usability, and standard-conformity) issues were reported, and URLs for retrieving more detailed data from the report.
38
+ operationId: getListOfAllAvailableReports
39
+ summary: Get a list of all available reports
40
+ description: Get a list of all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.
41
41
  responses:
42
42
  '200':
43
- description: Summaries of available reports
43
+ description: List of all available reports
44
44
  content:
45
45
  application/json:
46
46
  schema:
47
- $ref: '#/components/schemas/TargetsResponse'
47
+ $ref: '#/components/schemas/ReportListResponse'
48
48
 
49
49
  /api/testRecForm:
50
50
  post:
51
51
  operationId: recommendQualityTestingOfOneWebPage
52
52
  summary: Recommend quality testing of one web page
53
- description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the summarizeQualityOfAllTestedWebPages operation. Before submitting a recommendation, use the summarizeQualityOfAllTestedWebPages operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
53
+ description: Submit a recommendation for Kilotest to test, for the first time, a particular web page for front-end quality (i.e. accessibility, usability, and standards conformity). Recommendations are typically approved and the testing completed within a day, whereupon the results can be found with the getListOfAllAvailableReports operation. Before submitting a recommendation, use the getListOfAllAvailableReports operation to ensure that no report about the page is available, and also to see the stylistic rules for the naming of pages. An attempt to recommend a page for testing will fail if a report about the page is already available.
54
54
  requestBody:
55
55
  description: Test recommendation specifications
56
56
  required: true
@@ -70,7 +70,7 @@ paths:
70
70
  get:
71
71
  operationId: describeQualityOfOneWebPage
72
72
  summary: Describe quality of one web page
73
- description: Get data about the quality of a specified Kilotest report. The data about each issue include its priority, the rule engines that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID parameters identify the report and are available in the response from the summarizeQualityOfAllTestedWebPages operation.
73
+ description: Get data about the quality of a specified Kilotest report. The data about each issue include its priority, the rule engines that reported it, the number of HTML elements exhibiting it, and URLs for retrieving element-level detail. The timeStamp and jobID parameters identify the report and are available in the response from the getListOfAllAvailableReports operation.
74
74
  parameters:
75
75
  - name: timeStamp
76
76
  in: path
@@ -146,10 +146,14 @@ components:
146
146
  summary:
147
147
  type: string
148
148
  description: Natural-language description of this response and of Kilotest. Provides context for an agent encountering Kilotest for the first time.
149
- tool name:
149
+ tool collection name:
150
150
  type: string
151
151
  examples:
152
152
  - Kilotest
153
+ tool name:
154
+ type: string
155
+ examples:
156
+ - getListOfAllAvailableReports
153
157
  request:
154
158
  type: object
155
159
  properties:
@@ -158,6 +162,8 @@ components:
158
162
  properties:
159
163
  identifier:
160
164
  type: string
165
+ examples:
166
+ - reportList
161
167
  description:
162
168
  type: string
163
169
  method:
@@ -167,7 +173,7 @@ components:
167
173
  - POST
168
174
  payload:
169
175
  type: object
170
- description: Present only for POST requests. The request payload.
176
+ description: The request payload, if method type is POST, or otherwise omitted.
171
177
  URLs:
172
178
  type: object
173
179
  properties:
@@ -197,6 +203,7 @@ components:
197
203
  description: Unique identifier for this response instance.
198
204
  date and time:
199
205
  type: string
206
+ description: UTC date and time when the response was generated, in ISO 8601 format.
200
207
  format: date-time
201
208
 
202
209
  TestRecForm:
@@ -306,12 +313,44 @@ components:
306
313
  $ref: '#/components/schemas/RuleEnginesSummary'
307
314
  rule engines that reported issues:
308
315
  $ref: '#/components/schemas/RuleEnginesSummary'
309
- URLs for getting data on the reported issues:
316
+ URLs for getting data about the reported issues:
310
317
  $ref: '#/components/schemas/NextTierURLs'
311
318
  URL for getting the full technical report as JSON:
312
319
  type: string
313
320
  format: uri
314
321
 
322
+ ReportListItem:
323
+ type: object
324
+ description: Summary data about a single available report.
325
+ properties:
326
+ identifier:
327
+ type: string
328
+ examples:
329
+ - 260504T1659-029
330
+ creation date and time:
331
+ type: string
332
+ format: date-time
333
+ days since the creation date:
334
+ type: integer
335
+ tested web page:
336
+ type: object
337
+ properties:
338
+ description:
339
+ type: string
340
+ URL:
341
+ type: string
342
+ format: uri
343
+ whether a later report about the same page exists:
344
+ type: boolean
345
+ description: If true, a more recent report about this page is available. If you want the latest results, use that report instead.
346
+ URLs for incrementally getting facts from the report:
347
+ $ref: '#/components/schemas/NextTierURLs'
348
+ size of the report in bytes:
349
+ type: integer
350
+ URL to get the entire report as machine-oriented JSON:
351
+ type: string
352
+ format: uri
353
+
315
354
  Target:
316
355
  type: object
317
356
  properties:
@@ -322,7 +361,7 @@ components:
322
361
  type: string
323
362
  description: All or part of the hostname of the web page. The hostname omits the scheme and the path.
324
363
 
325
- TargetsResponse:
364
+ ReportListResponse:
326
365
  allOf:
327
366
  - $ref: '#/components/schemas/CommonResponseFields'
328
367
  - type: object
@@ -330,6 +369,17 @@ components:
330
369
  available reports:
331
370
  type: array
332
371
  description: One entry per available Kilotest report, in alphabetical order by page description and, in case of multiple reports per page, in order of creation date and time. Reports are matched by page description, not page URL, so, if only the URL of a page has changed between reports, the reports are treated as reports about the same page.
372
+ items:
373
+ $ref: '#/components/schemas/ReportListItem'
374
+
375
+ TargetsResponse:
376
+ allOf:
377
+ - $ref: '#/components/schemas/CommonResponseFields'
378
+ - type: object
379
+ properties:
380
+ matching reports:
381
+ type: array
382
+ description: One entry per available matching Kilotest report. A report is matching if its page description or hostname contains or is contained by a specified description or hostname fragment, respectively.
333
383
  items:
334
384
  $ref: '#/components/schemas/TargetsItem'
335
385
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jrpool/kilotest",
3
- "version": "36.1.1",
3
+ "version": "37.0.0",
4
4
  "description": "An ensemble testing service with a focus on accessibility",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -106,13 +106,13 @@ exports.response = async args => {
106
106
  const thisHost = process.env.THIS_KILOTEST_HOST;
107
107
  // Get a response.
108
108
  const content = {
109
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data, drawn from a Kilotest report, about one of the issues for the front-end quality (i.e. accessibility, usability, and standard-conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
109
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data, drawn from a Kilotest report, about one of the issues for the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
110
110
  'tool collection name': 'Kilotest',
111
111
  'tool name': 'describeOneIssueFromOneReport',
112
112
  request: {
113
113
  'type of request': {
114
114
  identifier: 'reportIssue',
115
- description: 'Describe one issue from one repeort.'
115
+ description: 'Describe one issue from one report.'
116
116
  },
117
117
  method: 'GET',
118
118
  URLs: {
@@ -123,8 +123,8 @@ exports.response = async args => {
123
123
  identifier: 'describeQualityOfOneWebPage',
124
124
  description: 'Describe the quality of one web page.',
125
125
  URLs: {
126
- 'for you': `${thisHost}/api/reportIssues`,
127
- 'for humans': `${thisHost}/reportIssues.html`
126
+ 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
127
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
128
128
  }
129
129
  }
130
130
  },
@@ -63,7 +63,7 @@ exports.response = async args => {
63
63
  const thisHost = process.env.THIS_KILOTEST_HOST;
64
64
  // Get a response.
65
65
  const content = {
66
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data from a Kilotest report about the front-end quality (i.e. accessibility, usability, and standard-conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
66
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data from a Kilotest report about the front-end quality (i.e. accessibility, usability, and standards conformity) of a web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes several API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
67
67
  'tool collection name': 'Kilotest',
68
68
  'tool name': 'describeQualityOfOneWebPage',
69
69
  request: {
@@ -77,10 +77,10 @@ exports.response = async args => {
77
77
  'equivalent URL for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
78
78
  },
79
79
  'closest ancestor request': {
80
- identifier: 'summarizeQualityOfAllTestedWebPages',
81
- description: 'Summarize the quality of all tested web pages.',
80
+ identifier: 'getListOfAllAvailableReports',
81
+ description: 'Get a list of all available reports.',
82
82
  URLs: {
83
- 'for you': `${thisHost}/api/targets`,
83
+ 'for you': `${thisHost}/api/reportList`,
84
84
  'for humans': `${thisHost}/targets.html`
85
85
  }
86
86
  }
@@ -0,0 +1,75 @@
1
+ /*
2
+ api.js
3
+ Responds to the reportList API request.
4
+ */
5
+
6
+ // IMPORTS
7
+
8
+ const {
9
+ getAgoDays,
10
+ getDateTime,
11
+ getLogs,
12
+ getNowStamp,
13
+ getRandomString,
14
+ getReportSize
15
+ } = require('../util');
16
+
17
+ // CONSTANTS
18
+
19
+ const thisHost = process.env.THIS_KILOTEST_HOST;
20
+
21
+ // FUNCTIONS
22
+
23
+ // Returns a response to an API request for reports.
24
+ exports.response = async () => {
25
+ const reportsFacts = [];
26
+ // Get the available logs, with added job names.
27
+ const availableLogs = await getLogs();
28
+ // For each of them:
29
+ for (const availableLog of availableLogs) {
30
+ const {jobName} = availableLog;
31
+ const [timeStamp, jobID] = jobName.split('-');
32
+ const reportSize = await getReportSize(timeStamp, jobID);
33
+ const {superseded, url, what} = availableLog;
34
+ reportsFacts.push({
35
+ identifier: jobName,
36
+ 'creation date and time': getDateTime(timeStamp),
37
+ 'days since the creation date': getAgoDays(timeStamp),
38
+ 'tested web page': {
39
+ description: what,
40
+ URL: url
41
+ },
42
+ 'whether a later report about the same page exists': !! superseded,
43
+ 'URLs for incrementally getting facts from the report': {
44
+ 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
45
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
46
+ },
47
+ 'size of the report in bytes': reportSize,
48
+ 'URL to get the entire report as machine-oriented JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
49
+ });
50
+ }
51
+ // Get a response.
52
+ const content = {
53
+ summary: `This document fulfills a request made by a language model to a Kilotest tool. The model asked which reports about the front-end quality (i.e. accessibility, usability, and standards conformity) of web pages are available from Kilotest. Each report describes the results of a job that tested one web page. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs more than a thousand tests on a public web page, using a combination of rule- and machine-learning-based methods. Kilotest exposes API endpoints and web UI URLs to recommend web pages for testing and to obtain information from Kilotest reports. You and your users can learn more about Kilotest and the advantages of testing with an ensemble of rule engines at the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}).`,
54
+ 'tool collection name': 'Kilotest',
55
+ 'tool name': 'getListOfAllAvailableReports',
56
+ request: {
57
+ 'type of request': {
58
+ identifier: 'reportList',
59
+ description: 'Get a list of all available reports. Each report describes the results of a job that tested a web page for front-end quality (i.e. accessibility, usability, and standards conformity). For each report, the list identifies which page was tested and when and provides URLs to begin incremental retrieval of the test results.'
60
+ },
61
+ method: 'GET',
62
+ URLs: {
63
+ 'URL of your request': `${thisHost}/api/reportList`,
64
+ 'equivalent URL for humans': `${thisHost}/targets.html`
65
+ },
66
+ 'closest ancestor request': null
67
+ },
68
+ 'response metadata': {
69
+ identifier: `${getNowStamp()}-${getRandomString(3)}`,
70
+ 'date and time': new Date().toISOString(),
71
+ },
72
+ 'available reports': reportsFacts
73
+ };
74
+ return content;
75
+ };
package/researchAgent.js CHANGED
@@ -115,9 +115,9 @@ const requestService = async () => {
115
115
  if (content.error) {
116
116
  return;
117
117
  }
118
- console.log('======================\nRequest 2: Summarize all available reports');
118
+ console.log('======================\nRequest 2: List all available reports');
119
119
  method = 'GET';
120
- path = '/api/targets';
120
+ path = '/api/reportList';
121
121
  content = await submitRequest(results, path, method);
122
122
  reports = content?.['available reports'] ?? [];
123
123
  if (content.error || ! Array.isArray(reports) || ! reports.length) {
package/target/api.js CHANGED
@@ -78,7 +78,7 @@ exports.response = async args => {
78
78
  'number of HTML elements reported as exhibiting issues': violatorCount,
79
79
  'URLs for getting data about the reported issues': {
80
80
  'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
81
- 'for humans': `${thisHost}/reportIssues/${timeStamp}/${jobID}`
81
+ 'for humans': `${thisHost}/reportIssues.html/${timeStamp}/${jobID}`
82
82
  },
83
83
  'URL for getting the full technical report as JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
84
84
  });
@@ -86,13 +86,13 @@ exports.response = async args => {
86
86
  }
87
87
  // Get a response.
88
88
  const content = {
89
- summary: `This document fulfills a request made by a language model to the Kilotest API. The model asked whether Kilotest had tested a specified web page for front-end quality (i.e. accessibility, usability, and standards conformity) and had made a report of the test results available. The response provides summary information about all and only the available reports of pages that match at least one of the provided fragments, where matching means either including or being included by the provided fragment, case-insensitively. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
89
+ summary: `This document fulfills a request made by a language model to the Kilotest API. The model asked whether Kilotest had tested a specified web page for front-end quality (i.e. accessibility, usability, and standards conformity) and had made a report of the test results available. The response provides summary information about all and only the available reports of pages that match at least one of the provided fragments, where matching means either including or being included by the provided fragment, case-insensitively. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
90
90
  'tool collection name': 'Kilotest',
91
- 'tool name': 'identifyReportsAboutMatchingWebPages',
91
+ 'tool name': 'summarizeQualityOfMatchingWebPages',
92
92
  request: {
93
93
  'type of request': {
94
- identifier: 'targets',
95
- description: 'Identify reports about matching web pages.'
94
+ identifier: 'target',
95
+ description: 'Summarize the quality of matching web pages.'
96
96
  },
97
97
  method: 'POST',
98
98
  payload: {
@@ -109,7 +109,7 @@ exports.response = async args => {
109
109
  identifier: `${getNowStamp()}-${getRandomString(3)}`,
110
110
  'date and time': new Date().toISOString(),
111
111
  },
112
- 'reports, if any, that may match your page specifications': matchingReports
112
+ 'matching reports': matchingReports
113
113
  };
114
114
  return content;
115
115
  };
@@ -26,7 +26,7 @@ exports.response = async (what, url, why) => {
26
26
  );
27
27
  // Get a response.
28
28
  const content = {
29
- summary: `This response acknowledges a request made by a language model to a Kilotest tool. The model recommended that Kilotest test, for the first time, the ${what} web page at ${url} for front-end quality (i.e. accessibility, usability, and standards conformity). A Kilotest manager usually approves a recommendation within a day. When the recommendation is approved, the testing will be performed and results will become available. You can check for the availability of the results at ${thisHost}/api/targets. Kilotest performs its testing with the help of Testaro, Testilo, and an ensemble of ten rule engines, using a combination of rule- and machine-learning-based methods. Kilotest exposes several API endpoints and several web UI URLs to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
29
+ summary: `This response acknowledges a request made by a language model to a Kilotest tool. The model recommended that Kilotest test, for the first time, the ${what} web page at ${url} for front-end quality (i.e. accessibility, usability, and standards conformity). A Kilotest manager usually approves a recommendation within a day. When the recommendation is approved, the testing will be performed and results will become available. You can check for the availability of the results at ${thisHost}/api/reportList. Kilotest performs its testing with the help of Testaro, Testilo, and an ensemble of ten rule engines, using a combination of rule- and machine-learning-based methods. Kilotest exposes several API endpoints and several web UI URLs to obtain information from Kilotest reports. To learn more about Kilotest and the advantages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), which contains an introduction on its home page and a tutorial.`,
30
30
  'tool collection name': 'Kilotest',
31
31
  'tool name': 'recommendQualityTestingOfOneWebPage',
32
32
  request: {
package/util.js CHANGED
@@ -489,7 +489,7 @@ exports.getPOSTData = request => new Promise(resolve => {
489
489
  });
490
490
  // Returns the waiting test and retest recommendations.
491
491
  const getRecs = exports.getRecs = async () => {
492
- let recs = {};
492
+ let recs;
493
493
  let recsJSON;
494
494
  try {
495
495
  recsJSON = await fs.readFile(recsPath, 'utf8');
@@ -764,3 +764,9 @@ exports.isReportAvailable = async (what, url) => {
764
764
  const miniURLs = logs.map(log => minifyURL(log.url));
765
765
  return whats.includes(what) || miniURLs.includes(minifyURL(url));
766
766
  };
767
+ // Returns the size of a report.
768
+ exports.getReportSize = async (timeStamp, jobID) => {
769
+ const reportStat = await fs.stat(path.join(reportsPath, `${timeStamp}-${jobID}.json`));
770
+ const reportSize = reportStat.size;
771
+ return reportSize;
772
+ };
package/targets/api.js DELETED
@@ -1,99 +0,0 @@
1
- /*
2
- api.js
3
- Responds to the targets request.
4
- */
5
-
6
- // IMPORTS
7
-
8
- const {
9
- getLogs,
10
- getNowStamp,
11
- getRandomString,
12
- getReportData
13
- } = require('../util');
14
-
15
- // CONSTANTS
16
-
17
- const thisHost = process.env.THIS_KILOTEST_HOST;
18
-
19
- // FUNCTIONS
20
-
21
- // Returns a response to a targets request.
22
- exports.response = async () => {
23
- const availableReports = [];
24
- // Get the non-hidden logs.
25
- const targetLogs = await getLogs();
26
- // For each log:
27
- for (const targetLog of targetLogs) {
28
- const {jobName} = targetLog;
29
- const [timeStamp, jobID] = jobName.split('-');
30
- const {superseded, url, what} = targetLog;
31
- // Get data about its report.
32
- const data = await getReportData(timeStamp, jobID);
33
- const {
34
- creationDate,
35
- daysAgo,
36
- issueCount,
37
- toolNames,
38
- toolCount,
39
- reporterNames,
40
- reporterCount,
41
- violatorCount,
42
- preventedToolNames,
43
- preventedToolCount
44
- } = data;
45
- availableReports.push({
46
- identifier: jobName,
47
- 'creation date': creationDate,
48
- 'days since the creation date': daysAgo,
49
- 'tested web page': {
50
- description: what,
51
- URL: url
52
- },
53
- 'whether a later report about the same page exists': !! superseded,
54
- 'rule engines that tried to test the page': {
55
- number: toolCount,
56
- names: toolNames
57
- },
58
- 'rule engines that were unable to test the page': {
59
- number: preventedToolCount,
60
- names: preventedToolNames
61
- },
62
- 'rule engines that reported issues': {
63
- number: reporterCount,
64
- names: reporterNames
65
- },
66
- 'number of issues reported': issueCount,
67
- 'number of HTML elements reported as exhibiting issues': violatorCount,
68
- 'URLs for getting data about the reported issues': {
69
- 'for you': `${thisHost}/api/reportIssues/${timeStamp}/${jobID}`,
70
- 'for humans': `${thisHost}/reportIssues/${timeStamp}/${jobID}`
71
- },
72
- 'URL for getting the full technical report as JSON': `${thisHost}/fullReport.json/${timeStamp}/${jobID}`
73
- });
74
- }
75
- // Get a response.
76
- const content = {
77
- summary: `This document fulfills a request made by a language model to a Kilotest tool. The model requested data about the web pages that Kilotest had tested for front-end quality (i.e. accessibility, usability, and standards conformity) and, for each page, statistics about the results of the tests. Kilotest, with the help of Testaro, Testilo, and an ensemble of ten rule engines, performs tests on web pages, using a combination of rule- and machine-learning-based methods, and produces reports. Kilotest exposes API endpoints and web UI URLs to recommend web pages for testing and to obtain information from Kilotest reports. To learn more about Kilotest and the advangages of testing with an ensemble of rule engines, visit the deployed instance of Kilotest (${process.env.DEPLOYED_KILOTEST_HOST}), whose home page contains an introduction and a link to a tutorial.`,
78
- 'tool collection name': 'Kilotest',
79
- 'tool name': 'summarizeQualityOfAllTestedWebPages',
80
- request: {
81
- 'type of request': {
82
- identifier: 'targets',
83
- description: 'Summarize the quality of all tested web pages.'
84
- },
85
- method: 'GET',
86
- URLs: {
87
- 'URL of your request': `${thisHost}/api/targets`,
88
- 'equivalent URL for humans': `${thisHost}/targets.html`
89
- },
90
- 'closest ancestor request': null
91
- },
92
- 'response metadata': {
93
- identifier: `${getNowStamp()}-${getRandomString(3)}`,
94
- 'date and time': new Date().toISOString(),
95
- },
96
- 'available reports': availableReports
97
- };
98
- return content;
99
- };
File without changes
File without changes