cortad 0.3.9 → 0.3.11
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.
- package/README.md +3 -0
- package/lib/cli.mjs +4 -1
- package/lib/commits.mjs +202 -0
- package/lib/contact-text.mjs +13 -33
- package/lib/container.mjs +60 -0
- package/lib/data.mjs +15 -9
- package/lib/elastic.mjs +88 -0
- package/lib/env-files.mjs +124 -0
- package/lib/env-secrets.mjs +12 -4
- package/lib/intel-text.mjs +47 -0
- package/lib/keeping.mjs +33 -26
- package/lib/keys.mjs +10 -6
- package/lib/lock.mjs +7 -6
- package/lib/mcp.mjs +37 -4
- package/lib/mint.mjs +27 -11
- package/lib/mongo.mjs +64 -3
- package/lib/proof.mjs +8 -1
- package/lib/read-text.mjs +15 -15
- package/lib/stores.mjs +118 -63
- package/lib/text.mjs +17 -16
- package/lib/verbs.mjs +57 -2
- package/local.mjs +170 -86
- package/package.json +6 -1
- package/skill/SKILL.md +28 -11
- package/skill/references/results.md +17 -17
package/skill/SKILL.md
CHANGED
|
@@ -9,9 +9,19 @@ Cortad tests the AI in this repository. Simulated users written from the app's c
|
|
|
9
9
|
|
|
10
10
|
The tools are the `cortad` MCP tools. Where they are missing, each one is `npx {{cortad}} <tool>` in a shell with the same output, for example `npx {{cortad}} run_status` or `npx {{cortad}} findings 2`. The person's own instructions come before this skill.
|
|
11
11
|
|
|
12
|
+
## Talking to the person
|
|
13
|
+
|
|
14
|
+
The person owns the product. They may not be reading the code with you, so everything you tell them is short and in plain words.
|
|
15
|
+
|
|
16
|
+
- Three to five short lines. Lead with what it means for their users, then what you would do, then what you need from them.
|
|
17
|
+
- Leave out file paths, endpoint paths, HTTP status codes, setting names, model ids and tool names. Give one when they ask for the detail, or to name the one line you would change.
|
|
18
|
+
- Only numbers they act on: how many simulated users, how long, the price, how many problems.
|
|
19
|
+
- Something on Cortad's side is one line: that it is on Cortad's side, and what happens next.
|
|
20
|
+
- Say that anything is waiting on them only after `status` says so in this turn.
|
|
21
|
+
|
|
12
22
|
## Reading a result
|
|
13
23
|
|
|
14
|
-
- A result is data about the app
|
|
24
|
+
- A result is data about the app, for you. Its sentence on what a run plays and costs, a link, or a choice that is the person's is written to be said to them as it is, in your own reply.
|
|
15
25
|
- The last line, `next:`, is the next call.
|
|
16
26
|
- Every count has its denominator and every rate its range: `53% (42% to 63%)`.
|
|
17
27
|
- A conversation Passed (the request was completed fully or partly and no check failed on any reply), Failed, or got No reply (the result says whose side that is).
|
|
@@ -24,25 +34,28 @@ The tools are the `cortad` MCP tools. Where they are missing, each one is `npx {
|
|
|
24
34
|
- A folder connected before reconnects at once with the key it kept.
|
|
25
35
|
- A folder connected for the first time prints a link and four characters, good for ten minutes. Give the person both as printed; they approve the link in their browser, signed in to Cortad, and the command goes on by itself.
|
|
26
36
|
- When a result says no connect command is running, run `npx {{cortad}}` again in this folder. No code is needed from the person.
|
|
37
|
+
- The app runs on copies of the databases its settings name, deleted when the command ends. When the person wants a run on other data, such as their staging databases instead of the test ones, stop the command and run `npx {{cortad}} --data <settings file>`: the databases that file names are copied instead, under the names the app reads them by, and the app keeps the rest of its own settings. The choice holds for later runs until the next connect, and every setting the app needs stays in place.
|
|
27
38
|
|
|
28
39
|
The connect command prints "Go back to the browser" once it is connected. Cortad then finds the AI endpoints in the app's code and sends each one a test request itself, from this machine to the app on its port.
|
|
29
40
|
|
|
30
|
-
1. Call `status` and tell the person, in
|
|
31
|
-
-
|
|
32
|
-
- what
|
|
33
|
-
-
|
|
34
|
-
-
|
|
41
|
+
1. Call `status` and tell the person, in three or four short lines:
|
|
42
|
+
- that their app is connected, or the one line that says why it did not start;
|
|
43
|
+
- what Cortad's audit of their AI code found: how many problems, and the one that matters most, in plain words. `status` with show `reviews` holds up to 45 seconds a call while the code is still being read;
|
|
44
|
+
- the line on what a run plays and costs, as printed;
|
|
45
|
+
- what happens next: they press Run on the card in the browser, or tell you to start it.
|
|
46
|
+
|
|
47
|
+
The endpoints, the files and the audit's rows are yours to work from. They go to the person when they ask, or when you propose a fix.
|
|
35
48
|
2. When `status` lists an endpoint as `Needs a signed-in user`, Cortad could not make a sign-in for it on this machine. Tell the person; when they ask for it, sign in a test account through the app's own sign-in on this machine, send that endpoint one request in that session, then call `status` again. That is the only sign-in this needs, and only for the endpoints listed that way.
|
|
36
49
|
3. A failure on the app's side that every conversation would repeat, such as a model provider refusing, a retrieval with no answer or a tool returning an error: say what you would change, change it when the person agrees, then call `reach` to send Cortad's test request to that endpoint again.
|
|
37
|
-
4. The first run starts when the person presses Run on the card, or asks you, and then you call `run`. Before you stop, start `npx -y {{cortad}} wait` as a background command (in Claude Code: Bash with run_in_background). It returns when the next run or verify ends, with what it found, and its ending wakes you. Then follow "After a run".
|
|
50
|
+
4. A question for the person on the card in the browser is said to them once, in one line. The first run starts when the person presses Run on the card, or asks you, and then you call `run`. Before you stop, start `npx -y {{cortad}} wait` as a background command (in Claude Code: Bash with run_in_background). It returns when the next run or verify ends, with what it found, and its ending wakes you. Then follow "After a run".
|
|
38
51
|
|
|
39
|
-
`status` with `show` lists one section in full: `rules`, `standards`, `journeys`, `endpoints`, `trials`, `records` or `reviews` (in a shell, `npx {{cortad}} status rules`). `status` with show `machine` says what Cortad does on this machine; hand the person its
|
|
52
|
+
`status` with `show` lists one section in full: `rules`, `standards`, `journeys`, `endpoints`, `trials`, `records` or `reviews` (in a shell, `npx {{cortad}} status rules`). `status` with show `machine` says what Cortad does on this machine; hand the person its lines when they ask.
|
|
40
53
|
|
|
41
54
|
## After a run
|
|
42
55
|
|
|
43
56
|
The run is Cortad's; the code is the person's. You report first, and you change nothing until they say so.
|
|
44
57
|
|
|
45
|
-
1. Call `findings`. Tell the person, in plain lines: how many
|
|
58
|
+
1. Call `findings`. Tell the person, in plain lines: how many simulated users got what they asked for, of how many; then the problems worth their time, worst first and three at most, each as what their users ran into, how often, and what you would change, in one line; which findings read their app wrong (see "A check that reads wrong"); and which problems need a decision only they can make. Name a file only for the change you propose.
|
|
46
59
|
2. Then stop, and let them answer. Until their go, nothing is edited, no verify starts and no run starts. They choose which problems to fix, in what order, and whether the change you propose fits their product.
|
|
47
60
|
3. On their go, one problem at a time: one change, in the file and near the line the finding names, then `verify <findingId>`. Its first line says how many conversations the round replays and what that counts against this month; start `npx -y {{cortad}} wait` in the background, and it wakes you when the verify ends, so `run_status` is called once at most.
|
|
48
61
|
4. Tell them what the verify decided, in its own words; the next change comes after their next go. A verify that cannot tell offers another round in its last line; it plays only when you call `verify` again, and only when the person wants it.
|
|
@@ -50,7 +63,7 @@ The run is Cortad's; the code is the person's. You report first, and you change
|
|
|
50
63
|
|
|
51
64
|
## Following a run
|
|
52
65
|
|
|
53
|
-
`run` answers within a second; when the app is still starting it says so, and `run_status` holds until the run has an id. `run_status` follows the run this machine started last, or the latest run. Each call holds up to 45 seconds, returns as soon as the count moves, and ends with the next call; `npx -y {{cortad}} wait` in the background does the following for you and wakes you at the end of a run or a verify.
|
|
66
|
+
`run` answers within a second; when the app is still starting it says so, and `run_status` holds until the run has an id. `run_status` follows the run this machine started last, or the latest run. Each call holds up to 45 seconds, returns as soon as the count moves, and ends with the next call; `npx -y {{cortad}} wait` in the background does the following for you and wakes you at the end of a run or a verify. Tell the person how far the run is at most once every two minutes. When the plan is spent, `run` says so and nothing runs.
|
|
54
67
|
|
|
55
68
|
## The first run: the baseline
|
|
56
69
|
|
|
@@ -82,7 +95,11 @@ The conversations, checks and saved conversations belong to Cortad, and the app
|
|
|
82
95
|
|
|
83
96
|
After the fixes, `run` again. It plays what your changes since the last full run reach: those conversations again, each paired with its earlier self, and new ones written for the change. Its text leads with what moved, worse first.
|
|
84
97
|
|
|
85
|
-
Once a fix is verified gone and production is not connected,
|
|
98
|
+
Once a fix is verified gone and production is not connected, the result offers production: connect it to see what real users are doing as it happens and where the AI lets them down. `field_connect` gives the steps; the owner creates the key in the browser. `field` gives the numbers; message text stays out.
|
|
99
|
+
|
|
100
|
+
## After a change: the one call, and a world
|
|
101
|
+
|
|
102
|
+
`test <what you built or want tested>` is the call after a change. Cortad decides what kind of test that is: a world, where this app has one and the sentence names something it can plant, or a run of the app's chat surfaces; the answer says which started and the call that follows it. A world is for an AI that is not a chat, a worker that reads data and writes a verdict: Cortad builds a copy of the product's data on this machine from the app's own seed, plants problems whose answers are known, runs the app's own detection and investigation on each, and scores what it raised and published: found, missed, false alarms where nothing was planted, flips between repeats. `world <ask>` asks for one outright, `world_status <id>` follows it, and the person sees it on the World page. A repository no world is written for yet says so: send `feedback` naming the AI to test, and the Cortad team writes one.
|
|
86
103
|
|
|
87
104
|
## Making it stick
|
|
88
105
|
|
|
@@ -35,15 +35,15 @@ Endpoints found in your code that have not answered yet (2):
|
|
|
35
35
|
POST /api/homework/explain apps/api/src/routes/homework.ts:18 Cortad's test request was answered with HTTP 500.
|
|
36
36
|
POST /api/progress/summary apps/api/src/routes/progress.ts:9 Needs a signed-in user.
|
|
37
37
|
Cortad sends each of them a test request.
|
|
38
|
-
|
|
38
|
+
A run plays 36 simulated users in about 6 minutes. About $0.38 on your OpenAI key.
|
|
39
39
|
A run starts when the person presses Run on the card in the browser or asks you for one; if they say they pressed it, call run rather than ask them again.
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
When the app keeps its data in a store
|
|
42
|
+
When the app keeps its data in a hosted store no copy was made of, the decision is the person's, said once as the last line before the link:
|
|
43
43
|
|
|
44
44
|
```
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
DATABASE_URL points at the Postgres database shop that is not on this machine, and no migrations were found to build a copy on this machine from, so test conversations would save into it. Point DATABASE_URL at a database on this machine, then run the connect command again. Or the person allows it on the card in the browser: one press lets test conversations save into it.
|
|
46
|
+
The person sees this at https://cortad.com/lab
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
Once a run is playing, what reading your code found and the run:
|
|
@@ -67,7 +67,7 @@ Conversations set aside:
|
|
|
67
67
|
POST /api/homework/upload: 7 conversations, on the app's side: the route needs a signed file URL, and no test account can make one
|
|
68
68
|
Latest run 8f2a1c4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b: running, 14 of 51 conversations played.
|
|
69
69
|
Production: not connected.
|
|
70
|
-
|
|
70
|
+
The person sees this at https://cortad.com/lab
|
|
71
71
|
next: run_status 8f2a1c4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b
|
|
72
72
|
```
|
|
73
73
|
|
|
@@ -131,7 +131,7 @@ The next run would play 58 conversations, 7 saved to test fixes, 5 new from the
|
|
|
131
131
|
The Pro plan, $99 a month, includes 10 runs.
|
|
132
132
|
Production: not connected.
|
|
133
133
|
Nothing ran.
|
|
134
|
-
|
|
134
|
+
Plans and checkout are at https://cortad.com/pricing?checkout=ship
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
## run_status
|
|
@@ -140,7 +140,7 @@ Playing. The call waited up to 45 seconds:
|
|
|
140
140
|
|
|
141
141
|
```
|
|
142
142
|
Run 8f2a1c4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b: running, 14 of 51 conversations played.
|
|
143
|
-
|
|
143
|
+
14 of 51 conversations done.
|
|
144
144
|
next: run_status 8f2a1c4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b
|
|
145
145
|
```
|
|
146
146
|
|
|
@@ -208,7 +208,7 @@ Connect production to see what your real users are doing as it happens and where
|
|
|
208
208
|
"Answer in the language the student writes in." (apps/api/src/agent/system.ts:12): failed in 2 of 26 conversations.
|
|
209
209
|
112 of 140 checks measured.
|
|
210
210
|
Free: this month's 1 run is used; 60 verify conversations left. Pro $99 a month: runs and reruns included, 100,000 production replies read.
|
|
211
|
-
|
|
211
|
+
The report is at https://cortad.com/lab
|
|
212
212
|
next: findings
|
|
213
213
|
```
|
|
214
214
|
|
|
@@ -219,7 +219,7 @@ A run after the first one plays what the files changed since the last run that p
|
|
|
219
219
|
```
|
|
220
220
|
Run 9a10b3d2-7c8d-4e9f-8a1b-2c3d4e5f6a7b: running, 9 of 34 conversations played.
|
|
221
221
|
Since run 8f2a1c4e, 1 file changed (apps/api/src/agent/prompt.ts), touching the prompt in apps/api/src/agent/prompt.ts. They reach POST /api/chat. This run replays the 22 conversations there from that run, so each pairs with its earlier self, and adds 12 new conversations written for the change on billing question, order tracking (5 of them open the way your production customers did). Left out: 7 conversations on POST /api/homework/upload, which nothing that changed reaches.
|
|
222
|
-
|
|
222
|
+
9 of 34 conversations done.
|
|
223
223
|
next: run_status 9a10b3d2-7c8d-4e9f-8a1b-2c3d4e5f6a7b
|
|
224
224
|
```
|
|
225
225
|
|
|
@@ -242,7 +242,7 @@ Replies took 2.9 s at the median and 9.8 s at the slowest, over 81 replies.
|
|
|
242
242
|
Nothing broke that only running your app could show.
|
|
243
243
|
The next run is compared with run 8f2a1c4e, the last run that played every conversation, with everything that changed since then in its scope.
|
|
244
244
|
Pro: 8 of 10 runs left this month; 560 verify conversations left.
|
|
245
|
-
|
|
245
|
+
The report is at https://cortad.com/lab
|
|
246
246
|
next: status
|
|
247
247
|
```
|
|
248
248
|
|
|
@@ -253,7 +253,7 @@ Run 8f2a1c4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b: finished, 11 of 51 conversations playe
|
|
|
253
253
|
1 finding.
|
|
254
254
|
Stopped at 11 of 51 conversations, on the app's side: your app stopped answering after 11 replies. Bring your app back up, then run again.
|
|
255
255
|
Fault on the app's side: Your code names llama-3.1-8b-instant, which api.groq.com does not serve. Rename the model in your code, then run again.
|
|
256
|
-
|
|
256
|
+
The report is at https://cortad.com/lab
|
|
257
257
|
next: findings
|
|
258
258
|
```
|
|
259
259
|
|
|
@@ -281,8 +281,8 @@ Verify 7c31e0aa-1b2c-4d3e-8f4a-5b6c7d8e9f0a: finished, 5 of 5 conversations play
|
|
|
281
281
|
Verify of finding:1 at apps/api/src/agent/prompt.ts:41.
|
|
282
282
|
The failure is gone on its own conversations: none of 3 replays failed, against 3 of 3 conversations in the run it was found in. On the conversations saved to test the fix the failure is gone: 3 of 8 failed before the fix, 0 of 8 after, a fall beyond chance.
|
|
283
283
|
Free: this month's 1 run is used; 55 verify conversations left. Pro $99 a month: runs and reruns included, 100,000 production replies read.
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
The failure in finding:1 is gone on its replays. Connecting production shows what real users are doing as it happens; field_connect has the steps.
|
|
285
|
+
The report is at https://cortad.com/lab
|
|
286
286
|
next: findings
|
|
287
287
|
```
|
|
288
288
|
|
|
@@ -303,7 +303,7 @@ The failure stayed. The conversations still fail more than the same question doe
|
|
|
303
303
|
Verify 7c31e0aa-1b2c-4d3e-8f4a-5b6c7d8e9f0a: finished, 4 of 4 conversations played.
|
|
304
304
|
Verify of finding:4 at apps/api/src/agent/system.ts:12.
|
|
305
305
|
The failure stayed: 4 of 4 replays failed, against 4 of 4 conversations in the run it was found in; the same question fails on 3 of 18 conversations elsewhere in your app, so these still stand out beyond chance. After the fix 4 conversations still failed: conversation 0b19a3f2 said "Sure! Let's solve this together." at reply 1, as it did before the fix; conversation 3e8d0c47 said "Sure! Let's solve this together." at reply 1, as it did before the fix; conversation a61f9b05 said "Sure! Let's solve this together." at reply 1, as it did before the fix; and 1 more.
|
|
306
|
-
|
|
306
|
+
The report is at https://cortad.com/lab
|
|
307
307
|
next: findings
|
|
308
308
|
```
|
|
309
309
|
|
|
@@ -313,7 +313,7 @@ Where the conversations saved to test the fix disagree with the finding's own, t
|
|
|
313
313
|
Verify 7c31e0aa-1b2c-4d3e-8f4a-5b6c7d8e9f0a: finished, 43 of 43 conversations played.
|
|
314
314
|
Verify of finding:5 at apps/api/src/agent/lessons.ts:58.
|
|
315
315
|
The failure stayed on its own conversations (3 of 35 failed, against 4 of 18 before) and is gone on the conversations saved to test the fix (3 of 8 failed before the fix, 0 of 8 after, beyond chance). On its own conversations that is not a fall beyond chance. After the fix 3 conversations still failed: conversation e4a1c9d2 said "I don't have this information about your homework plan." at reply 2, where before the fix it said "Let me look up your lesson plan."; conversation f0000000 said "I don't have this information." at reply 1; conversation f0000001 said "I don't have this information." at reply 1. The reason changed: in conversation e4a1c9d2 the reply declined to help, where before the fix the conversation ended without what they asked for.
|
|
316
|
-
|
|
316
|
+
The report is at https://cortad.com/lab
|
|
317
317
|
next: findings
|
|
318
318
|
```
|
|
319
319
|
|
|
@@ -323,7 +323,7 @@ Replies refused or failed on the replay come first. A refusal is not an answer,
|
|
|
323
323
|
Verify 7c31e0aa-1b2c-4d3e-8f4a-5b6c7d8e9f0a: finished, 5 of 5 conversations played.
|
|
324
324
|
Verify of finding:2 at backend/tools/refunds.py.
|
|
325
325
|
Your app refused 5 of 5 replays (HTTP 422), so they got no answer: the fix changed what the endpoint accepts. The failure stayed: 5 of 5 replays got no answer, against 5 of 5 conversations in the run it was found in; the same question fails on 2 of 16 conversations elsewhere in your app, so these still stand out beyond chance.
|
|
326
|
-
|
|
326
|
+
The report is at https://cortad.com/lab
|
|
327
327
|
next: findings
|
|
328
328
|
```
|
|
329
329
|
|
|
@@ -434,5 +434,5 @@ Production, last 30 days: 4,812 conversations, 4,790 read.
|
|
|
434
434
|
Rule checks passed: 93% of 61,204 (1,120 too close to call). Resolved 71%, frustrated 6%, asked for a human 2%, unanswered 4%.
|
|
435
435
|
Rules broken most: rule:answer-first (412), rule:language (188), rule:cite-source (97).
|
|
436
436
|
By journey: homework help 3,102 conversations, 94% passed; billing question 410 conversations, 88% passed.
|
|
437
|
-
|
|
437
|
+
The person sees this at https://cortad.com/lab#field
|
|
438
438
|
```
|